| /* Copyright (c) 2008 by Intel Corp. |
| Scanner for the machine check grammar. |
| |
| mce-inject is free software; you can redistribute it and/or |
| modify it under the terms of the GNU General Public |
| License as published by the Free Software Foundation; version |
| 2. |
| |
| mce-inject is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| General Public License for more details. |
| |
| You should find a copy of v2 of the GNU General Public License somewhere |
| on your Linux system; if not, write to the Free Software Foundation, |
| Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| |
| Authors: |
| Andi Kleen |
| Ying Huang |
| */ |
| %{ |
| #define _GNU_SOURCE 1 |
| #include <stdlib.h> |
| #include <string.h> |
| |
| #include "mce.h" |
| #include "parser.h" |
| #include "mce.tab.h" |
| #include "util.h" |
| #include "inject.h" |
| |
| int yylineno; |
| |
| static int lookup_symbol(const char *); |
| |
| #define YY_NO_INPUT 1 |
| %} |
| |
| %option nounput |
| |
| %% |
| |
| #.*\n /* comment */; |
| \n ++yylineno; |
| 0x[0-9a-fA-F]+ | |
| 0[0-7]+ | |
| [0-9]+ yylval = strtoull(yytext, NULL, 0); return NUMBER; |
| [:{}<>] return yytext[0]; |
| [_a-zA-Z][_a-zA-Z0-9]* return lookup_symbol(yytext); |
| [ \t]+ /* white space */; |
| . yyerror("Unrecognized character '%s'", yytext); |
| |
| %% |
| |
| /* Keyword handling */ |
| |
| static struct key { |
| const char *name; |
| int tok; |
| u64 val; |
| } keys[] = { |
| #define KEY(x) { #x, x } |
| #define KEYVAL(x,v) { #x, x, v } |
| KEY(MCE), |
| KEY(STATUS), |
| KEY(RIP), |
| KEY(TSC), |
| KEY(TIME), |
| KEY(SOCKETID), |
| KEY(APICID), |
| KEY(MCGCAP), |
| KEY(ADDR), |
| KEY(MISC), |
| KEY(CPU), |
| KEY(BANK), |
| KEY(MCGSTATUS), |
| KEY(PROCESSOR), |
| KEY(NOBROADCAST), |
| KEY(HOLD), |
| KEY(IN_IRQ), |
| KEY(IN_PROC), |
| KEY(POLL), |
| KEY(EXCP), |
| KEYVAL(CORRECTED, MCI_STATUS_VAL|MCI_STATUS_EN), // checkme |
| KEYVAL(UNCORRECTED, MCI_STATUS_VAL|MCI_STATUS_UC|MCI_STATUS_EN), |
| KEYVAL(FATAL, MCI_STATUS_VAL|MCI_STATUS_UC|MCI_STATUS_EN |
| |MCI_STATUS_PCC), |
| KEY(MACHINE), |
| KEY(CHECK), |
| KEY(EXCEPTION), |
| KEYVAL(RIPV, MCG_STATUS_RIPV), |
| KEYVAL(EIPV, MCG_STATUS_EIPV), |
| KEYVAL(MCIP, MCG_STATUS_MCIP), |
| KEYVAL(VAL, MCI_STATUS_VAL), |
| KEYVAL(OVER, MCI_STATUS_OVER), |
| KEYVAL(UC, MCI_STATUS_UC), |
| KEYVAL(EN, MCI_STATUS_EN), |
| KEYVAL(PCC, MCI_STATUS_PCC), |
| KEYVAL(S, MCI_STATUS_S), |
| KEYVAL(AR, MCI_STATUS_AR), |
| KEYVAL(UCNA, 0), |
| KEYVAL(SRAO, MCI_STATUS_S), |
| KEYVAL(SRAR, MCI_STATUS_S|MCI_STATUS_AR), |
| }; |
| |
| static int cmp_key(const void *av, const void *bv) |
| { |
| const struct key *a = av; |
| const struct key *b = bv; |
| return strcasecmp(a->name, b->name); |
| } |
| |
| static int lookup_symbol(const char *name) |
| { |
| struct key *k; |
| struct key key; |
| key.name = name; |
| k = bsearch(&key, keys, ARRAY_SIZE(keys), sizeof(struct key), cmp_key); |
| if (k != NULL) { |
| yylval = k->val; |
| return k->tok; |
| } |
| return SYMBOL; |
| } |
| |
| static void init_lex(void) |
| { |
| qsort(keys, ARRAY_SIZE(keys), sizeof(struct key), cmp_key); |
| } |
| |
| int do_dump; |
| int no_random; |
| static char **argv; |
| char *filename = "<stdin>"; |
| |
| int yywrap(void) |
| { |
| if (*argv == NULL) |
| return 1; |
| filename = *argv; |
| yyin = fopen(filename, "r"); |
| if (!yyin) |
| err(filename); |
| argv++; |
| return 0; |
| } |
| |
| int main(int ac, char **av) |
| { |
| int rc = 0; |
| |
| init_lex(); |
| argv = ++av; |
| if (*argv && !strcmp(*argv, "--dump")) { |
| do_dump = 1; |
| argv++; |
| } |
| if (*argv && !strcmp(*argv, "--no-random")) { |
| no_random = 1; |
| argv++; |
| } |
| init_cpu_info(); |
| init_inject(); |
| if (*argv) |
| yywrap(); |
| rc = yyparse(); |
| clean_inject(); |
| |
| return rc; |
| } |