parser.c revision 1be6968d9d51f43fdb00535708a6fed0be6bfbca
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            x++;
87            state->ptr = x;
88            return T_NEWLINE;
89        case ' ':
90        case '\t':
91        case '\r':
92            x++;
93            continue;
94        case '#':
95            while (*x && (*x != '\n')) x++;
96            if (*x == '\n') {
97                state->ptr = x+1;
98                return T_NEWLINE;
99            } else {
100                state->ptr = x;
101                return T_EOF;
102            }
103        default:
104            goto text;
105        }
106    }
107
108textdone:
109    state->ptr = x;
110    *s = 0;
111    return T_TEXT;
112text:
113    state->text = s = x;
114textresume:
115    for (;;) {
116        switch (*x) {
117        case 0:
118            goto textdone;
119        case ' ':
120        case '\t':
121        case '\r':
122            x++;
123            goto textdone;
124        case '\n':
125            state->nexttoken = T_NEWLINE;
126            x++;
127            goto textdone;
128        case '"':
129            x++;
130            for (;;) {
131                switch (*x) {
132                case 0:
133                        /* unterminated quoted thing */
134                    state->ptr = x;
135                    return T_EOF;
136                case '"':
137                    x++;
138                    goto textresume;
139                default:
140                    *s++ = *x++;
141                }
142            }
143            break;
144        case '\\':
145            x++;
146            switch (*x) {
147            case 0:
148                goto textdone;
149            case 'n':
150                *s++ = '\n';
151                break;
152            case 'r':
153                *s++ = '\r';
154                break;
155            case 't':
156                *s++ = '\t';
157                break;
158            case '\\':
159                *s++ = '\\';
160                break;
161            case '\r':
162                    /* \ <cr> <lf> -> line continuation */
163                if (x[1] != '\n') {
164                    x++;
165                    continue;
166                }
167            case '\n':
168                    /* \ <lf> -> line continuation */
169                state->line++;
170                x++;
171                    /* eat any extra whitespace */
172                while((*x == ' ') || (*x == '\t')) x++;
173                continue;
174            default:
175                    /* unknown escape -- just copy */
176                *s++ = *x++;
177            }
178            continue;
179        default:
180            *s++ = *x++;
181        }
182    }
183    return T_EOF;
184}
185