HAMMER 60I/Many: Mirroring
[dragonfly.git] / lib / libsys / genhooks / lex.c
blob15c04a705ce17ba7154aefca0b9da6d12608802e
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:
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.
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.
34 * $DragonFly: src/lib/libsys/genhooks/lex.c,v 1.1 2005/05/08 18:14:56 dillon Exp $
37 * LEX.C
39 * Lexical tokenizer for the parser.
42 #include "defs.h"
44 static int lex_keyword(const char *ptr, int len);
46 void
47 lex_open(const char *path, lex_token *tok)
49 struct stat st;
50 lex_info *lex;
51 int fd;
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 */
60 if (fstat(lex->fd, &st) < 0) {
61 err(1, "unable to stat %s", path);
62 /* not reached */
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 */
73 tok->info = lex;
76 void
77 lex_close(lex_token *tok)
79 lex_info *lex = tok->info;
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);
91 int
92 lex_gettoken(lex_token *tok)
94 lex_info *lex = tok->info;
95 int b = tok->index + tok->len;
96 int i = b;
97 char c;
99 tok->type = TOK_EOF;
100 while (i < lex->size) {
101 c = lex->base[i];
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;
135 goto done;
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;
144 tok->type = lex_keyword(lex->base + b, i - b);
145 goto done;
147 tok->type = TOK_UNKNOWN;
148 ++i;
149 goto done;
152 done:
153 tok->index = b;
154 tok->sym = lex->base + b;
155 tok->len = i - b;
156 return(tok->type);
159 static int
160 lex_keyword(const char *ptr, int len)
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);
177 const char *
178 lex_string_quick(lex_token *tok)
180 lex_info *lex = tok->info;
181 static char save_buf[64];
182 static char *save_str = save_buf;
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);
195 char *
196 lex_string(lex_token *tok)
198 lex_info *lex = tok->info;
199 char *ptr;
201 ptr = malloc(tok->len + 1);
202 bcopy(lex->base + tok->index, ptr, tok->len);
203 ptr[tok->len] = 0;
204 return(ptr);
208 lex_skip_token(lex_token *tok, int type)
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);
217 return(lex_gettoken(tok));
220 void
221 lex_error(lex_token *tok, const char *ctl, ...)
223 lex_info *lex = tok->info;
224 va_list va;
225 int i;
226 int j;
229 * Locate the line and line number containing the error
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;
237 lex->cache_len = lex->cache_index - i;
238 lex->cache_index = i;
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;
245 if (lex->base[i] == '\n') {
246 if (tok->index <= i) {
247 lex->cache_len = i + 1 - lex->cache_index;
248 break;
250 lex->cache_index = i + 1;
251 ++lex->cache_line;
256 * Pretty print.
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");
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);