1#include <stdio.h>
2#include <stdarg.h>
3#include <string.h>
4
5#include "parser.h"
6#include "log.h"
7
8#define RAW(x...) log_write(6, x)
9
10void DUMP(void)
11{
12#if 0
13    struct service *svc;
14    struct action *act;
15    struct command *cmd;
16    struct listnode *node;
17    struct listnode *node2;
18    struct socketinfo *si;
19    int n;
20
21    list_for_each(node, &service_list) {
22        svc = node_to_item(node, struct service, slist);
23        RAW("service %s\n", svc->name);
24        RAW("  class '%s'\n", svc->classname);
25        RAW("  exec");
26        for (n = 0; n < svc->nargs; n++) {
27            RAW(" '%s'", svc->args[n]);
28        }
29        RAW("\n");
30        for (si = svc->sockets; si; si = si->next) {
31            RAW("  socket %s %s 0%o\n", si->name, si->type, si->perm);
32        }
33    }
34
35    list_for_each(node, &action_list) {
36        act = node_to_item(node, struct action, alist);
37        RAW("on %s\n", act->name);
38        list_for_each(node2, &act->commands) {
39            cmd = node_to_item(node2, struct command, clist);
40            RAW("  %p", cmd->func);
41            for (n = 0; n < cmd->nargs; n++) {
42                RAW(" %s", cmd->args[n]);
43            }
44            RAW("\n");
45        }
46        RAW("\n");
47    }
48#endif
49}
50
51void parse_error(struct parse_state *state, const char *fmt, ...)
52{
53    va_list ap;
54    char buf[128];
55    int off;
56
57    snprintf(buf, 128, "%s: %d: ", state->filename, state->line);
58    buf[127] = 0;
59    off = strlen(buf);
60
61    va_start(ap, fmt);
62    vsnprintf(buf + off, 128 - off, fmt, ap);
63    va_end(ap);
64    buf[127] = 0;
65    ERROR("%s", buf);
66}
67
68int next_token(struct parse_state *state)
69{
70    char *x = state->ptr;
71    char *s;
72
73    if (state->nexttoken) {
74        int t = state->nexttoken;
75        state->nexttoken = 0;
76        return t;
77    }
78
79    for (;;) {
80        switch (*x) {
81        case 0:
82            state->ptr = x;
83            return T_EOF;
84        case '\n':
85            x++;
86            state->ptr = x;
87            return T_NEWLINE;
88        case ' ':
89        case '\t':
90        case '\r':
91            x++;
92            continue;
93        case '#':
94            while (*x && (*x != '\n')) x++;
95            if (*x == '\n') {
96                state->ptr = x+1;
97                return T_NEWLINE;
98            } else {
99                state->ptr = x;
100                return T_EOF;
101            }
102        default:
103            goto text;
104        }
105    }
106
107textdone:
108    state->ptr = x;
109    *s = 0;
110    return T_TEXT;
111text:
112    state->text = s = x;
113textresume:
114    for (;;) {
115        switch (*x) {
116        case 0:
117            goto textdone;
118        case ' ':
119        case '\t':
120        case '\r':
121            x++;
122            goto textdone;
123        case '\n':
124            state->nexttoken = T_NEWLINE;
125            x++;
126            goto textdone;
127        case '"':
128            x++;
129            for (;;) {
130                switch (*x) {
131                case 0:
132                        /* unterminated quoted thing */
133                    state->ptr = x;
134                    return T_EOF;
135                case '"':
136                    x++;
137                    goto textresume;
138                default:
139                    *s++ = *x++;
140                }
141            }
142            break;
143        case '\\':
144            x++;
145            switch (*x) {
146            case 0:
147                goto textdone;
148            case 'n':
149                *s++ = '\n';
150                break;
151            case 'r':
152                *s++ = '\r';
153                break;
154            case 't':
155                *s++ = '\t';
156                break;
157            case '\\':
158                *s++ = '\\';
159                break;
160            case '\r':
161                    /* \ <cr> <lf> -> line continuation */
162                if (x[1] != '\n') {
163                    x++;
164                    continue;
165                }
166            case '\n':
167                    /* \ <lf> -> line continuation */
168                state->line++;
169                x++;
170                    /* eat any extra whitespace */
171                while((*x == ' ') || (*x == '\t')) x++;
172                continue;
173            default:
174                    /* unknown escape -- just copy */
175                *s++ = *x++;
176            }
177            continue;
178        default:
179            *s++ = *x++;
180        }
181    }
182    return T_EOF;
183}
184