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