parser.cpp revision f3cf438714aa1284d8a58e2f3b108ba93f6d3abb
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    char name_str[256] = "";
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 ");
39        build_triggers_string(name_str, sizeof(name_str), act);
40        RAW("%s", name_str);
41        RAW("\n");
42
43        list_for_each(node2, &act->commands) {
44            cmd = node_to_item(node2, struct command, clist);
45            RAW("  %p", cmd->func);
46            for (n = 0; n < cmd->nargs; n++) {
47                RAW(" %s", cmd->args[n]);
48            }
49            RAW("\n");
50        }
51        RAW("\n");
52    }
53#endif
54}
55
56void parse_error(struct parse_state *state, const char *fmt, ...)
57{
58    va_list ap;
59    char buf[128];
60    int off;
61
62    snprintf(buf, 128, "%s: %d: ", state->filename, state->line);
63    buf[127] = 0;
64    off = strlen(buf);
65
66    va_start(ap, fmt);
67    vsnprintf(buf + off, 128 - off, fmt, ap);
68    va_end(ap);
69    buf[127] = 0;
70    ERROR("%s", buf);
71}
72
73int next_token(struct parse_state *state)
74{
75    char *x = state->ptr;
76    char *s;
77
78    if (state->nexttoken) {
79        int t = state->nexttoken;
80        state->nexttoken = 0;
81        return t;
82    }
83
84    for (;;) {
85        switch (*x) {
86        case 0:
87            state->ptr = x;
88            return T_EOF;
89        case '\n':
90            x++;
91            state->ptr = x;
92            return T_NEWLINE;
93        case ' ':
94        case '\t':
95        case '\r':
96            x++;
97            continue;
98        case '#':
99            while (*x && (*x != '\n')) x++;
100            if (*x == '\n') {
101                state->ptr = x+1;
102                return T_NEWLINE;
103            } else {
104                state->ptr = x;
105                return T_EOF;
106            }
107        default:
108            goto text;
109        }
110    }
111
112textdone:
113    state->ptr = x;
114    *s = 0;
115    return T_TEXT;
116text:
117    state->text = s = x;
118textresume:
119    for (;;) {
120        switch (*x) {
121        case 0:
122            goto textdone;
123        case ' ':
124        case '\t':
125        case '\r':
126            x++;
127            goto textdone;
128        case '\n':
129            state->nexttoken = T_NEWLINE;
130            x++;
131            goto textdone;
132        case '"':
133            x++;
134            for (;;) {
135                switch (*x) {
136                case 0:
137                        /* unterminated quoted thing */
138                    state->ptr = x;
139                    return T_EOF;
140                case '"':
141                    x++;
142                    goto textresume;
143                default:
144                    *s++ = *x++;
145                }
146            }
147            break;
148        case '\\':
149            x++;
150            switch (*x) {
151            case 0:
152                goto textdone;
153            case 'n':
154                *s++ = '\n';
155                break;
156            case 'r':
157                *s++ = '\r';
158                break;
159            case 't':
160                *s++ = '\t';
161                break;
162            case '\\':
163                *s++ = '\\';
164                break;
165            case '\r':
166                    /* \ <cr> <lf> -> line continuation */
167                if (x[1] != '\n') {
168                    x++;
169                    continue;
170                }
171            case '\n':
172                    /* \ <lf> -> line continuation */
173                state->line++;
174                x++;
175                    /* eat any extra whitespace */
176                while((*x == ' ') || (*x == '\t')) x++;
177                continue;
178            default:
179                    /* unknown escape -- just copy */
180                *s++ = *x++;
181            }
182            continue;
183        default:
184            *s++ = *x++;
185        }
186    }
187    return T_EOF;
188}
189