2 * Copyright (c) 2005 The DragonFly Project. All rights reserved.
4 * This code is derived from software contributed to The DragonFly Project
5 * by Matthew Dillon <dillon@backplane.com>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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
34 * $DragonFly: src/lib/libsys/genhooks/lex.c,v 1.1 2005/05/08 18:14:56 dillon Exp $
39 * Lexical tokenizer for the parser.
44 static int lex_keyword(const char *ptr, int len);
47 lex_open(const char *path, lex_token *tok)
53 lex = zalloc(sizeof(*lex));
54 bzero(tok, sizeof(lex_token));
55 lex->fd = open(path, O_RDONLY);
57 err(1, "unable to open %s", path);
60 if (fstat(lex->fd, &st) < 0) {
61 err(1, "unable to stat %s", path);
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);
68 if (lex->base == MAP_FAILED) {
69 err(1, "unable to mmap %s", path);
77 lex_close(lex_token *tok)
79 lex_info *lex = tok->info;
83 munmap((void *)lex->base, lex->size);
92 lex_gettoken(lex_token *tok)
94 lex_info *lex = tok->info;
95 int b = tok->index + tok->len;
100 while (i < lex->size) {
111 while (i < lex->size && lex->base[i] != '\n')
125 if (c >= '0' && c <= '9') {
126 tok->type = TOK_INTEGER;
128 while (i < lex->size) {
130 if (c < '0' || c > '9')
132 tok->value = tok->value * 10 + (c - '0');
137 if (c == '_' || isalpha(c)) {
138 while (i < lex->size) {
140 if (c != '_' && isalnum(c) == 0)
144 tok->type = lex_keyword(lex->base + b, i - b);
147 tok->type = TOK_UNKNOWN;
154 tok->sym = lex->base + b;
160 lex_keyword(const char *ptr, int len)
162 if (len == 4 && strncasecmp(ptr, "base", 4) == 0)
164 if (len == 3 && strncasecmp(ptr, "add", 3) == 0)
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)
172 if (len == 9 && strncasecmp(ptr, "simulated", 9) == 0)
173 return(TOK_SIMULATED);
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)
186 if (tok->len < sizeof(save_buf))
189 save_str = malloc(tok->len + 1);
190 bcopy(lex->base + tok->index, save_str, tok->len);
191 save_str[tok->len] = 0;
196 lex_string(lex_token *tok)
198 lex_info *lex = tok->info;
201 ptr = malloc(tok->len + 1);
202 bcopy(lex->base + tok->index, ptr, tok->len);
208 lex_skip_token(lex_token *tok, int type)
210 if (tok->type != type) {
212 lex_error(tok, "Unexpected token, expected '%c'", type);
214 lex_error(tok, "Unexpected token");
217 return(lex_gettoken(tok));
221 lex_error(lex_token *tok, const char *ctl, ...)
223 lex_info *lex = tok->info;
229 * Locate the line and line number containing the error
231 while (lex->cache_index > tok->index) {
233 for (i = lex->cache_index - 1; i > 0; --i) {
234 if (lex->base[i - 1] == '\n')
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;
245 if (lex->base[i] == '\n') {
246 if (tok->index <= i) {
247 lex->cache_len = i + 1 - lex->cache_index;
250 lex->cache_index = i + 1;
258 fprintf(stderr, "line %d of %s, ", lex->cache_line, lex->path);
260 vfprintf(stderr, ctl, 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);