Changeset 3455

Show
Ignore:
Timestamp:
08/09/07 15:10:50 (1 year ago)
Author:
tg
Message:

finish the parser (hopefully), add a dumper

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/common-nfo/tools/nfotiser/nfotiser.h

    r3445 r3455  
    5555const char *category(const char *); 
    5656/* parser.c */ 
    57 struct parser_result *nfo_parse(int fd, const struct parser_keywords *); 
     57struct parser_result *nfo_parse(int, const struct parser_keywords *); 
     58const struct parser_keywords *parser_getkwbynum(parser_kwords, 
     59    const struct parser_keywords *); 
     60void parser_dump(struct parser_res *, const struct parser_keywords *); 
    5861__END_DECLS 
    5962 
  • branches/common-nfo/tools/nfotiser/parser.c

    r3454 r3455  
    8888        struct parser_result *res; 
    8989        struct parser_res *entry; 
    90         char ch, *cp, *t, *buf, *buf_base; 
     90        const struct parser_keywords *kwp; 
     91        char ch, *cp, *t, *tp, *buf, *buf_base; 
    9192        size_t len, n; 
    9293        struct stat sb; 
     94        char *entry_multi; 
     95        unsigned entry_iter; 
    9396 
    9497        res = xmalloc(sizeof (struct parser_result)); 
     
    120123        /* get a line and add it to line buffer */ 
    121124        if (*buf == '\0') 
    122                 goto eof; 
     125                goto loop_eof; 
    123126        if (*buf == '\n') { 
    124127                ++buf; 
     
    135138                            " got trail line!"); 
    136139                t = ++buf; 
    137  loop_storeline: 
    138                 while (*t != '\n') 
    139                         ++t; 
    140                 t = str_nsave(buf, t - buf + /* NL */ 1); 
    141                 goto loop_addline; 
     140                goto loop_storeline; 
    142141        } 
    143142        if (cp != NULL) 
    144143                goto process_line; 
    145144        if ((*buf >= 'A' && *buf <= 'Z') || 
    146             (*buf >= 'a' && *buf <= 'z') || *buf == '_') { 
     145            (*buf >= 'a' && *buf <= 'z') || *buf == '_') 
    147146                t = buf; 
    148                 goto loop_storeline; 
    149         } 
    150         errx(1, "syntax error: line must begin with letter or underscore!"); 
     147        else 
     148                errx(1, "syntax error: line must begin with" 
     149                    " a letter or underscore!"); 
     150 loop_storeline: 
     151        while (*t != '\n') 
     152                ++t; 
     153        t = str_nsave(buf, t - buf + /* NL */ 1); 
    151154 loop_addline: 
     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 
     245const struct parser_keywords * 
     246parser_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 
     257void 
     258nfo_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}