summaryrefslogtreecommitdiff
path: root/command/echo.c
blob: 396a0f4fd47a047d81643a5f53a277494b7228c7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/**
 *  file: echo.c
 *  command: echo
 *  author: Tyler Murphy
 */

#include "command.h"
#include "lslib.h"

#include <stdlib.h>

/**
 * Flags that are to be used with echo
 */
static struct {
    bool escape_codes;
    bool newline;
} flags;

/**
 * Prints a null terminated string to standard out and changes each char based on input flags
 * @param str the string to print
 */
static void print_with_escape_codes(const char* str) {
    
    size_t index = 0; /* current index in the string */
    char c; /* current char being read */
    char n; /* next char being read */

    while (true) {
        c = str[index]; /* read current char */
        index++;

        if (c == '\0') break; /* if we hit the NUL, break */
        if (c != '\\') { /* if its not a escaped code, print and continue */
            putchar(c);
            continue;
        }

        /* read next character */
        n = str[index];
        index++;

        /* check each char against the valid escape codes */
        switch (n) {
            case '\\':
                putchar('\\');
                break;
            case 'b':
                putchar('\b');
                break;
            case 'c':
                exit(EXIT_SUCCESS);
            case 'n':
                putchar('\n');
                break;
            case 'r':
                putchar('\r');
                break;
            case 't':
                putchar('\t');
                break;
            case 'v':
                putchar('\v');
                break;
            default: /* if none found print both chars as is */
                putchar(c);
                putchar(n);
        }
    }
}

/** 
 * Takes in each argument that has a single - and parses it 
 * @param c the character after the -
 * @param next the next argument in argv that hasnt been parsed
 * @reutrn if the next arg was used or if the arg was invalid
 */
static int short_arg(char c, char* next) {
    UNUSED(next);
    switch (c) {
        case 'e':
            flags.escape_codes = true;
            break;
        case 'E':
            flags.escape_codes = false;
            break;
        case 'n':
            flags.newline = false;
            break;
        default:
            flags.newline = true;
            flags.escape_codes = false;
            return ARG_IGNORE;
    };
    return ARG_UNUSED;
}

/**
 * Prints data in each argument to stdout
 */
COMMAND(echo_main) {

    int start, i;

    /* if no arguments supplied exit */
    if (argc < 1) {
        return EXIT_FAILURE;
    }

    /* set default flags */
    flags.escape_codes = false;
    flags.newline = true;

    /* parse arguments, no help message */
    start = parse_args(argc, argv, NULL, short_arg, NULL);

    /* for each argument either print as is or parse each character for escape codes */
    for (i = start; i < argc; i++) {
         if (flags.escape_codes) {
            print_with_escape_codes(argv[i]);
        } else {
            printf("%s", argv[i]);
        }

        /* put a space seperator between arguments */
        if (i + 1 != argc) {
            putchar(' ');
        }
    } 

    /* if set to put a new line at the end (default), do so */
    if (flags.newline) {
        putchar('\n');
    }

    /* done */
    return EXIT_SUCCESS;
}