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