systat - Fix initial pftop state
[dragonfly.git] / lib / libsys / genhooks / lex.c
1 /*
2  * Copyright (c) 2005 The DragonFly Project.  All rights reserved.
3  * 
4  * This code is derived from software contributed to The DragonFly Project
5  * by Matthew Dillon <dillon@backplane.com>
6  * 
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  * 3. Neither the name of The DragonFly Project nor the names of its
18  *    contributors may be used to endorse or promote products derived
19  *    from this software without specific, prior written permission.
20  * 
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
25  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  * 
34  * $DragonFly: src/lib/libsys/genhooks/lex.c,v 1.1 2005/05/08 18:14:56 dillon Exp $
35  */
36 /*
37  * LEX.C
38  *
39  * Lexical tokenizer for the parser.
40  */
41
42 #include "defs.h"
43
44 static int lex_keyword(const char *ptr, int len);
45
46 void
47 lex_open(const char *path, lex_token *tok)
48 {
49     struct stat st;
50     lex_info *lex;
51     int fd;
52
53     lex = zalloc(sizeof(*lex));
54     bzero(tok, sizeof(lex_token));
55     lex->fd = open(path, O_RDONLY);
56     if (lex->fd < 0) {
57         err(1, "unable to open %s", path);
58         /* not reached */
59     }
60     if (fstat(lex->fd, &st) < 0) {
61         err(1, "unable to stat %s", path);
62         /* not reached */
63     }
64     lex->path = strdup(path);
65     lex->size = st.st_size;
66     lex->base = mmap(NULL, lex->size, PROT_READ, MAP_SHARED, lex->fd, 0);
67     lex->cache_line = 1;
68     if (lex->base == MAP_FAILED) {
69         err(1, "unable to mmap %s", path);
70         /* not reached */
71     }
72
73     tok->info = lex;
74 }
75
76 void
77 lex_close(lex_token *tok)
78 {
79     lex_info *lex = tok->info;
80
81     assert(lex->fd >= 0);
82     close(lex->fd);
83     munmap((void *)lex->base, lex->size);
84     lex->fd = -1;
85     lex->base = NULL;
86     tok->info = NULL;
87     free(lex->path);
88     free(lex);
89 }
90
91 int
92 lex_gettoken(lex_token *tok)
93 {
94     lex_info *lex = tok->info;
95     int b = tok->index + tok->len;
96     int i = b;
97     char c;
98
99     tok->type = TOK_EOF;
100     while (i < lex->size) {
101         c = lex->base[i];
102
103         switch(c) {
104         case '\n':
105         case ' ':
106         case '\t':
107             ++b;
108             ++i;
109             break;
110         case '#':
111             while (i < lex->size && lex->base[i] != '\n')
112                 ++i;
113             b = i;
114             break;
115         case ';':
116         case ',':
117         case '(':
118         case ')':
119         case '{':
120         case '}':
121             ++i;
122             tok->type = c;
123             goto done;
124         default:
125             if (c >= '0' && c <= '9') {
126                 tok->type = TOK_INTEGER;
127                 tok->value = 0;
128                 while (i < lex->size) {
129                     c = lex->base[i];
130                     if (c < '0' || c > '9')
131                         break;
132                     tok->value = tok->value * 10 + (c - '0');
133                     ++i;
134                 }
135                 goto done;
136             }
137             if (c == '_' || isalpha(c)) {
138                 while (i < lex->size) {
139                     c = lex->base[i];
140                     if (c != '_' && isalnum(c) == 0)
141                         break;
142                     ++i;
143                 }
144                 tok->type = lex_keyword(lex->base + b, i - b);
145                 goto done;
146             }
147             tok->type = TOK_UNKNOWN;
148             ++i;
149             goto done;
150         }
151     }
152 done:
153     tok->index = b;
154     tok->sym = lex->base + b;
155     tok->len = i - b;
156     return(tok->type);
157 }
158
159 static int
160 lex_keyword(const char *ptr, int len)
161 {
162     if (len == 4 && strncasecmp(ptr, "base", 4) == 0)
163         return(TOK_BASE);
164     if (len == 3 && strncasecmp(ptr, "add", 3) == 0)
165         return(TOK_ADD);
166     if (len == 8 && strncasecmp(ptr, "function", 8) == 0)
167         return(TOK_FUNCTION);
168     if (len == 14 && strncasecmp(ptr, "implementation", 14) == 0)
169         return(TOK_IMPLEMENTATION);
170     if (len == 6 && strncasecmp(ptr, "direct", 6) == 0)
171         return(TOK_DIRECT);
172     if (len == 9 && strncasecmp(ptr, "simulated", 9) == 0)
173         return(TOK_SIMULATED);
174     return(TOK_SYMBOL);
175 }
176
177 const char *
178 lex_string_quick(lex_token *tok)
179 {
180     lex_info *lex = tok->info;
181     static char save_buf[64];
182     static char *save_str = save_buf;
183
184     if (save_str != save_buf)
185         free(save_str);
186     if (tok->len < sizeof(save_buf)) 
187         save_str = save_buf;
188     else
189         save_str = malloc(tok->len + 1);
190     bcopy(lex->base + tok->index, save_str, tok->len);
191     save_str[tok->len] = 0;
192     return(save_str);
193 }
194
195 char *
196 lex_string(lex_token *tok)
197 {
198     lex_info *lex = tok->info;
199     char *ptr;
200
201     ptr = malloc(tok->len + 1);
202     bcopy(lex->base + tok->index, ptr, tok->len);
203     ptr[tok->len] = 0;
204     return(ptr);
205 }
206
207 int
208 lex_skip_token(lex_token *tok, int type)
209 {
210     if (tok->type != type) {
211         if (type < 0x0100)
212             lex_error(tok, "Unexpected token, expected '%c'", type);
213         else
214             lex_error(tok, "Unexpected token");
215         exit(1);
216     }
217     return(lex_gettoken(tok));
218 }
219
220 void
221 lex_error(lex_token *tok, const char *ctl, ...)
222 {
223     lex_info *lex = tok->info;
224     va_list va;
225     int i;
226     int j;
227
228     /*
229      * Locate the line and line number containing the error
230      */
231     while (lex->cache_index > tok->index) {
232         --lex->cache_line;
233         for (i = lex->cache_index - 1; i > 0; --i) {
234             if (lex->base[i - 1] == '\n')
235                 break;
236         }
237         lex->cache_len = lex->cache_index - i;
238         lex->cache_index = i;
239     }
240     for (i = lex->cache_index; i <= lex->size; ++i) {
241         if (i == lex->size) {
242             lex->cache_len = i - lex->cache_index;
243             break;
244         }
245         if (lex->base[i] == '\n') {
246             if (tok->index <= i) {
247                 lex->cache_len = i + 1 - lex->cache_index;
248                 break;
249             }
250             lex->cache_index = i + 1;
251             ++lex->cache_line;
252         }
253     }
254
255     /*
256      * Pretty print.
257      */
258     fprintf(stderr, "line %d of %s, ", lex->cache_line, lex->path);
259     va_start(va, ctl);
260     vfprintf(stderr, ctl, va);
261     va_end(va);
262     fprintf(stderr, ":\n");
263
264     i = tok->index - lex->cache_index;
265     j = (lex->cache_index + lex->cache_len) - (tok->index + tok->len); 
266     fprintf(stderr, "%*.*s", i, i, lex->base + lex->cache_index);
267     fprintf(stderr, "\033[7m%*.*s\033[0m", tok->len, tok->len, lex->base + tok->index);
268     fprintf(stderr, "%*.*s", j, j, lex->base + tok->index + tok->len);
269 }
270