struct token force(struct parser *parser, struct lexer *lex, enum token_type type) { /* {{{ force body */ struct token tok = fetch_token(parser, lex); if (tok.type == type){ #if DEBUG /* {{{ */ if (NM_DEBUG_GET_FLAG(NM_DEBUG_LEXER)){ fprintf(stderr, "%s:%05u:%03u force ", lex->name, lex->line, lex->col); debug_print_token(tok); fprintf(stderr, "\n"); } /* }}} */ #endif lex->curr_tok = tok; advance(lex); return tok; } else { if (tok.type == TOK_KEYWORD) fprintf(stderr, "%s:%u.%u: error: expected a %s instead of a keyword (%s)\n", lex->name, lex->save.line, lex->save.col, tok_to_s(type), tok.value.s); else if (tok.type == TOK_NAME) fprintf(stderr, "%s:%u.%u: error: expected a %s instead of a name (%s)\n", lex->name, lex->save.line, lex->save.col, tok_to_s(type), tok.value.s); else fprintf(stderr, "%s:%u.%u: error: expected a %s instead of a %s\n", lex->name, lex->save.line, lex->save.col, tok_to_s(type), tok_to_s(tok.type)); parser->errorless = false; /* advance to the next token (sometimes there is an infinite loop that * fails to `force` a token) */ skip(parser, lex); /* shut up, errors */ return tok; } /* }}} */ }
/** * Parse a table name * * @param sql Pointer to pointer to column list updated to point to the table name * @return A tree of table names */ static MAXINFO_TREE * parse_table_name(char **ptr) { int token; char *text; MAXINFO_TREE *tree = NULL; *ptr = fetch_token(*ptr, &token, &text); if (token == LT_STRING) return make_tree_node(MAXOP_TABLE, text, NULL, NULL); free(text); return NULL; }
/** * Parse a column list, may be a * or a valid list of string name * separated by a comma * * @param sql Pointer to pointer to column list updated to point to the table name * @return A tree of column names */ static MAXINFO_TREE * parse_column_list(char **ptr) { int token, lookahead; char *text, *text2; MAXINFO_TREE *tree = NULL; MAXINFO_TREE * rval = NULL; *ptr = fetch_token(*ptr, &token, &text); *ptr = fetch_token(*ptr, &lookahead, &text2); switch (token) { case LT_STRING: switch (lookahead) { case LT_COMMA: rval = make_tree_node(MAXOP_COLUMNS, text, NULL, parse_column_list(ptr)); break; case LT_FROM: rval = make_tree_node(MAXOP_COLUMNS, text, NULL, NULL); break; default: break; } break; case LT_STAR: if (lookahead != LT_FROM) rval = make_tree_node(MAXOP_ALL_COLUMNS, NULL, NULL, NULL); break; default: break; } free(text); free(text2); return rval; }
void skip(struct parser *parser, struct lexer *lex) { /* {{{ skip body */ struct token tok = fetch_token(parser, lex); if (tok.type == TOK_EOS){ err(parser, lex, "unexpected <EOS>"); } #if DEBUG /* {{{ */ if (NM_DEBUG_GET_FLAG(NM_DEBUG_LEXER)){ fprintf(stderr, "%s:%05u:%03u skip ", lex->name, lex->line, lex->col); debug_print_token(tok); fprintf(stderr, "\n"); } /* }}} */ #endif advance(lex); /* }}} */ }
bool peek(struct parser *parser, struct lexer *lex, enum token_type type) { /* {{{ peek_body */ struct token tok = fetch_token(parser, lex); fallback(lex); if (tok.type == type){ #if DEBUG /* {{{ */ if (NM_DEBUG_GET_FLAG(NM_DEBUG_LEXER)){ fprintf(stderr, "%s:%05u:%03u peek ", lex->name, lex->line, lex->col); debug_print_token(tok); fprintf(stderr, "\n"); } /* }}} */ #endif lex->curr_tok = tok; return true; } else { return false; } /* }}} */ }
/** * Parse the remaining arguments as literals. * @param tree Previous head of the parse tree * @param min_args Minimum required number of arguments * @param ptr Pointer to client command * @param parse_error Pointer to parsing error to fill * @return Parsed tree or NULL if parsing failed */ MAXINFO_TREE* maxinfo_parse_literals(MAXINFO_TREE *tree, int min_args, char *ptr, PARSE_ERROR *parse_error) { int token; MAXINFO_TREE* node = tree; char *text; for(int i = 0; i < min_args; i++) { if((ptr = fetch_token(ptr, &token, &text)) == NULL || (node->right = make_tree_node(MAXOP_LITERAL, text, NULL, NULL)) == NULL) { *parse_error = PARSE_SYNTAX_ERROR; free_tree(tree); if(ptr) { free(text); } return NULL; } node = node->right; } return tree; }
void txtproto_print(netdissect_options *ndo, const u_char *pptr, u_int len, const char *protoname, const char **cmds, u_int flags) { u_int idx, eol; u_char token[MAX_TOKEN+1]; const char *cmd; int is_reqresp = 0; const char *pnp; if (cmds != NULL) { /* * This protocol has more than just request and * response lines; see whether this looks like a * request or response. */ idx = fetch_token(ndo, pptr, 0, len, token, sizeof(token)); if (idx != 0) { /* Is this a valid request name? */ while ((cmd = *cmds++) != NULL) { if (strcasecmp((const char *)token, cmd) == 0) { /* Yes. */ is_reqresp = 1; break; } } /* * No - is this a valid response code (3 digits)? * * Is this token the response code, or is the next * token the response code? */ if (flags & RESP_CODE_SECOND_TOKEN) { /* * Next token - get it. */ idx = fetch_token(ndo, pptr, idx, len, token, sizeof(token)); } if (idx != 0) { if (isdigit(token[0]) && isdigit(token[1]) && isdigit(token[2]) && token[3] == '\0') { /* Yes. */ is_reqresp = 1; } } } } else { /* * This protocol has only request and response lines * (e.g., FTP, where all the data goes over a * different connection); assume the payload is * a request or response. */ is_reqresp = 1; } /* Capitalize the protocol name */ for (pnp = protoname; *pnp != '\0'; pnp++) ND_PRINT((ndo, "%c", toupper(*pnp))); if (is_reqresp) { /* * In non-verbose mode, just print the protocol, followed * by the first line as the request or response info. * * In verbose mode, print lines as text until we run out * of characters or see something that's not a * printable-ASCII line. */ if (ndo->ndo_vflag) { /* * We're going to print all the text lines in the * request or response; just print the length * on the first line of the output. */ ND_PRINT((ndo, ", length: %u", len)); for (idx = 0; idx < len && (eol = print_txt_line(ndo, protoname, "\n\t", pptr, idx, len)) != 0; idx = eol) ; } else { /* * Just print the first text line. */ print_txt_line(ndo, protoname, ": ", pptr, 0, len); } } }
/** * Parse a SQL subset for the maxinfo plugin and return a parse tree * * @param sql The SQL query * @return Parse tree or NULL on error */ MAXINFO_TREE * maxinfo_parse(char *sql, PARSE_ERROR *parse_error) { int token; char *ptr, *text; MAXINFO_TREE *tree = NULL; MAXINFO_TREE *col, *table; *parse_error = PARSE_NOERROR; while ((ptr = fetch_token(sql, &token, &text)) != NULL) { switch (token) { case LT_SHOW: free(text); // not needed ptr = fetch_token(ptr, &token, &text); if (ptr == NULL || token != LT_STRING) { // Expected show "name" *parse_error = PARSE_MALFORMED_SHOW; return NULL; } tree = make_tree_node(MAXOP_SHOW, text, NULL, NULL); if ((ptr = fetch_token(ptr, &token, &text)) == NULL) return tree; else if (token == LT_LIKE) { if ((ptr = fetch_token(ptr, &token, &text)) != NULL) { tree->right = make_tree_node(MAXOP_LIKE, text, NULL, NULL); return tree; } else { // Expected expression *parse_error = PARSE_EXPECTED_LIKE; free_tree(tree); return NULL; } } // Malformed show free(text); free_tree(tree); *parse_error = PARSE_MALFORMED_SHOW; return NULL; #if 0 case LT_SELECT: free(text); // not needed col = parse_column_list(&ptr); table = parse_table_name(&ptr); return make_tree_node(MAXOP_SELECT, NULL, col, table); #endif case LT_FLUSH: free(text); // not needed ptr = fetch_token(ptr, &token, &text); return make_tree_node(MAXOP_FLUSH, text, NULL, NULL); case LT_SHUTDOWN: free(text); ptr = fetch_token(ptr, &token, &text); tree = make_tree_node(MAXOP_SHUTDOWN, text, NULL, NULL); if ((ptr = fetch_token(ptr, &token, &text)) == NULL) { /** Possibly SHUTDOWN MAXSCALE */ return tree; } tree->right = make_tree_node(MAXOP_LITERAL, text, NULL, NULL); if ((ptr = fetch_token(ptr, &token, &text)) != NULL) { /** Unknown token after SHUTDOWN MONITOR|SERVICE */ *parse_error = PARSE_SYNTAX_ERROR; free_tree(tree); return NULL; } return tree; case LT_RESTART: free(text); ptr = fetch_token(ptr, &token, &text); tree = make_tree_node(MAXOP_RESTART, text, NULL, NULL); if ((ptr = fetch_token(ptr, &token, &text)) == NULL) { /** Missing token for RESTART MONITOR|SERVICE */ *parse_error = PARSE_SYNTAX_ERROR; free_tree(tree); return NULL; } tree->right = make_tree_node(MAXOP_LITERAL, text, NULL, NULL); if ((ptr = fetch_token(ptr, &token, &text)) != NULL) { /** Unknown token after RESTART MONITOR|SERVICE */ *parse_error = PARSE_SYNTAX_ERROR; free(text); free_tree(tree); return NULL; } return tree; case LT_SET: free(text); // not needed ptr = fetch_token(ptr, &token, &text); tree = make_tree_node(MAXOP_SET, text, NULL, NULL); return maxinfo_parse_literals(tree, 2, ptr, parse_error); case LT_CLEAR: free(text); // not needed ptr = fetch_token(ptr, &token, &text); tree = make_tree_node(MAXOP_CLEAR, text, NULL, NULL); return maxinfo_parse_literals(tree, 2, ptr, parse_error); break; default: *parse_error = PARSE_SYNTAX_ERROR; return NULL; } } *parse_error = PARSE_SYNTAX_ERROR; return NULL; }