Retry only for https protocol
[elinks.git] / src / util / scanner.c
blobc0840099b991811573b2f986407fec601ee2cfe3
1 /** A pretty generic scanner
2 * @file */
4 #ifdef HAVE_CONFIG_H
5 #include "config.h"
6 #endif
8 #include <stdio.h>
9 #include <string.h>
11 #include "elinks.h"
13 #include "util/error.h"
14 #include "util/scanner.h"
15 #include "util/string.h"
18 int
19 map_scanner_string(struct scanner *scanner,
20 const unsigned char *ident, const unsigned char *end,
21 int base_type)
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;
32 return base_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. */
43 while (token) {
44 if (token->type == skipto
45 || token->precedence > precedence)
46 break;
47 token = get_next_scanner_token(scanner);
50 return (token && token->type == skipto)
51 ? get_next_scanner_token(scanner) : NULL;
54 #ifdef DEBUG_SCANNER
55 void
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;
64 int srclen;
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);
73 bufpos += added;
76 if (scanner->tokens > token_lookahead) {
77 memcpy(bufpos, "... ", 4);
78 bufpos += 4;
81 srclen = strlen(srcpos);
82 int_upper_bound(&src_lookahead, srclen);
83 *bufpos++ = '[';
85 /* Compress the lookahead string */
86 for (; src_lookahead > 0; src_lookahead--, srcpos++, bufpos++) {
87 if (*srcpos == '\n' || *srcpos == '\r' || *srcpos == '\t') {
88 *bufpos++ = '\\';
89 *bufpos = *srcpos == '\n' ? 'n'
90 : (*srcpos == '\r' ? 'r' : 't');
91 } else {
92 *bufpos = *srcpos;
96 if (srclen > src_lookahead)
97 memcpy(bufpos, "...]", 4);
98 else
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);
118 #endif
121 /** @name Initializers
122 * @{ */
124 static inline void
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;
129 int i;
131 if (!info) return;
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;
139 assert(index > 0);
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;
146 } else {
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;
158 void
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);
177 /** @} */