1 /** A pretty generic scanner
13 #include "util/error.h"
14 #include "util/scanner.h"
15 #include "util/string.h"
19 map_scanner_string(struct scanner
*scanner
,
20 const unsigned char *ident
, const unsigned char *end
,
23 const struct scanner_string_mapping
*mappings
= scanner
->info
->mappings
;
24 int length
= end
- ident
;
26 for (; mappings
->name
; mappings
++) {
27 if (mappings
->base_type
== base_type
28 && !c_strlcasecmp(mappings
->name
, -1, ident
, length
))
29 return mappings
->type
;
36 struct scanner_token
*
37 skip_scanner_tokens(struct scanner
*scanner
, int skipto
, int precedence
)
39 struct scanner_token
*token
= get_scanner_token(scanner
);
41 /* Skip tokens while handling some basic precedens of special chars
42 * so we don't skip to long. */
44 if (token
->type
== skipto
45 || token
->precedence
> precedence
)
47 token
= get_next_scanner_token(scanner
);
50 return (token
&& token
->type
== skipto
)
51 ? get_next_scanner_token(scanner
) : NULL
;
56 dump_scanner(struct scanner
*scanner
)
58 unsigned char buffer
[MAX_STR_LEN
];
59 struct scanner_token
*token
= scanner
->current
;
60 struct scanner_token
*table_end
= scanner
->table
+ scanner
->tokens
;
61 unsigned char *srcpos
= token
->string
, *bufpos
= buffer
;
62 int src_lookahead
= 50;
63 int token_lookahead
= 4;
66 if (!scanner_has_tokens(scanner
)) return;
68 memset(buffer
, 0, MAX_STR_LEN
);
69 for (; token_lookahead
> 0 && token
< table_end
; token
++, token_lookahead
--) {
70 int buflen
= MAX_STR_LEN
- (bufpos
- buffer
);
71 int added
= snprintf(bufpos
, buflen
, "[%.*s] ", token
->length
, token
->string
);
76 if (scanner
->tokens
> token_lookahead
) {
77 memcpy(bufpos
, "... ", 4);
81 srclen
= strlen(srcpos
);
82 int_upper_bound(&src_lookahead
, srclen
);
85 /* Compress the lookahead string */
86 for (; src_lookahead
> 0; src_lookahead
--, srcpos
++, bufpos
++) {
87 if (*srcpos
== '\n' || *srcpos
== '\r' || *srcpos
== '\t') {
89 *bufpos
= *srcpos
== '\n' ? 'n'
90 : (*srcpos
== '\r' ? 'r' : 't');
96 if (srclen
> src_lookahead
)
97 memcpy(bufpos
, "...]", 4);
99 memcpy(bufpos
, "]", 2);
101 errfile
= scanner
->file
, errline
= scanner
->line
;
102 elinks_wdebug("%s", buffer
);
105 struct scanner_token
*
106 get_scanner_token_debug(struct scanner
*scanner
)
108 if (!scanner_has_tokens(scanner
)) return NULL
;
110 dump_scanner(scanner
);
112 /* Make sure we do not return invalid tokens */
113 assert(!scanner_has_tokens(scanner
)
114 || scanner
->current
->type
!= 0);
116 return get_scanner_token(scanner
);
121 /** @name Initializers
125 init_scanner_info(struct scanner_info
*scanner_info
)
127 const struct scan_table_info
*info
= scanner_info
->scan_table_info
;
128 int *scan_table
= scanner_info
->scan_table
;
133 for (i
= 0; info
[i
].type
!= SCAN_END
; i
++) {
134 const union scan_table_data
*data
= &info
[i
].data
;
136 if (info
[i
].type
== SCAN_RANGE
) {
137 int index
= *data
->range
.start
;
140 assert(data
->range
.end
< SCAN_TABLE_SIZE
);
141 assert(index
<= data
->range
.end
);
143 for (; index
<= data
->range
.end
; index
++)
144 scan_table
[index
] |= info
[i
].bits
;
147 unsigned char *string
= info
[i
].data
.string
.source
;
148 int pos
= info
[i
].data
.string
.length
- 1;
150 assert(info
[i
].type
== SCAN_STRING
&& pos
>= 0);
152 for (; pos
>= 0; pos
--)
153 scan_table
[string
[pos
]] |= info
[i
].bits
;
159 init_scanner(struct scanner
*scanner
, struct scanner_info
*scanner_info
,
160 const unsigned char *string
, const unsigned char *end
)
162 if (!scanner_info
->initialized
) {
163 init_scanner_info(scanner_info
);
164 scanner_info
->initialized
= 1;
167 memset(scanner
, 0, sizeof(*scanner
));
169 scanner
->string
= string
;
170 scanner
->position
= string
;
171 scanner
->end
= end
? end
: string
+ strlen(string
);
172 scanner
->current
= scanner
->table
;
173 scanner
->info
= scanner_info
;
174 scanner
->info
->scan(scanner
);