| 35 |
|
|
| 36 |
#include <err.h> |
#include <err.h> |
| 37 |
#include <errno.h> |
#include <errno.h> |
| 38 |
|
#include <stdarg.h> |
| 39 |
#include <stdint.h> |
#include <stdint.h> |
| 40 |
#include <stdio.h> |
#include <stdio.h> |
| 41 |
#include <stdlib.h> |
#include <stdlib.h> |
| 42 |
#include <string.h> |
#include <string.h> |
|
//#include <unistd.h> |
|
| 43 |
|
|
| 44 |
#include "nfotiser.h" |
#include "nfotiser.h" |
| 45 |
|
|
| 46 |
|
static void syntaxerr_(size_t, const char *, ...) |
| 47 |
|
__attribute__((format (printf, 2, 3))) |
| 48 |
|
__attribute__((noreturn)); |
| 49 |
|
#define syntaxerr(fmt, ...) syntaxerr_(lineno, (fmt), ##__VA_ARGS__) |
| 50 |
|
|
| 51 |
/* |
/* |
| 52 |
* Parsing works as follows: |
* Parsing works as follows: |
| 53 |
* |
* |
| 94 |
struct parser_res *entry; |
struct parser_res *entry; |
| 95 |
const struct parser_keywords *kwp; |
const struct parser_keywords *kwp; |
| 96 |
char *cp, *t, *tp, *buf, *buf_base; |
char *cp, *t, *tp, *buf, *buf_base; |
| 97 |
size_t len, n, lineno; |
size_t len, n, lineno = 0; |
| 98 |
struct stat sb; |
struct stat sb; |
| 99 |
char *entry_multi; |
char *entry_multi; |
| 100 |
unsigned entry_iter; |
unsigned entry_iter; |
| 122 |
|
|
| 123 |
/* now we can operate on the NUL-terminated R/W string “buf” */ |
/* now we can operate on the NUL-terminated R/W string “buf” */ |
| 124 |
if (buf[len - 1] != '\n') |
if (buf[len - 1] != '\n') |
| 125 |
errx(1, "syntax error: file does not end with a newline!"); |
syntaxerr("file does not end with a newline!"); |
| 126 |
|
|
| 127 |
D(2, "entire string: «%s» (%zu)\n", buf, strlen(buf)); |
D(2, "entire string: «%s» (%zu)\n", buf, strlen(buf)); |
| 128 |
lineno = 1; |
lineno = 1; |
| 157 |
if (*buf == '\t') { |
if (*buf == '\t') { |
| 158 |
D(2, "D: [%4zu] read trail line\n", lineno); |
D(2, "D: [%4zu] read trail line\n", lineno); |
| 159 |
if (cp == NULL) |
if (cp == NULL) |
| 160 |
errx(1, "syntax error: expected lead line," |
syntaxerr("expected lead line, got trail line!"); |
|
" got trail line!"); |
|
| 161 |
t = ++buf; |
t = ++buf; |
| 162 |
goto loop_storeline; |
goto loop_storeline; |
| 163 |
} else { |
} else { |
| 164 |
D(2, "D: [%4zu] read head line (%02X)\n", lineno, *buf); |
D(2, "D: [%4zu] read head line (%02X)\n", lineno, *buf); |
| 165 |
} |
} |
| 166 |
if (cp != NULL) |
if (cp != NULL) { |
| 167 |
|
--lineno; |
| 168 |
goto process_line; |
goto process_line; |
| 169 |
|
} |
| 170 |
if ((*buf >= 'A' && *buf <= 'Z') || |
if ((*buf >= 'A' && *buf <= 'Z') || |
| 171 |
(*buf >= 'a' && *buf <= 'z') || *buf == '_') |
(*buf >= 'a' && *buf <= 'z') || *buf == '_') |
| 172 |
t = buf; |
t = buf; |
| 173 |
else |
else |
| 174 |
errx(1, "syntax error: line must begin with" |
syntaxerr("line must begin with a letter or an underscore!"); |
|
" a letter or underscore!"); |
|
| 175 |
loop_storeline: |
loop_storeline: |
| 176 |
while (*t != '\n') |
while (*t++ != '\n') |
| 177 |
++t; |
; |
| 178 |
t = str_nsave(buf, t - buf + /* NL */ 1); |
t = str_nsave(buf, (tp = t) - buf); |
| 179 |
|
buf = tp; |
| 180 |
if (cp != NULL) { |
if (cp != NULL) { |
| 181 |
if (*(tp = cp + strlen(cp) - 2) == '\\') |
if (*(tp = cp + strlen(cp) - 2) == '\\') |
| 182 |
*tp = '\0'; |
*tp = '\0'; |
| 183 |
} |
} |
| 184 |
|
tp = t + strlen(t) - 1; |
| 185 |
|
*tp = '\0'; |
| 186 |
|
D(2, "D: [%4zu] storing string '%s'\n", lineno, t); |
| 187 |
|
*tp = '\n'; |
| 188 |
tp = str_add(cp, t); |
tp = str_add(cp, t); |
| 189 |
if (cp != NULL) |
if (cp != NULL) |
| 190 |
free(cp); |
free(cp); |
| 191 |
free(t); |
free(t); |
| 192 |
cp = tp; |
cp = tp; |
| 193 |
|
++lineno; |
| 194 |
goto loop_getline; |
goto loop_getline; |
| 195 |
process_line: |
process_line: |
| 196 |
/* cp points to <line>[<nl><line>…][\]<nl> */ |
/* cp points to <line>[<nl><line>…][\]<nl> */ |
| 197 |
/* buf points to first byte of next line */ |
/* buf points to first byte of next line */ |
| 198 |
if (*(tp = cp + strlen(cp) - 2) == '\\') |
if (*(tp = cp + strlen(cp) - 2) == '\\') |
| 199 |
errx(1, "syntax error: expected trail line," |
syntaxerr("expected trail line, got lead line!"); |
|
" got lead line!"); |
|
| 200 |
process_lastline: |
process_lastline: |
| 201 |
/* cut off final newline */ |
/* cut off final newline */ |
| 202 |
*++tp = '\0'; |
*++tp = '\0'; |
| 203 |
|
D(2, "D: [%4zu] processing «%s»\n", lineno, cp); |
| 204 |
|
|
| 205 |
/* parse the meat out of there */ |
/* parse the meat out of there */ |
| 206 |
if ((tp = strchr(cp, '\t')) == NULL) |
if ((tp = strchr(cp, '\t')) == NULL) |
| 207 |
errx(1, "syntax error: expected keyword +" |
syntaxerr("expected keyword + tab + value!"); |
|
" tab + value!"); |
|
| 208 |
*tp++ = '\0'; |
*tp++ = '\0'; |
| 209 |
/* cp points to keyword, tp points to value */ |
/* cp points to keyword, tp points to value */ |
| 210 |
entry_multi = NULL; |
entry_multi = NULL; |
| 234 |
while (*zp >= '0' && *zp <= '9') |
while (*zp >= '0' && *zp <= '9') |
| 235 |
++zp; |
++zp; |
| 236 |
if (zp == np) |
if (zp == np) |
| 237 |
errx(1, "syntax error: iterator expected"); |
syntaxerr("iterator expected"); |
| 238 |
if (*zp != (char)(kwp->kwtype == KWT_ITERATED ? |
if (*zp != (char)(kwp->kwtype == KWT_ITERATED ? |
| 239 |
'\0' : '_')) |
'\0' : '_')) |
| 240 |
errx(1, "syntax error: %s expected," |
syntaxerr("%s expected, got 0x%02X", |
| 241 |
" got 0x%02X", kwp->kwtype == KWT_ITERATED ? |
kwp->kwtype == KWT_ITERATED ? |
| 242 |
"tab" : "underscore", *zp); |
"tab" : "underscore", *zp); |
| 243 |
*zp++ = '\0'; |
*zp++ = '\0'; |
| 244 |
entry_iter = (unsigned)strtoul(np, NULL, 0); |
entry_iter = (unsigned)strtoul(np, NULL, 0); |
| 260 |
entry->value = str_save(tp); |
entry->value = str_save(tp); |
| 261 |
CIRCLEQ_INSERT_TAIL(res, entry, e); |
CIRCLEQ_INSERT_TAIL(res, entry, e); |
| 262 |
free(cp); |
free(cp); |
| 263 |
|
++lineno; |
| 264 |
goto loop_newline; |
goto loop_newline; |
| 265 |
loop_eof: |
loop_eof: |
| 266 |
if (cp != NULL) { |
if (cp != NULL) { |
| 267 |
if (*(tp = cp + strlen(cp) - 2) == '\\') |
if (*(tp = cp + strlen(cp) - 2) == '\\') |
| 268 |
errx(1, "syntax error: expected trail line," |
syntaxerr("expected trail line, read end of file!"); |
|
" read end of file!"); |
|
| 269 |
goto process_lastline; |
goto process_lastline; |
| 270 |
} |
} |
| 271 |
free(buf_base); |
free(buf_base); |
| 328 |
|
|
| 329 |
free(head); |
free(head); |
| 330 |
} |
} |
| 331 |
|
|
| 332 |
|
static void |
| 333 |
|
syntaxerr_(size_t lno, const char *fmt, ...) |
| 334 |
|
{ |
| 335 |
|
va_list args; |
| 336 |
|
|
| 337 |
|
va_start(args, fmt); |
| 338 |
|
fflush(NULL); |
| 339 |
|
fprintf(stderr, "syntax error [%4zu]: ", lno); |
| 340 |
|
fflush(NULL); |
| 341 |
|
verrx(1, fmt, args); |
| 342 |
|
va_end(args); |
| 343 |
|
} |