static const char * lex_parse_macro(const char *p, struct lex_token *token) { p++; if (!lex_is_id1(*p)) { lex_error(token, "`$' must be followed by a valid identifier."); return p; } return lex_parse_id(p, LEX_T_MACRO, token); }
/* Initializes 'token' and parses the first token from the beginning of * null-terminated string 'p' into 'token'. Stores a pointer to the start of * the token (after skipping white space and comments, if any) into '*startp'. * Returns the character position at which to begin parsing the next token. */ const char * lex_token_parse(struct lex_token *token, const char *p, const char **startp) { lex_token_init(token); next: *startp = p; switch (*p) { case '\0': token->type = LEX_T_END; return p; case ' ': case '\t': case '\n': case '\r': p++; goto next; case '/': p++; if (*p == '/') { do { p++; } while (*p != '\0' && *p != '\n'); goto next; } else if (*p == '*') { p++; for (;;) { if (*p == '*' && p[1] == '/') { p += 2; goto next; } else if (*p == '\0' || *p == '\n') { lex_error(token, "`/*' without matching `*/'."); return p; } else { p++; } } goto next; } else { lex_error(token, "`/' is only valid as part of `//' or `/*'."); } break; case '(': token->type = LEX_T_LPAREN; p++; break; case ')': token->type = LEX_T_RPAREN; p++; break; case '{': token->type = LEX_T_LCURLY; p++; break; case '}': token->type = LEX_T_RCURLY; p++; break; case '[': token->type = LEX_T_LSQUARE; p++; break; case ']': token->type = LEX_T_RSQUARE; p++; break; case '=': p++; if (*p == '=') { token->type = LEX_T_EQ; p++; } else { token->type = LEX_T_EQUALS; } break; case '!': p++; if (*p == '=') { token->type = LEX_T_NE; p++; } else { token->type = LEX_T_LOG_NOT; } break; case '&': p++; if (*p == '&') { token->type = LEX_T_LOG_AND; p++; } else { lex_error(token, "`&' is only valid as part of `&&'."); } break; case '|': p++; if (*p == '|') { token->type = LEX_T_LOG_OR; p++; } else { lex_error(token, "`|' is only valid as part of `||'."); } break; case '<': p++; if (*p == '=') { token->type = LEX_T_LE; p++; } else if (*p == '-' && p[1] == '>') { token->type = LEX_T_EXCHANGE; p += 2; } else { token->type = LEX_T_LT; } break; case '>': p++; if (*p == '=') { token->type = LEX_T_GE; p++; } else { token->type = LEX_T_GT; } break; case '.': p++; if (*p == '.') { token->type = LEX_T_ELLIPSIS; p++; } else { lex_error(token, "`.' is only valid as part of `..' or a number."); } break; case ',': p++; token->type = LEX_T_COMMA; break; case ';': p++; token->type = LEX_T_SEMICOLON; break; case '-': p++; if (*p == '-') { token->type = LEX_T_DECREMENT; p++; } else { lex_error(token, "`-' is only valid as part of `--'."); } break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case ':': p = lex_parse_integer(p, token); break; case '"': p = lex_parse_string(p, token); break; case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': /* We need to distinguish an Ethernet address or IPv6 address from an * identifier. Fortunately, Ethernet addresses and IPv6 addresses that * are ambiguous based on the first character, always start with hex * digits followed by a colon, but identifiers never do. */ p = (p[strspn(p, "0123456789abcdefABCDEF")] == ':' ? lex_parse_integer(p, token) : lex_parse_id(p, token)); break; default: if (lex_is_id1(*p)) { p = lex_parse_id(p, token); } else { if (isprint((unsigned char) *p)) { lex_error(token, "Invalid character `%c' in input.", *p); } else { lex_error(token, "Invalid byte 0x%d in input.", *p); } p++; } break; } return p; }
static bool lex_is_idn(unsigned char c) { return lex_is_id1(c) || (c >= '0' && c <= '9'); }