| | 155 | if (cp != NULL) { |
|---|
| | 156 | if (*(tp = cp + strlen(cp) - 2) == '\\') |
|---|
| | 157 | *tp = '\0'; |
|---|
| | 158 | } |
|---|
| | 159 | tp = str_add(cp, t); |
|---|
| | 160 | if (cp != NULL) |
|---|
| | 161 | free(cp); |
|---|
| | 162 | free(t); |
|---|
| | 163 | cp = tp; |
|---|
| | 164 | goto loop_getline; |
|---|
| | 165 | process_line: |
|---|
| | 166 | /* cp points to <line>[<nl><line>…][\]<nl> */ |
|---|
| | 167 | /* buf points to first byte of next line */ |
|---|
| | 168 | if (*(tp = cp + strlen(cp) - 2) == '\\') |
|---|
| | 169 | errx(1, "syntax error: expected trail line," |
|---|
| | 170 | " got lead line!"); |
|---|
| | 171 | process_lastline: |
|---|
| | 172 | /* cut off final newline */ |
|---|
| | 173 | *++tp = '\0'; |
|---|
| | 174 | |
|---|
| | 175 | /* parse the meat out of there */ |
|---|
| | 176 | if ((tp = strchr(cp, '\t')) == NULL) |
|---|
| | 177 | errx(1, "syntax error: expected keyword +" |
|---|
| | 178 | " tab + value!"); |
|---|
| | 179 | *tp++ = '\0'; |
|---|
| | 180 | /* cp points to keyword, tp points to value */ |
|---|
| | 181 | entry_multi = NULL; |
|---|
| | 182 | entry_iter = 0; |
|---|
| | 183 | for (kwp = kws; kwp->kwprefix != NULL; ++kwp) { |
|---|
| | 184 | char *np; |
|---|
| | 185 | |
|---|
| | 186 | /* exact match? */ |
|---|
| | 187 | if (!strcasecmp(cp, kwp->kwprefix)) |
|---|
| | 188 | /* yepp */ break; |
|---|
| | 189 | /* prefix match allowed? */ |
|---|
| | 190 | if (kwp->kwtype == KWT_NORMAL) |
|---|
| | 191 | /* nope */ continue; |
|---|
| | 192 | /* prefix match? */ |
|---|
| | 193 | if (strncasecmp(cp, kwp->kwprefix, n = strlen(kwp->kwprefix))) |
|---|
| | 194 | /* nope */ continue; |
|---|
| | 195 | if (cp[n] != '_') |
|---|
| | 196 | /* same */ continue; |
|---|
| | 197 | /* okay, we got a prefix match, get args */ |
|---|
| | 198 | np = cp + n + 1; |
|---|
| | 199 | if (kwp->kwtype == KWT_ITERATED || |
|---|
| | 200 | kwp->kwtype == KWT_MULTITER) { |
|---|
| | 201 | char *zp = np; |
|---|
| | 202 | |
|---|
| | 203 | if (zp[0] == '0' && (zp[1] == 'x' || zp[1] == 'X')) |
|---|
| | 204 | zp += 2; |
|---|
| | 205 | while (*zp >= '0' && *zp <= '9') |
|---|
| | 206 | ++zp; |
|---|
| | 207 | if (zp == np) |
|---|
| | 208 | errx(1, "syntax error: iterator expected"); |
|---|
| | 209 | if (*zp != kwp->kwtype == KWT_ITERATED ? '\0' : '_') |
|---|
| | 210 | errx(1, "syntax error: %s expected," |
|---|
| | 211 | " got 0x%02X", kwp->kwtype == KWT_ITERATED ? |
|---|
| | 212 | "tab" : "underscore", *zp); |
|---|
| | 213 | *zp++ = '\0'; |
|---|
| | 214 | entry_iter = (unsigned)strtoul(np, NULL, 0); |
|---|
| | 215 | np = zp; |
|---|
| | 216 | } |
|---|
| | 217 | if (kwp->kwtype == KWT_MULTI || |
|---|
| | 218 | kwp->kwtype == KWT_MULTITER) |
|---|
| | 219 | entry_multi = str_save(np); |
|---|
| | 220 | /* values filled out */ |
|---|
| | 221 | break; |
|---|
| | 222 | } |
|---|
| | 223 | if (kwp->kwprefix == NULL) |
|---|
| | 224 | errx(1, "unknown keyword '%s'", cp); |
|---|
| | 225 | entry = xmalloc(sizeof (struct parser_res)); |
|---|
| | 226 | bzero(entry, sizeof (struct parser_res)); |
|---|
| | 227 | entry->keyword = kwp->kwnum; |
|---|
| | 228 | entry->kw_multi = entry_multi; |
|---|
| | 229 | entry->kw_iter = entry_iter; |
|---|
| | 230 | entry->value = str_save(tp); |
|---|
| | 231 | CIRCLEQ_INSERT_TAIL(res, entry, e); |
|---|
| | 232 | free(cp); |
|---|
| | 233 | goto loop_newline; |
|---|
| | 234 | loop_eof: |
|---|
| | 235 | if (cp != NULL) { |
|---|
| | 236 | if (*(tp = cp + strlen(cp) - 2) == '\\') |
|---|
| | 237 | errx(1, "syntax error: expected trail line," |
|---|
| | 238 | " read end of file!"); |
|---|
| | 239 | goto process_lastline; |
|---|
| | 240 | } |
|---|
| | 241 | free(buf_base); |
|---|
| | 242 | return (res); |
|---|
| | 243 | } |
|---|
| | 244 | |
|---|
| | 245 | const struct parser_keywords * |
|---|
| | 246 | parser_getkwbynum(parser_kwords num, const struct parser_keywords *kws) |
|---|
| | 247 | { |
|---|
| | 248 | const struct parser_keywords *kwp; |
|---|
| | 249 | |
|---|
| | 250 | for (kwp = kws; kwp->kwprefix != NULL; ++kwp) |
|---|
| | 251 | if (kwp->kwnum == num) |
|---|
| | 252 | break; |
|---|
| | 253 | |
|---|
| | 254 | return (kwp->kwprefix == NULL ? NULL : kwp); |
|---|
| | 255 | } |
|---|
| | 256 | |
|---|
| | 257 | void |
|---|
| | 258 | nfo_parser_dump(struct parser_res *entry, const struct parser_keywords *kws) |
|---|
| | 259 | { |
|---|
| | 260 | const struct parser_keywords *kwp; |
|---|
| | 261 | |
|---|
| | 262 | printf("keyword %s (type %s)", |
|---|
| | 263 | (kwp = parser_getkwbynum(entry->keyword, kws)) == NULL ? |
|---|
| | 264 | "<unknown>" : kwp->kwprefix, |
|---|
| | 265 | kwp == NULL ? "invalid" : |
|---|
| | 266 | kwp->kwtype == KWT_NORMAL ? "normal" : |
|---|
| | 267 | kwp->kwtype == KWT_MULTI ? "multi" : |
|---|
| | 268 | kwp->kwtype == KWT_ITERATED ? "iterated" : |
|---|
| | 269 | kwp->kwtype == KWT_MULTITER ? "multiter" : "unknown"); |
|---|
| | 270 | if (kwp) { |
|---|
| | 271 | if (kwp->kwtype == KWT_ITERATED || |
|---|
| | 272 | kwp->kwtype == KWT_MULTITER) |
|---|
| | 273 | printf(", iterator %u", entry->kw_iter); |
|---|
| | 274 | if (kwp->kwtype == KWT_MULTI || |
|---|
| | 275 | kwp->kwtype == KWT_MULTITER) |
|---|
| | 276 | printf(", multival '%s'", entry->kw_multi); |
|---|
| | 277 | } |
|---|
| | 278 | putchar('\n'); |
|---|
| | 279 | } |
|---|