| 89 |
struct parser_res *entry; |
struct parser_res *entry; |
| 90 |
const struct parser_keywords *kwp; |
const struct parser_keywords *kwp; |
| 91 |
char *cp, *t, *tp, *buf, *buf_base; |
char *cp, *t, *tp, *buf, *buf_base; |
| 92 |
size_t len, n; |
size_t len, n, lineno; |
| 93 |
struct stat sb; |
struct stat sb; |
| 94 |
char *entry_multi; |
char *entry_multi; |
| 95 |
unsigned entry_iter; |
unsigned entry_iter; |
| 101 |
err(255, "cannot stat"); |
err(255, "cannot stat"); |
| 102 |
|
|
| 103 |
/* slurp whole file into mapped memory */ |
/* slurp whole file into mapped memory */ |
| 104 |
if ((cp = mmap(NULL, (len = sb.st_size), PROT_READ, MAP_FILE, fd, 0)) |
len = sb.st_size; |
| 105 |
== MAP_FAILED) |
D(2, "trying to mmap %zu bytes...", len); |
| 106 |
|
if ((cp = mmap(NULL, len, PROT_READ, MAP_FILE, fd, 0)) == MAP_FAILED) |
| 107 |
err(255, "cannot mmap %zu bytes", len); |
err(255, "cannot mmap %zu bytes", len); |
| 108 |
|
D(2, "ok\n"); |
| 109 |
/* make a nice NUL-terminated copy (malloc'd) */ |
/* make a nice NUL-terminated copy (malloc'd) */ |
| 110 |
|
D(2, "copying %zu bytes...", len); |
| 111 |
buf = buf_base = str_nsave(cp, len); |
buf = buf_base = str_nsave(cp, len); |
| 112 |
|
D(2, " munmap..."); |
| 113 |
if (munmap(cp, len)) |
if (munmap(cp, len)) |
| 114 |
err(255, "cannot munmap"); |
err(255, "cannot munmap"); |
| 115 |
|
D(2, "ok\n"); |
| 116 |
/* don't need the file any more */ |
/* don't need the file any more */ |
| 117 |
|
|
| 118 |
/* now we can operate on the NUL-terminated R/W string “buf” */ |
/* now we can operate on the NUL-terminated R/W string “buf” */ |
| 119 |
if (buf[len - 1] != '\n') |
if (buf[len - 1] != '\n') |
| 120 |
errx(1, "syntax error: file does not end with a newline!"); |
errx(1, "syntax error: file does not end with a newline!"); |
| 121 |
|
|
| 122 |
|
D(2, "entire string: «%s» (%zu)\n", buf, strlen(buf)); |
| 123 |
|
lineno = 1; |
| 124 |
|
|
| 125 |
loop_newline: |
loop_newline: |
| 126 |
/* completely new line buffer */ |
/* completely new line buffer */ |
| 127 |
cp = NULL; |
cp = NULL; |
| 128 |
|
|
| 129 |
loop_getline: |
loop_getline: |
| 130 |
/* get a line and add it to line buffer */ |
/* get a line and add it to line buffer */ |
| 131 |
if (*buf == '\0') |
if (*buf == '\0') { |
| 132 |
|
D(2, "D: [%4zu] read EOF\n", lineno); |
| 133 |
goto loop_eof; |
goto loop_eof; |
| 134 |
|
} |
| 135 |
if (*buf == '\n') { |
if (*buf == '\n') { |
| 136 |
|
D(2, "D: [%4zu] read newline\n", lineno); |
| 137 |
++buf; |
++buf; |
| 138 |
|
++lineno; |
| 139 |
goto loop_getline; |
goto loop_getline; |
| 140 |
} |
} |
| 141 |
if (*buf == '#') { |
if (*buf == '#') { |
| 142 |
while (*buf != '\n') |
D(2, "D: [%4zu] read comment ", lineno); |
| 143 |
++buf; |
t = buf; |
| 144 |
|
while (*t != '\n') |
| 145 |
|
++t; |
| 146 |
|
*t++ = '\0'; |
| 147 |
|
D(2, "'%s'\n", buf); |
| 148 |
|
buf = t; |
| 149 |
|
++lineno; |
| 150 |
goto loop_getline; |
goto loop_getline; |
| 151 |
} |
} |
| 152 |
if (*buf == '\t') { |
if (*buf == '\t') { |
| 153 |
|
D(2, "D: [%4zu] read trail line\n", lineno); |
| 154 |
if (cp == NULL) |
if (cp == NULL) |
| 155 |
errx(1, "syntax error: expected lead line," |
errx(1, "syntax error: expected lead line," |
| 156 |
" got trail line!"); |
" got trail line!"); |
| 157 |
t = ++buf; |
t = ++buf; |
| 158 |
goto loop_storeline; |
goto loop_storeline; |
| 159 |
|
} else { |
| 160 |
|
D(2, "D: [%4zu] read head line (%02X)\n", lineno, *buf); |
| 161 |
} |
} |
| 162 |
if (cp != NULL) |
if (cp != NULL) |
| 163 |
goto process_line; |
goto process_line; |