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
);