| 481 | /* tok822_parse_limit - translate external string to token tree */ |
| 482 | |
| 483 | TOK822 *tok822_parse_limit(const char *str, int tok_count_limit) |
| 484 | { |
| 485 | TOK822 *head; |
| 486 | TOK822 *tail; |
| 487 | TOK822 *right; |
| 488 | TOK822 *first_token; |
| 489 | TOK822 *last_token; |
| 490 | TOK822 *tp; |
| 491 | int state; |
| 492 | |
| 493 | /* |
| 494 | * First, tokenize the string, from left to right. We are not allowed to |
| 495 | * throw away any information that we do not understand. With a flat |
| 496 | * token list that contains all tokens, we can always convert back to |
| 497 | * string form. |
| 498 | */ |
| 499 | if ((first_token = tok822_scan_limit(str, &last_token, tok_count_limit)) == 0) |
| 500 | return (0); |
| 501 | |
| 502 | /* |
| 503 | * For convenience, sandwich the token list between two sentinel tokens. |
| 504 | */ |
| 505 | #define GLUE(left,rite) { left->next = rite; rite->prev = left; } |
| 506 | |
| 507 | head = tok822_alloc(0, (char *) 0); |
| 508 | GLUE(head, first_token); |
| 509 | tail = tok822_alloc(0, (char *) 0); |
| 510 | GLUE(last_token, tail); |
| 511 | |
| 512 | /* |
| 513 | * Next step is to transform the token list into a parse tree. This is |
| 514 | * done most conveniently from right to left. If there is something that |
| 515 | * we do not understand, just leave it alone, don't throw it away. The |
| 516 | * address information that we're looking for sits in-between the current |
| 517 | * node (tp) and the one called right. Add missing commas on the fly. |
| 518 | */ |
| 519 | state = DO_WORD; |
| 520 | right = tail; |
| 521 | tp = tail->prev; |
| 522 | while (tp->type) { |
| 523 | if (tp->type == TOK822_COMMENT) { /* move comment to the side */ |
| 524 | MOVE_COMMENT_AND_CONTINUE(tp, right); |
| 525 | } else if (tp->type == ';') { /* rh side of named group */ |
| 526 | right = tok822_group(TOK822_ADDR, tp, right, ADD_COMMA); |
| 527 | state = DO_GROUP | DO_WORD; |
| 528 | } else if (tp->type == ':' && (state & DO_GROUP) != 0) { |
| 529 | tp->type = TOK822_STARTGRP; |
| 530 | (void) tok822_group(TOK822_ADDR, tp, right, NO_MISSING_COMMA); |
| 531 | SKIP(tp, tp->type != ','); |
| 532 | right = tp; |
| 533 | continue; |
| 534 | } else if (tp->type == '>') { /* rh side of <route> */ |
| 535 | right = tok822_group(TOK822_ADDR, tp, right, ADD_COMMA); |
| 536 | SKIP_MOVE_COMMENT(tp, tp->type != '<', right); |
| 537 | (void) tok822_group(TOK822_ADDR, tp, right, NO_MISSING_COMMA); |
| 538 | SKIP(tp, tp->type > 0xff || strchr(">;,:", tp->type) == 0); |
| 539 | right = tp; |
| 540 | state |= DO_WORD; |
no test coverage detected
searching dependent graphs…