%{ /* * Copyright (C) 2006-2010 Michael Buesch * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 * as published by the Free Software Foundation. * * This program 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. */ #include "parser.h" #include "main.h" #include "util.h" #include #include static void interpret_cppinfo(const char *); static void update_lineinfo(void); static inline void log_current_line(void) { size_t len; len = min(sizeof(cur_lineinfo.linecopy) - 1, strlen(yytext)); memcpy(cur_lineinfo.linecopy, yytext, len); cur_lineinfo.linecopy[len] = '\0'; } %} IDENTIFIER ([a-zA-Z_][0-9a-zA-Z_]*) WS ([ \t]) NEWLINE ((\r)|(\n)|(\r\n)) %% ^.*$ { log_current_line(); REJECT; } #{WS}+[0-9]+{WS}+\".*\"[0-9 \t]*{NEWLINE} { interpret_cppinfo(yytext); } {WS}+ { update_lineinfo(); /* whitespace */ } {NEWLINE} { cur_lineinfo.lineno++; update_lineinfo(); } ^{WS}*"%"{WS}*arch { update_lineinfo(); return ASM_ARCH; } ^{WS}*"%"{WS}*start { update_lineinfo(); return ASM_START; } "%"{WS}*assert { update_lineinfo(); return ASM_ASSERT; } ^{WS}*\.text{WS}*$ { update_lineinfo(); return SECTION_TEXT; } ^{WS}*\.initvals/\({IDENTIFIER}\) { update_lineinfo(); return SECTION_IVALS; } spr[0-9a-fA-F]{1,4} { update_lineinfo(); return SPR; } r/([0-9]|([1-5][0-9])|(6[0-3])) { update_lineinfo(); return GPR; } off/[0-6] { update_lineinfo(); return OFFR; } lr/[0-3] { update_lineinfo(); return LR; } , { update_lineinfo(); return COMMA; } ; { update_lineinfo(); return SEMICOLON; } \[ { update_lineinfo(); return BRACK_OPEN; } \] { update_lineinfo(); return BRACK_CLOSE; } \( { update_lineinfo(); return PAREN_OPEN; } \) { update_lineinfo(); return PAREN_CLOSE; } == { update_lineinfo(); return EQUAL; } != { update_lineinfo(); return NOT_EQUAL; } \|\| { update_lineinfo(); return LOGICAL_OR; } \&\& { update_lineinfo(); return LOGICAL_AND; } \+ { update_lineinfo(); return PLUS; } \- { update_lineinfo(); return MINUS; } \* { update_lineinfo(); return MULTIPLY; } \/ { update_lineinfo(); return DIVIDE; } \| { update_lineinfo(); return BITW_OR; } \& { update_lineinfo(); return BITW_AND; } \^ { update_lineinfo(); return BITW_XOR; } \~ { update_lineinfo(); return BITW_NOT; } \<\< { update_lineinfo(); return LEFTSHIFT; } \>\> { update_lineinfo(); return RIGHTSHIFT; } mul { update_lineinfo(); return OP_MUL; } add { update_lineinfo(); return OP_ADD; } add\. { update_lineinfo(); return OP_ADDSC; } addc { update_lineinfo(); return OP_ADDC; } addc\. { update_lineinfo(); return OP_ADDSCC; } sub { update_lineinfo(); return OP_SUB; } sub\. { update_lineinfo(); return OP_SUBSC; } subc { update_lineinfo(); return OP_SUBC; } subc\. { update_lineinfo(); return OP_SUBSCC; } sra { update_lineinfo(); return OP_SRA; } or { update_lineinfo(); return OP_OR; } and { update_lineinfo(); return OP_AND; } xor { update_lineinfo(); return OP_XOR; } sr { update_lineinfo(); return OP_SR; } srx { update_lineinfo(); return OP_SRX; } srxh { update_lineinfo(); return OP_SRXH; } sl { update_lineinfo(); return OP_SL; } rl { update_lineinfo(); return OP_RL; } rr { update_lineinfo(); return OP_RR; } nand { update_lineinfo(); return OP_NAND; } orx { update_lineinfo(); return OP_ORX; } orxh { update_lineinfo(); return OP_ORXH; } mov { update_lineinfo(); return OP_MOV; } jmp { update_lineinfo(); return OP_JMP; } jand { update_lineinfo(); return OP_JAND; } jnand { update_lineinfo(); return OP_JNAND; } js { update_lineinfo(); return OP_JS; } jns { update_lineinfo(); return OP_JNS; } je { update_lineinfo(); return OP_JE; } jne { update_lineinfo(); return OP_JNE; } jls { update_lineinfo(); return OP_JLS; } jges { update_lineinfo(); return OP_JGES; } jgs { update_lineinfo(); return OP_JGS; } jles { update_lineinfo(); return OP_JLES; } jl { update_lineinfo(); return OP_JL; } jge { update_lineinfo(); return OP_JGE; } jg { update_lineinfo(); return OP_JG; } jle { update_lineinfo(); return OP_JLE; } jdn { update_lineinfo(); return OP_JDN; } jdpz { update_lineinfo(); return OP_JDPZ; } jdp { update_lineinfo(); return OP_JDP; } jdnz { update_lineinfo(); return OP_JDNZ; } jboh { update_lineinfo(); return OP_JBOH; } jnboh { update_lineinfo(); return OP_JNBOH; } jzx { update_lineinfo(); return OP_JZX; } jzxh { update_lineinfo(); return OP_JZXH; } jnzx { update_lineinfo(); return OP_JNZX; } jnzxh { update_lineinfo(); return OP_JNZXH; } jext { update_lineinfo(); return OP_JEXT; } jnext { update_lineinfo(); return OP_JNEXT; } call { update_lineinfo(); return OP_CALL; } calls { update_lineinfo(); return OP_CALLS; } ret { update_lineinfo(); return OP_RET; } rets { update_lineinfo(); return OP_RETS; } tkiph { update_lineinfo(); return OP_TKIPH; } tkiphs { update_lineinfo(); return OP_TKIPHS; } tkipl { update_lineinfo(); return OP_TKIPL; } tkipls { update_lineinfo(); return OP_TKIPLS; } nap { update_lineinfo(); return OP_NAP; } nap2 { update_lineinfo(); return OP_NAP2; } mmio16 { update_lineinfo(); return IVAL_MMIO16; } mmio32 { update_lineinfo(); return IVAL_MMIO32; } phy { update_lineinfo(); return IVAL_PHY; } radio { update_lineinfo(); return IVAL_RADIO; } shm16 { update_lineinfo(); return IVAL_SHM16; } shm32 { update_lineinfo(); return IVAL_SHM32; } tram { update_lineinfo(); return IVAL_TRAM; } @[0-9a-fA-F]{1,4} { update_lineinfo(); return RAW_CODE; } 0x[0-9a-fA-F]+ { update_lineinfo(); return HEXNUM; } -?[0-9]+ { update_lineinfo(); return DECNUM; } {IDENTIFIER}: { update_lineinfo(); return LABEL; } {IDENTIFIER} { update_lineinfo(); return IDENT; } %% struct lineinfo cur_lineinfo; static inline const char * strip_leading_ws(const char *str) { while (*str != '\0' && isspace(*str)) str++; return str; } static void interpret_cppinfo(const char *str) { const char * const orig = str; char tmp[64]; const char *found; char *tail; /* This will interpret lines added by CPP. * They look like: * # lineno "filename" flags... */ str = strip_leading_ws(str); if (*str != '#') goto error; str++; /* skip # character */ str = strip_leading_ws(str); if (*str == '\0') goto error; /* Line number */ found = strchr(str, ' '); if (!found) goto error; memset(tmp, 0, sizeof(tmp)); memcpy(tmp, str, min(sizeof(tmp) - 1, (size_t)(found - str))); cur_lineinfo.lineno = strtoul(tmp, &tail, 0); if (*tail != '\0') goto error; str = strip_leading_ws(found); /* File name */ if (*str != '\"') goto error; str++; if (*str == '\0') goto error; found = strchr(str, '\"'); if (!found) goto error; memset(cur_lineinfo.file, 0, sizeof(cur_lineinfo.file)); memcpy(cur_lineinfo.file, str, min(sizeof(cur_lineinfo.file) - 1, (size_t)(found - str))); /* We ignore the flags. */ return; error: fprintf(stderr, "Invalid CPP line directive: %s\n", orig); exit(1); } static void update_lineinfo(void) { int i = 0; while (yytext[i] != '\0') { switch (yytext[i]) { case '\r': case '\n': cur_lineinfo.column = 0; break; case '\t': cur_lineinfo.column += 8 - (cur_lineinfo.column % 8); break; default: cur_lineinfo.column++; } i++; } }