aicasm_scan.l 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618
  1. %{
  2. /*
  3. * Lexical Analyzer for the Aic7xxx SCSI Host adapter sequencer assembler.
  4. *
  5. * Copyright (c) 1997, 1998, 2000 Justin T. Gibbs.
  6. * Copyright (c) 2001, 2002 Adaptec Inc.
  7. * All rights reserved.
  8. *
  9. * Redistribution and use in source and binary forms, with or without
  10. * modification, are permitted provided that the following conditions
  11. * are met:
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions, and the following disclaimer,
  14. * without modification.
  15. * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  16. * substantially similar to the "NO WARRANTY" disclaimer below
  17. * ("Disclaimer") and any redistribution must be conditioned upon
  18. * including a substantially similar Disclaimer requirement for further
  19. * binary redistribution.
  20. * 3. Neither the names of the above-listed copyright holders nor the names
  21. * of any contributors may be used to endorse or promote products derived
  22. * from this software without specific prior written permission.
  23. *
  24. * Alternatively, this software may be distributed under the terms of the
  25. * GNU General Public License ("GPL") version 2 as published by the Free
  26. * Software Foundation.
  27. *
  28. * NO WARRANTY
  29. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  30. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  31. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
  32. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  33. * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  34. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  35. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  36. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  37. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  38. * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  39. * POSSIBILITY OF SUCH DAMAGES.
  40. *
  41. * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_scan.l#20 $
  42. *
  43. * $FreeBSD$
  44. */
  45. #include <sys/types.h>
  46. #include <inttypes.h>
  47. #include <limits.h>
  48. #include <regex.h>
  49. #include <stdio.h>
  50. #include <string.h>
  51. #include <sysexits.h>
  52. #include "../queue.h"
  53. #include "aicasm.h"
  54. #include "aicasm_symbol.h"
  55. #include "aicasm_gram.h"
  56. /* This is used for macro body capture too, so err on the large size. */
  57. #define MAX_STR_CONST 4096
  58. static char string_buf[MAX_STR_CONST];
  59. static char *string_buf_ptr;
  60. static int parren_count;
  61. static int quote_count;
  62. static char buf[255];
  63. %}
  64. PATH ([/]*[-A-Za-z0-9_.])+
  65. WORD [A-Za-z_][-A-Za-z_0-9]*
  66. SPACE [ \t]+
  67. MCARG [^(), \t]+
  68. MBODY ((\\[^\n])*[^\n\\]*)+
  69. %x COMMENT
  70. %x CEXPR
  71. %x INCLUDE
  72. %x STRING
  73. %x MACRODEF
  74. %x MACROARGLIST
  75. %x MACROCALLARGS
  76. %x MACROBODY
  77. %%
  78. \n { ++yylineno; }
  79. \r ;
  80. "/*" { BEGIN COMMENT; /* Enter comment eating state */ }
  81. <COMMENT>"/*" { fprintf(stderr, "Warning! Comment within comment."); }
  82. <COMMENT>\n { ++yylineno; }
  83. <COMMENT>[^*/\n]* ;
  84. <COMMENT>"*"+[^*/\n]* ;
  85. <COMMENT>"/"+[^*/\n]* ;
  86. <COMMENT>"*"+"/" { BEGIN INITIAL; }
  87. if[ \t]*\( {
  88. string_buf_ptr = string_buf;
  89. parren_count = 1;
  90. BEGIN CEXPR;
  91. return T_IF;
  92. }
  93. <CEXPR>\( { *string_buf_ptr++ = '('; parren_count++; }
  94. <CEXPR>\) {
  95. parren_count--;
  96. if (parren_count == 0) {
  97. /* All done */
  98. BEGIN INITIAL;
  99. *string_buf_ptr = '\0';
  100. yylval.sym = symtable_get(string_buf);
  101. return T_CEXPR;
  102. } else {
  103. *string_buf_ptr++ = ')';
  104. }
  105. }
  106. <CEXPR>\n { ++yylineno; }
  107. <CEXPR>\r ;
  108. <CEXPR>[^()\n]+ {
  109. char *yptr;
  110. yptr = yytext;
  111. while (*yptr != '\0') {
  112. /* Remove duplicate spaces */
  113. if (*yptr == '\t')
  114. *yptr = ' ';
  115. if (*yptr == ' '
  116. && string_buf_ptr != string_buf
  117. && string_buf_ptr[-1] == ' ')
  118. yptr++;
  119. else
  120. *string_buf_ptr++ = *yptr++;
  121. }
  122. }
  123. else { return T_ELSE; }
  124. VERSION { return T_VERSION; }
  125. PREFIX { return T_PREFIX; }
  126. PATCH_ARG_LIST { return T_PATCH_ARG_LIST; }
  127. \" {
  128. string_buf_ptr = string_buf;
  129. BEGIN STRING;
  130. }
  131. <STRING>[^"]+ {
  132. char *yptr;
  133. yptr = yytext;
  134. while (*yptr)
  135. *string_buf_ptr++ = *yptr++;
  136. }
  137. <STRING>\" {
  138. /* All done */
  139. BEGIN INITIAL;
  140. *string_buf_ptr = '\0';
  141. yylval.str = string_buf;
  142. return T_STRING;
  143. }
  144. {SPACE} ;
  145. /* Register/SCB/SRAM definition keywords */
  146. export { return T_EXPORT; }
  147. register { return T_REGISTER; }
  148. const { yylval.value = FALSE; return T_CONST; }
  149. download { return T_DOWNLOAD; }
  150. address { return T_ADDRESS; }
  151. count { return T_COUNT; }
  152. access_mode { return T_ACCESS_MODE; }
  153. dont_generate_debug_code { return T_DONT_GENERATE_DEBUG_CODE; }
  154. modes { return T_MODES; }
  155. RW|RO|WO {
  156. if (strcmp(yytext, "RW") == 0)
  157. yylval.value = RW;
  158. else if (strcmp(yytext, "RO") == 0)
  159. yylval.value = RO;
  160. else
  161. yylval.value = WO;
  162. return T_MODE;
  163. }
  164. field { return T_FIELD; }
  165. enum { return T_ENUM; }
  166. mask { return T_MASK; }
  167. alias { return T_ALIAS; }
  168. size { return T_SIZE; }
  169. scb { return T_SCB; }
  170. scratch_ram { return T_SRAM; }
  171. accumulator { return T_ACCUM; }
  172. mode_pointer { return T_MODE_PTR; }
  173. allones { return T_ALLONES; }
  174. allzeros { return T_ALLZEROS; }
  175. none { return T_NONE; }
  176. sindex { return T_SINDEX; }
  177. A { return T_A; }
  178. /* Instruction Formatting */
  179. PAD_PAGE { return T_PAD_PAGE; }
  180. BEGIN_CRITICAL { return T_BEGIN_CS; }
  181. END_CRITICAL { return T_END_CS; }
  182. SET_SRC_MODE { return T_SET_SRC_MODE; }
  183. SET_DST_MODE { return T_SET_DST_MODE; }
  184. /* Opcodes */
  185. shl { return T_SHL; }
  186. shr { return T_SHR; }
  187. ror { return T_ROR; }
  188. rol { return T_ROL; }
  189. mvi { return T_MVI; }
  190. mov { return T_MOV; }
  191. clr { return T_CLR; }
  192. jmp { return T_JMP; }
  193. jc { return T_JC; }
  194. jnc { return T_JNC; }
  195. je { return T_JE; }
  196. jne { return T_JNE; }
  197. jz { return T_JZ; }
  198. jnz { return T_JNZ; }
  199. call { return T_CALL; }
  200. add { return T_ADD; }
  201. adc { return T_ADC; }
  202. bmov { return T_BMOV; }
  203. inc { return T_INC; }
  204. dec { return T_DEC; }
  205. stc { return T_STC; }
  206. clc { return T_CLC; }
  207. cmp { return T_CMP; }
  208. not { return T_NOT; }
  209. xor { return T_XOR; }
  210. test { return T_TEST;}
  211. and { return T_AND; }
  212. or { return T_OR; }
  213. ret { return T_RET; }
  214. nop { return T_NOP; }
  215. /* ARP2 16bit extensions */
  216. /* or16 { return T_OR16; } */
  217. /* and16 { return T_AND16; }*/
  218. /* xor16 { return T_XOR16; }*/
  219. /* add16 { return T_ADD16; }*/
  220. /* adc16 { return T_ADC16; }*/
  221. /* mvi16 { return T_MVI16; }*/
  222. /* test16 { return T_TEST16; }*/
  223. /* cmp16 { return T_CMP16; }*/
  224. /* cmpxchg { return T_CMPXCHG; }*/
  225. /* Allowed Symbols */
  226. \<\< { return T_EXPR_LSHIFT; }
  227. \>\> { return T_EXPR_RSHIFT; }
  228. [-+,:()~|&."{};<>[\]/*!=] { return yytext[0]; }
  229. /* Number processing */
  230. 0[0-7]* {
  231. yylval.value = strtol(yytext, NULL, 8);
  232. return T_NUMBER;
  233. }
  234. 0[xX][0-9a-fA-F]+ {
  235. yylval.value = strtoul(yytext + 2, NULL, 16);
  236. return T_NUMBER;
  237. }
  238. [1-9][0-9]* {
  239. yylval.value = strtol(yytext, NULL, 10);
  240. return T_NUMBER;
  241. }
  242. /* Include Files */
  243. #include{SPACE} {
  244. BEGIN INCLUDE;
  245. quote_count = 0;
  246. return T_INCLUDE;
  247. }
  248. <INCLUDE>[<] { return yytext[0]; }
  249. <INCLUDE>[>] { BEGIN INITIAL; return yytext[0]; }
  250. <INCLUDE>[\"] {
  251. if (quote_count != 0)
  252. BEGIN INITIAL;
  253. quote_count++;
  254. return yytext[0];
  255. }
  256. <INCLUDE>{PATH} {
  257. char *yptr;
  258. yptr = yytext;
  259. string_buf_ptr = string_buf;
  260. while (*yptr)
  261. *string_buf_ptr++ = *yptr++;
  262. yylval.str = string_buf;
  263. *string_buf_ptr = '\0';
  264. return T_PATH;
  265. }
  266. <INCLUDE>. { stop("Invalid include line", EX_DATAERR); }
  267. #define{SPACE} {
  268. BEGIN MACRODEF;
  269. return T_DEFINE;
  270. }
  271. <MACRODEF>{WORD}{SPACE} {
  272. char *yptr;
  273. /* Strip space and return as a normal symbol */
  274. yptr = yytext;
  275. while (*yptr != ' ' && *yptr != '\t')
  276. yptr++;
  277. *yptr = '\0';
  278. yylval.sym = symtable_get(yytext);
  279. string_buf_ptr = string_buf;
  280. BEGIN MACROBODY;
  281. return T_SYMBOL;
  282. }
  283. <MACRODEF>{WORD}\( {
  284. /*
  285. * We store the symbol with its opening
  286. * parren so we can differentiate macros
  287. * that take args from macros with the
  288. * same name that do not take args as
  289. * is allowed in C.
  290. */
  291. BEGIN MACROARGLIST;
  292. yylval.sym = symtable_get(yytext);
  293. unput('(');
  294. return T_SYMBOL;
  295. }
  296. <MACROARGLIST>{WORD} {
  297. yylval.str = yytext;
  298. return T_ARG;
  299. }
  300. <MACROARGLIST>{SPACE} ;
  301. <MACROARGLIST>[(,] {
  302. return yytext[0];
  303. }
  304. <MACROARGLIST>[)] {
  305. string_buf_ptr = string_buf;
  306. BEGIN MACROBODY;
  307. return ')';
  308. }
  309. <MACROARGLIST>. {
  310. snprintf(buf, sizeof(buf), "Invalid character "
  311. "'%c' in macro argument list",
  312. yytext[0]);
  313. stop(buf, EX_DATAERR);
  314. }
  315. <MACROCALLARGS>{SPACE} ;
  316. <MACROCALLARGS>\( {
  317. parren_count++;
  318. if (parren_count == 1)
  319. return ('(');
  320. *string_buf_ptr++ = '(';
  321. }
  322. <MACROCALLARGS>\) {
  323. parren_count--;
  324. if (parren_count == 0) {
  325. BEGIN INITIAL;
  326. return (')');
  327. }
  328. *string_buf_ptr++ = ')';
  329. }
  330. <MACROCALLARGS>{MCARG} {
  331. char *yptr;
  332. yptr = yytext;
  333. while (*yptr)
  334. *string_buf_ptr++ = *yptr++;
  335. }
  336. <MACROCALLARGS>\, {
  337. if (string_buf_ptr != string_buf) {
  338. /*
  339. * Return an argument and
  340. * rescan this comma so we
  341. * can return it as well.
  342. */
  343. *string_buf_ptr = '\0';
  344. yylval.str = string_buf;
  345. string_buf_ptr = string_buf;
  346. unput(',');
  347. return T_ARG;
  348. }
  349. return ',';
  350. }
  351. <MACROBODY>\\\n {
  352. /* Eat escaped newlines. */
  353. ++yylineno;
  354. }
  355. <MACROBODY>\r ;
  356. <MACROBODY>\n {
  357. /* Macros end on the first unescaped newline. */
  358. BEGIN INITIAL;
  359. *string_buf_ptr = '\0';
  360. yylval.str = string_buf;
  361. ++yylineno;
  362. return T_MACROBODY;
  363. }
  364. <MACROBODY>{MBODY} {
  365. char *yptr;
  366. char c;
  367. yptr = yytext;
  368. while (c = *yptr++) {
  369. /*
  370. * Strip carriage returns.
  371. */
  372. if (c == '\r')
  373. continue;
  374. *string_buf_ptr++ = c;
  375. }
  376. }
  377. {WORD}\( {
  378. char *yptr;
  379. char *ycopy;
  380. /* May be a symbol or a macro invocation. */
  381. yylval.sym = symtable_get(yytext);
  382. if (yylval.sym->type == MACRO) {
  383. YY_BUFFER_STATE old_state;
  384. YY_BUFFER_STATE temp_state;
  385. ycopy = strdup(yytext);
  386. yptr = ycopy + yyleng;
  387. while (yptr > ycopy)
  388. unput(*--yptr);
  389. old_state = YY_CURRENT_BUFFER;
  390. temp_state =
  391. yy_create_buffer(stdin,
  392. YY_BUF_SIZE);
  393. yy_switch_to_buffer(temp_state);
  394. mm_switch_to_buffer(old_state);
  395. mmparse();
  396. mm_switch_to_buffer(temp_state);
  397. yy_switch_to_buffer(old_state);
  398. mm_delete_buffer(temp_state);
  399. expand_macro(yylval.sym);
  400. } else {
  401. if (yylval.sym->type == UNINITIALIZED) {
  402. /* Try without the '(' */
  403. symbol_delete(yylval.sym);
  404. yytext[yyleng-1] = '\0';
  405. yylval.sym =
  406. symtable_get(yytext);
  407. }
  408. unput('(');
  409. return T_SYMBOL;
  410. }
  411. }
  412. {WORD} {
  413. yylval.sym = symtable_get(yytext);
  414. if (yylval.sym->type == MACRO) {
  415. expand_macro(yylval.sym);
  416. } else {
  417. return T_SYMBOL;
  418. }
  419. }
  420. . {
  421. snprintf(buf, sizeof(buf), "Invalid character "
  422. "'%c'", yytext[0]);
  423. stop(buf, EX_DATAERR);
  424. }
  425. %%
  426. typedef struct include {
  427. YY_BUFFER_STATE buffer;
  428. int lineno;
  429. char *filename;
  430. SLIST_ENTRY(include) links;
  431. }include_t;
  432. SLIST_HEAD(, include) include_stack;
  433. void
  434. include_file(char *file_name, include_type type)
  435. {
  436. FILE *newfile;
  437. include_t *include;
  438. newfile = NULL;
  439. /* Try the current directory first */
  440. if (includes_search_curdir != 0 || type == SOURCE_FILE)
  441. newfile = fopen(file_name, "r");
  442. if (newfile == NULL && type != SOURCE_FILE) {
  443. path_entry_t include_dir;
  444. for (include_dir = search_path.slh_first;
  445. include_dir != NULL;
  446. include_dir = include_dir->links.sle_next) {
  447. char fullname[PATH_MAX];
  448. if ((include_dir->quoted_includes_only == TRUE)
  449. && (type != QUOTED_INCLUDE))
  450. continue;
  451. snprintf(fullname, sizeof(fullname),
  452. "%s/%s", include_dir->directory, file_name);
  453. if ((newfile = fopen(fullname, "r")) != NULL)
  454. break;
  455. }
  456. }
  457. if (newfile == NULL) {
  458. perror(file_name);
  459. stop("Unable to open input file", EX_SOFTWARE);
  460. /* NOTREACHED */
  461. }
  462. if (type != SOURCE_FILE) {
  463. include = (include_t *)malloc(sizeof(include_t));
  464. if (include == NULL) {
  465. stop("Unable to allocate include stack entry",
  466. EX_SOFTWARE);
  467. /* NOTREACHED */
  468. }
  469. include->buffer = YY_CURRENT_BUFFER;
  470. include->lineno = yylineno;
  471. include->filename = yyfilename;
  472. SLIST_INSERT_HEAD(&include_stack, include, links);
  473. }
  474. yy_switch_to_buffer(yy_create_buffer(newfile, YY_BUF_SIZE));
  475. yylineno = 1;
  476. yyfilename = strdup(file_name);
  477. }
  478. static void next_substitution(struct symbol *mac_symbol, const char *body_pos,
  479. const char **next_match,
  480. struct macro_arg **match_marg, regmatch_t *match);
  481. void
  482. expand_macro(struct symbol *macro_symbol)
  483. {
  484. struct macro_arg *marg;
  485. struct macro_arg *match_marg;
  486. const char *body_head;
  487. const char *body_pos;
  488. const char *next_match;
  489. /*
  490. * Due to the nature of unput, we must work
  491. * backwards through the macro body performing
  492. * any expansions.
  493. */
  494. body_head = macro_symbol->info.macroinfo->body;
  495. body_pos = body_head + strlen(body_head);
  496. while (body_pos > body_head) {
  497. regmatch_t match;
  498. next_match = body_head;
  499. match_marg = NULL;
  500. next_substitution(macro_symbol, body_pos, &next_match,
  501. &match_marg, &match);
  502. /* Put back everything up until the replacement. */
  503. while (body_pos > next_match)
  504. unput(*--body_pos);
  505. /* Perform the replacement. */
  506. if (match_marg != NULL) {
  507. const char *strp;
  508. next_match = match_marg->replacement_text;
  509. strp = next_match + strlen(next_match);
  510. while (strp > next_match)
  511. unput(*--strp);
  512. /* Skip past the unexpanded macro arg. */
  513. body_pos -= match.rm_eo - match.rm_so;
  514. }
  515. }
  516. /* Cleanup replacement text. */
  517. STAILQ_FOREACH(marg, &macro_symbol->info.macroinfo->args, links) {
  518. free(marg->replacement_text);
  519. }
  520. }
  521. /*
  522. * Find the next substitution in the macro working backwards from
  523. * body_pos until the beginning of the macro buffer. next_match
  524. * should be initialized to the beginning of the macro buffer prior
  525. * to calling this routine.
  526. */
  527. static void
  528. next_substitution(struct symbol *mac_symbol, const char *body_pos,
  529. const char **next_match, struct macro_arg **match_marg,
  530. regmatch_t *match)
  531. {
  532. regmatch_t matches[2];
  533. struct macro_arg *marg;
  534. const char *search_pos;
  535. int retval;
  536. do {
  537. search_pos = *next_match;
  538. STAILQ_FOREACH(marg, &mac_symbol->info.macroinfo->args, links) {
  539. retval = regexec(&marg->arg_regex, search_pos, 2,
  540. matches, 0);
  541. if (retval == 0
  542. && (matches[1].rm_eo + search_pos) <= body_pos
  543. && (matches[1].rm_eo + search_pos) > *next_match) {
  544. *match = matches[1];
  545. *next_match = match->rm_eo + search_pos;
  546. *match_marg = marg;
  547. }
  548. }
  549. } while (search_pos != *next_match);
  550. }
  551. int
  552. yywrap()
  553. {
  554. include_t *include;
  555. yy_delete_buffer(YY_CURRENT_BUFFER);
  556. (void)fclose(yyin);
  557. if (yyfilename != NULL)
  558. free(yyfilename);
  559. yyfilename = NULL;
  560. include = include_stack.slh_first;
  561. if (include != NULL) {
  562. yy_switch_to_buffer(include->buffer);
  563. yylineno = include->lineno;
  564. yyfilename = include->filename;
  565. SLIST_REMOVE_HEAD(&include_stack, links);
  566. free(include);
  567. return (0);
  568. }
  569. return (1);
  570. }