1c5cb3888SJustin T. Gibbs %{ 2098ca2bdSWarner Losh /*- 3c5cb3888SJustin T. Gibbs * Lexical Analyzer for the Aic7xxx SCSI Host adapter sequencer assembler. 4c5cb3888SJustin T. Gibbs * 5*718cf2ccSPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 6*718cf2ccSPedro F. Giffuni * 77ce72dbaSJustin T. Gibbs * Copyright (c) 1997, 1998, 2000 Justin T. Gibbs. 863183d8cSJustin T. Gibbs * Copyright (c) 2001, 2002 Adaptec Inc. 9c5cb3888SJustin T. Gibbs * All rights reserved. 10c5cb3888SJustin T. Gibbs * 11c5cb3888SJustin T. Gibbs * Redistribution and use in source and binary forms, with or without 12c5cb3888SJustin T. Gibbs * modification, are permitted provided that the following conditions 13c5cb3888SJustin T. Gibbs * are met: 14c5cb3888SJustin T. Gibbs * 1. Redistributions of source code must retain the above copyright 15f68f348bSJustin T. Gibbs * notice, this list of conditions, and the following disclaimer, 1641c47eeeSJustin T. Gibbs * without modification. 177ce72dbaSJustin T. Gibbs * 2. Redistributions in binary form must reproduce at minimum a disclaimer 187ce72dbaSJustin T. Gibbs * substantially similar to the "NO WARRANTY" disclaimer below 197ce72dbaSJustin T. Gibbs * ("Disclaimer") and any redistribution must be conditioned upon 207ce72dbaSJustin T. Gibbs * including a substantially similar Disclaimer requirement for further 217ce72dbaSJustin T. Gibbs * binary redistribution. 227ce72dbaSJustin T. Gibbs * 3. Neither the names of the above-listed copyright holders nor the names 237ce72dbaSJustin T. Gibbs * of any contributors may be used to endorse or promote products derived 247ce72dbaSJustin T. Gibbs * from this software without specific prior written permission. 25c5cb3888SJustin T. Gibbs * 26aa6dfd9dSJustin T. Gibbs * Alternatively, this software may be distributed under the terms of the 277ce72dbaSJustin T. Gibbs * GNU General Public License ("GPL") version 2 as published by the Free 287ce72dbaSJustin T. Gibbs * Software Foundation. 29aa6dfd9dSJustin T. Gibbs * 307ce72dbaSJustin T. Gibbs * NO WARRANTY 317ce72dbaSJustin T. Gibbs * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 327ce72dbaSJustin T. Gibbs * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 337ce72dbaSJustin T. Gibbs * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 347ce72dbaSJustin T. Gibbs * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 357ce72dbaSJustin T. Gibbs * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36c5cb3888SJustin T. Gibbs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37c5cb3888SJustin T. Gibbs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 387ce72dbaSJustin T. Gibbs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 397ce72dbaSJustin T. Gibbs * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 407ce72dbaSJustin T. Gibbs * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 417ce72dbaSJustin T. Gibbs * POSSIBILITY OF SUCH DAMAGES. 42c5cb3888SJustin T. Gibbs * 43708d2cb0SJustin T. Gibbs * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_scan.l#19 $ 44c5cb3888SJustin T. Gibbs */ 45c5cb3888SJustin T. Gibbs 4660b161a9SBruce Evans #include <sys/types.h> 4760b161a9SBruce Evans 4899ddedd8SJustin T. Gibbs #include <inttypes.h> 49c5cb3888SJustin T. Gibbs #include <limits.h> 507ce72dbaSJustin T. Gibbs #include <regex.h> 51c5cb3888SJustin T. Gibbs #include <stdio.h> 52c5cb3888SJustin T. Gibbs #include <string.h> 53c5cb3888SJustin T. Gibbs #include <sysexits.h> 54c5cb3888SJustin T. Gibbs #include <sys/queue.h> 55c5cb3888SJustin T. Gibbs 56c66dbc92SJustin T. Gibbs #include "aicasm.h" 57c66dbc92SJustin T. Gibbs #include "aicasm_symbol.h" 587ce72dbaSJustin T. Gibbs #include "aicasm_gram.h" 593bafc9d4SJustin T. Gibbs 607ce72dbaSJustin T. Gibbs /* This is used for macro body capture too, so err on the large size. */ 617ce72dbaSJustin T. Gibbs #define MAX_STR_CONST 4096 627ce72dbaSJustin T. Gibbs static char string_buf[MAX_STR_CONST]; 637ce72dbaSJustin T. Gibbs static char *string_buf_ptr; 647ce72dbaSJustin T. Gibbs static int parren_count; 657ce72dbaSJustin T. Gibbs static int quote_count; 66b18a2ef1SXin LI static char msgbuf[255]; 67b18a2ef1SXin LI 68b18a2ef1SXin LI extern int yylex(void); 69b18a2ef1SXin LI extern int mmlex(void); 70b18a2ef1SXin LI extern int mmparse(void); 71b18a2ef1SXin LI extern void mm_switch_to_buffer(YY_BUFFER_STATE); 72b18a2ef1SXin LI extern void mm_delete_buffer(YY_BUFFER_STATE); 73c5cb3888SJustin T. Gibbs %} 74c5cb3888SJustin T. Gibbs 75487d088eSDimitry Andric %option noinput 76487d088eSDimitry Andric 777ce72dbaSJustin T. Gibbs PATH ([/]*[-A-Za-z0-9_.])+ 78c5cb3888SJustin T. Gibbs WORD [A-Za-z_][-A-Za-z_0-9]* 79c5cb3888SJustin T. Gibbs SPACE [ \t]+ 807ce72dbaSJustin T. Gibbs MCARG [^(), \t]+ 817ce72dbaSJustin T. Gibbs MBODY ((\\[^\n])*[^\n\\]*)+ 82c5cb3888SJustin T. Gibbs 83c5cb3888SJustin T. Gibbs %x COMMENT 843bafc9d4SJustin T. Gibbs %x CEXPR 853bafc9d4SJustin T. Gibbs %x INCLUDE 862d0fbde8SJustin T. Gibbs %x STRING 877ce72dbaSJustin T. Gibbs %x MACRODEF 887ce72dbaSJustin T. Gibbs %x MACROARGLIST 897ce72dbaSJustin T. Gibbs %x MACROCALLARGS 907ce72dbaSJustin T. Gibbs %x MACROBODY 91c5cb3888SJustin T. Gibbs 92c5cb3888SJustin T. Gibbs %% 93c5cb3888SJustin T. Gibbs \n { ++yylineno; } 94708d2cb0SJustin T. Gibbs \r ; 95c5cb3888SJustin T. Gibbs "/*" { BEGIN COMMENT; /* Enter comment eating state */ } 96c5cb3888SJustin T. Gibbs <COMMENT>"/*" { fprintf(stderr, "Warning! Comment within comment."); } 97c5cb3888SJustin T. Gibbs <COMMENT>\n { ++yylineno; } 98c5cb3888SJustin T. Gibbs <COMMENT>[^*/\n]* ; 99c5cb3888SJustin T. Gibbs <COMMENT>"*"+[^*/\n]* ; 100c5cb3888SJustin T. Gibbs <COMMENT>"/"+[^*/\n]* ; 101c5cb3888SJustin T. Gibbs <COMMENT>"*"+"/" { BEGIN INITIAL; } 1023bafc9d4SJustin T. Gibbs if[ \t]*\( { 1033bafc9d4SJustin T. Gibbs string_buf_ptr = string_buf; 1043bafc9d4SJustin T. Gibbs parren_count = 1; 1053bafc9d4SJustin T. Gibbs BEGIN CEXPR; 1063bafc9d4SJustin T. Gibbs return T_IF; 1073bafc9d4SJustin T. Gibbs } 1083bafc9d4SJustin T. Gibbs <CEXPR>\( { *string_buf_ptr++ = '('; parren_count++; } 1093bafc9d4SJustin T. Gibbs <CEXPR>\) { 1103bafc9d4SJustin T. Gibbs parren_count--; 1113bafc9d4SJustin T. Gibbs if (parren_count == 0) { 1123bafc9d4SJustin T. Gibbs /* All done */ 1133bafc9d4SJustin T. Gibbs BEGIN INITIAL; 1143bafc9d4SJustin T. Gibbs *string_buf_ptr = '\0'; 1153bafc9d4SJustin T. Gibbs yylval.sym = symtable_get(string_buf); 1163bafc9d4SJustin T. Gibbs return T_CEXPR; 1173bafc9d4SJustin T. Gibbs } else { 1183bafc9d4SJustin T. Gibbs *string_buf_ptr++ = ')'; 1193bafc9d4SJustin T. Gibbs } 1203bafc9d4SJustin T. Gibbs } 1213bafc9d4SJustin T. Gibbs <CEXPR>\n { ++yylineno; } 122708d2cb0SJustin T. Gibbs <CEXPR>\r ; 1233bafc9d4SJustin T. Gibbs <CEXPR>[^()\n]+ { 1242d0fbde8SJustin T. Gibbs char *yptr; 1253bafc9d4SJustin T. Gibbs 1262d0fbde8SJustin T. Gibbs yptr = yytext; 12732da3127SJustin T. Gibbs while (*yptr != '\0') { 12832da3127SJustin T. Gibbs /* Remove duplicate spaces */ 12932da3127SJustin T. Gibbs if (*yptr == '\t') 13032da3127SJustin T. Gibbs *yptr = ' '; 13132da3127SJustin T. Gibbs if (*yptr == ' ' 13232da3127SJustin T. Gibbs && string_buf_ptr != string_buf 13332da3127SJustin T. Gibbs && string_buf_ptr[-1] == ' ') 13432da3127SJustin T. Gibbs yptr++; 13532da3127SJustin T. Gibbs else 1363bafc9d4SJustin T. Gibbs *string_buf_ptr++ = *yptr++; 1373bafc9d4SJustin T. Gibbs } 13832da3127SJustin T. Gibbs } 139c5cb3888SJustin T. Gibbs 1402d0fbde8SJustin T. Gibbs VERSION { return T_VERSION; } 14163183d8cSJustin T. Gibbs PREFIX { return T_PREFIX; } 1427ce72dbaSJustin T. Gibbs PATCH_ARG_LIST { return T_PATCH_ARG_LIST; } 1432d0fbde8SJustin T. Gibbs \" { 1442d0fbde8SJustin T. Gibbs string_buf_ptr = string_buf; 1452d0fbde8SJustin T. Gibbs BEGIN STRING; 1462d0fbde8SJustin T. Gibbs } 1472d0fbde8SJustin T. Gibbs <STRING>[^"]+ { 1482d0fbde8SJustin T. Gibbs char *yptr; 1492d0fbde8SJustin T. Gibbs 1502d0fbde8SJustin T. Gibbs yptr = yytext; 1512d0fbde8SJustin T. Gibbs while (*yptr) 1522d0fbde8SJustin T. Gibbs *string_buf_ptr++ = *yptr++; 1532d0fbde8SJustin T. Gibbs } 1542d0fbde8SJustin T. Gibbs <STRING>\" { 1552d0fbde8SJustin T. Gibbs /* All done */ 1562d0fbde8SJustin T. Gibbs BEGIN INITIAL; 1572d0fbde8SJustin T. Gibbs *string_buf_ptr = '\0'; 1582d0fbde8SJustin T. Gibbs yylval.str = string_buf; 1592d0fbde8SJustin T. Gibbs return T_STRING; 1602d0fbde8SJustin T. Gibbs } 161c5cb3888SJustin T. Gibbs {SPACE} ; 162c5cb3888SJustin T. Gibbs 163c5cb3888SJustin T. Gibbs /* Register/SCB/SRAM definition keywords */ 1647ce72dbaSJustin T. Gibbs export { return T_EXPORT; } 165c5cb3888SJustin T. Gibbs register { return T_REGISTER; } 166c5cb3888SJustin T. Gibbs const { yylval.value = FALSE; return T_CONST; } 16737507c1bSJustin T. Gibbs download { return T_DOWNLOAD; } 168c5cb3888SJustin T. Gibbs address { return T_ADDRESS; } 169c5cb3888SJustin T. Gibbs access_mode { return T_ACCESS_MODE; } 1707ce72dbaSJustin T. Gibbs modes { return T_MODES; } 171c5cb3888SJustin T. Gibbs RW|RO|WO { 172c5cb3888SJustin T. Gibbs if (strcmp(yytext, "RW") == 0) 173c5cb3888SJustin T. Gibbs yylval.value = RW; 174c5cb3888SJustin T. Gibbs else if (strcmp(yytext, "RO") == 0) 175c5cb3888SJustin T. Gibbs yylval.value = RO; 176c5cb3888SJustin T. Gibbs else 177c5cb3888SJustin T. Gibbs yylval.value = WO; 178c5cb3888SJustin T. Gibbs return T_MODE; 179c5cb3888SJustin T. Gibbs } 180083d01f2SJustin T. Gibbs BEGIN_CRITICAL { return T_BEGIN_CS; } 181083d01f2SJustin T. Gibbs END_CRITICAL { return T_END_CS; } 1827ce72dbaSJustin T. Gibbs SET_SRC_MODE { return T_SET_SRC_MODE; } 1837ce72dbaSJustin T. Gibbs SET_DST_MODE { return T_SET_DST_MODE; } 18463183d8cSJustin T. Gibbs field { return T_FIELD; } 18563183d8cSJustin T. Gibbs enum { return T_ENUM; } 186c5cb3888SJustin T. Gibbs mask { return T_MASK; } 187c5cb3888SJustin T. Gibbs alias { return T_ALIAS; } 188c5cb3888SJustin T. Gibbs size { return T_SIZE; } 189c5cb3888SJustin T. Gibbs scb { return T_SCB; } 190c5cb3888SJustin T. Gibbs scratch_ram { return T_SRAM; } 191c5cb3888SJustin T. Gibbs accumulator { return T_ACCUM; } 1927ce72dbaSJustin T. Gibbs mode_pointer { return T_MODE_PTR; } 193c5cb3888SJustin T. Gibbs allones { return T_ALLONES; } 194c5cb3888SJustin T. Gibbs allzeros { return T_ALLZEROS; } 195c5cb3888SJustin T. Gibbs none { return T_NONE; } 196c5cb3888SJustin T. Gibbs sindex { return T_SINDEX; } 197c5cb3888SJustin T. Gibbs A { return T_A; } 198c5cb3888SJustin T. Gibbs 199c5cb3888SJustin T. Gibbs /* Opcodes */ 200c5cb3888SJustin T. Gibbs shl { return T_SHL; } 201c5cb3888SJustin T. Gibbs shr { return T_SHR; } 202c5cb3888SJustin T. Gibbs ror { return T_ROR; } 203c5cb3888SJustin T. Gibbs rol { return T_ROL; } 204c5cb3888SJustin T. Gibbs mvi { return T_MVI; } 205c5cb3888SJustin T. Gibbs mov { return T_MOV; } 206c5cb3888SJustin T. Gibbs clr { return T_CLR; } 207c5cb3888SJustin T. Gibbs jmp { return T_JMP; } 208c5cb3888SJustin T. Gibbs jc { return T_JC; } 209c5cb3888SJustin T. Gibbs jnc { return T_JNC; } 210c5cb3888SJustin T. Gibbs je { return T_JE; } 211c5cb3888SJustin T. Gibbs jne { return T_JNE; } 212c5cb3888SJustin T. Gibbs jz { return T_JZ; } 213c5cb3888SJustin T. Gibbs jnz { return T_JNZ; } 214c5cb3888SJustin T. Gibbs call { return T_CALL; } 215c5cb3888SJustin T. Gibbs add { return T_ADD; } 216c5cb3888SJustin T. Gibbs adc { return T_ADC; } 2173bafc9d4SJustin T. Gibbs bmov { return T_BMOV; } 218c5cb3888SJustin T. Gibbs inc { return T_INC; } 219c5cb3888SJustin T. Gibbs dec { return T_DEC; } 220c5cb3888SJustin T. Gibbs stc { return T_STC; } 221c5cb3888SJustin T. Gibbs clc { return T_CLC; } 222c5cb3888SJustin T. Gibbs cmp { return T_CMP; } 223aa6dfd9dSJustin T. Gibbs not { return T_NOT; } 224c5cb3888SJustin T. Gibbs xor { return T_XOR; } 225c5cb3888SJustin T. Gibbs test { return T_TEST;} 226c5cb3888SJustin T. Gibbs and { return T_AND; } 227c5cb3888SJustin T. Gibbs or { return T_OR; } 228c5cb3888SJustin T. Gibbs ret { return T_RET; } 229c5cb3888SJustin T. Gibbs nop { return T_NOP; } 2303bafc9d4SJustin T. Gibbs else { return T_ELSE; } 231c5cb3888SJustin T. Gibbs 232c5cb3888SJustin T. Gibbs /* Allowed Symbols */ 2337ce72dbaSJustin T. Gibbs \<\< { return T_EXPR_LSHIFT; } 2347ce72dbaSJustin T. Gibbs \>\> { return T_EXPR_RSHIFT; } 2357ce72dbaSJustin T. Gibbs [-+,:()~|&."{};<>[\]/*!=] { return yytext[0]; } 236c5cb3888SJustin T. Gibbs 237c5cb3888SJustin T. Gibbs /* Number processing */ 238c5cb3888SJustin T. Gibbs 0[0-7]* { 239c5cb3888SJustin T. Gibbs yylval.value = strtol(yytext, NULL, 8); 240c5cb3888SJustin T. Gibbs return T_NUMBER; 241c5cb3888SJustin T. Gibbs } 242c5cb3888SJustin T. Gibbs 243c5cb3888SJustin T. Gibbs 0[xX][0-9a-fA-F]+ { 244c5cb3888SJustin T. Gibbs yylval.value = strtoul(yytext + 2, NULL, 16); 245c5cb3888SJustin T. Gibbs return T_NUMBER; 246c5cb3888SJustin T. Gibbs } 247c5cb3888SJustin T. Gibbs 248c5cb3888SJustin T. Gibbs [1-9][0-9]* { 249c5cb3888SJustin T. Gibbs yylval.value = strtol(yytext, NULL, 10); 250c5cb3888SJustin T. Gibbs return T_NUMBER; 251c5cb3888SJustin T. Gibbs } 252c5cb3888SJustin T. Gibbs /* Include Files */ 2532d0fbde8SJustin T. Gibbs #include{SPACE} { 2542d0fbde8SJustin T. Gibbs BEGIN INCLUDE; 2552d0fbde8SJustin T. Gibbs quote_count = 0; 2562d0fbde8SJustin T. Gibbs return T_INCLUDE; 2572d0fbde8SJustin T. Gibbs } 2582d0fbde8SJustin T. Gibbs <INCLUDE>[<] { return yytext[0]; } 2592d0fbde8SJustin T. Gibbs <INCLUDE>[>] { BEGIN INITIAL; return yytext[0]; } 2602d0fbde8SJustin T. Gibbs <INCLUDE>[\"] { 2612d0fbde8SJustin T. Gibbs if (quote_count != 0) 2622d0fbde8SJustin T. Gibbs BEGIN INITIAL; 2632d0fbde8SJustin T. Gibbs quote_count++; 2642d0fbde8SJustin T. Gibbs return yytext[0]; 2652d0fbde8SJustin T. Gibbs } 2667ce72dbaSJustin T. Gibbs <INCLUDE>{PATH} { 2672d0fbde8SJustin T. Gibbs char *yptr; 2682d0fbde8SJustin T. Gibbs 2692d0fbde8SJustin T. Gibbs yptr = yytext; 2702d0fbde8SJustin T. Gibbs string_buf_ptr = string_buf; 2712d0fbde8SJustin T. Gibbs while (*yptr) 2722d0fbde8SJustin T. Gibbs *string_buf_ptr++ = *yptr++; 2732d0fbde8SJustin T. Gibbs yylval.str = string_buf; 2742d0fbde8SJustin T. Gibbs *string_buf_ptr = '\0'; 2752d0fbde8SJustin T. Gibbs return T_PATH; 2762d0fbde8SJustin T. Gibbs } 2777ce72dbaSJustin T. Gibbs <INCLUDE>. { stop("Invalid include line", EX_DATAERR); } 2787ce72dbaSJustin T. Gibbs #define{SPACE} { 2797ce72dbaSJustin T. Gibbs BEGIN MACRODEF; 2807ce72dbaSJustin T. Gibbs return T_DEFINE; 2817ce72dbaSJustin T. Gibbs } 2827ce72dbaSJustin T. Gibbs <MACRODEF>{WORD}{SPACE} { 2837ce72dbaSJustin T. Gibbs char *yptr; 284c5cb3888SJustin T. Gibbs 2857ce72dbaSJustin T. Gibbs /* Strip space and return as a normal symbol */ 2867ce72dbaSJustin T. Gibbs yptr = yytext; 2877ce72dbaSJustin T. Gibbs while (*yptr != ' ' && *yptr != '\t') 2887ce72dbaSJustin T. Gibbs yptr++; 2897ce72dbaSJustin T. Gibbs *yptr = '\0'; 2907ce72dbaSJustin T. Gibbs yylval.sym = symtable_get(yytext); 2917ce72dbaSJustin T. Gibbs string_buf_ptr = string_buf; 2927ce72dbaSJustin T. Gibbs BEGIN MACROBODY; 2937ce72dbaSJustin T. Gibbs return T_SYMBOL; 2947ce72dbaSJustin T. Gibbs } 2957ce72dbaSJustin T. Gibbs <MACRODEF>{WORD}\( { 2967ce72dbaSJustin T. Gibbs /* 2977ce72dbaSJustin T. Gibbs * We store the symbol with its opening 2987ce72dbaSJustin T. Gibbs * parren so we can differentiate macros 2997ce72dbaSJustin T. Gibbs * that take args from macros with the 3007ce72dbaSJustin T. Gibbs * same name that do not take args as 3017ce72dbaSJustin T. Gibbs * is allowed in C. 3027ce72dbaSJustin T. Gibbs */ 3037ce72dbaSJustin T. Gibbs BEGIN MACROARGLIST; 3047ce72dbaSJustin T. Gibbs yylval.sym = symtable_get(yytext); 3057ce72dbaSJustin T. Gibbs unput('('); 3067ce72dbaSJustin T. Gibbs return T_SYMBOL; 3077ce72dbaSJustin T. Gibbs } 3087ce72dbaSJustin T. Gibbs <MACROARGLIST>{WORD} { 3097ce72dbaSJustin T. Gibbs yylval.str = yytext; 3107ce72dbaSJustin T. Gibbs return T_ARG; 3117ce72dbaSJustin T. Gibbs } 3127ce72dbaSJustin T. Gibbs <MACROARGLIST>{SPACE} ; 3137ce72dbaSJustin T. Gibbs <MACROARGLIST>[(,] { 3147ce72dbaSJustin T. Gibbs return yytext[0]; 3157ce72dbaSJustin T. Gibbs } 3167ce72dbaSJustin T. Gibbs <MACROARGLIST>[)] { 3177ce72dbaSJustin T. Gibbs string_buf_ptr = string_buf; 3187ce72dbaSJustin T. Gibbs BEGIN MACROBODY; 3197ce72dbaSJustin T. Gibbs return ')'; 3207ce72dbaSJustin T. Gibbs } 3217ce72dbaSJustin T. Gibbs <MACROARGLIST>. { 322b18a2ef1SXin LI snprintf(msgbuf, sizeof(msgbuf), "Invalid character " 3237ce72dbaSJustin T. Gibbs "'%c' in macro argument list", 3247ce72dbaSJustin T. Gibbs yytext[0]); 325b18a2ef1SXin LI stop(msgbuf, EX_DATAERR); 3267ce72dbaSJustin T. Gibbs } 3277ce72dbaSJustin T. Gibbs <MACROCALLARGS>{SPACE} ; 3287ce72dbaSJustin T. Gibbs <MACROCALLARGS>\( { 3297ce72dbaSJustin T. Gibbs parren_count++; 3307ce72dbaSJustin T. Gibbs if (parren_count == 1) 3317ce72dbaSJustin T. Gibbs return ('('); 3327ce72dbaSJustin T. Gibbs *string_buf_ptr++ = '('; 3337ce72dbaSJustin T. Gibbs } 3347ce72dbaSJustin T. Gibbs <MACROCALLARGS>\) { 3357ce72dbaSJustin T. Gibbs parren_count--; 3367ce72dbaSJustin T. Gibbs if (parren_count == 0) { 3377ce72dbaSJustin T. Gibbs BEGIN INITIAL; 3387ce72dbaSJustin T. Gibbs return (')'); 3397ce72dbaSJustin T. Gibbs } 3407ce72dbaSJustin T. Gibbs *string_buf_ptr++ = ')'; 3417ce72dbaSJustin T. Gibbs } 3427ce72dbaSJustin T. Gibbs <MACROCALLARGS>{MCARG} { 3437ce72dbaSJustin T. Gibbs char *yptr; 344c5cb3888SJustin T. Gibbs 3457ce72dbaSJustin T. Gibbs yptr = yytext; 3467ce72dbaSJustin T. Gibbs while (*yptr) 3477ce72dbaSJustin T. Gibbs *string_buf_ptr++ = *yptr++; 3487ce72dbaSJustin T. Gibbs } 3497ce72dbaSJustin T. Gibbs <MACROCALLARGS>\, { 3507ce72dbaSJustin T. Gibbs if (string_buf_ptr != string_buf) { 3517ce72dbaSJustin T. Gibbs /* 3527ce72dbaSJustin T. Gibbs * Return an argument and 3537ce72dbaSJustin T. Gibbs * rescan this comma so we 3547ce72dbaSJustin T. Gibbs * can return it as well. 3557ce72dbaSJustin T. Gibbs */ 3567ce72dbaSJustin T. Gibbs *string_buf_ptr = '\0'; 3577ce72dbaSJustin T. Gibbs yylval.str = string_buf; 3587ce72dbaSJustin T. Gibbs string_buf_ptr = string_buf; 3597ce72dbaSJustin T. Gibbs unput(','); 3607ce72dbaSJustin T. Gibbs return T_ARG; 3617ce72dbaSJustin T. Gibbs } 3627ce72dbaSJustin T. Gibbs return ','; 3637ce72dbaSJustin T. Gibbs } 3647ce72dbaSJustin T. Gibbs <MACROBODY>\\\n { 3657ce72dbaSJustin T. Gibbs /* Eat escaped newlines. */ 3667ce72dbaSJustin T. Gibbs ++yylineno; 3677ce72dbaSJustin T. Gibbs } 368708d2cb0SJustin T. Gibbs <MACROBODY>\r ; 3697ce72dbaSJustin T. Gibbs <MACROBODY>\n { 3707ce72dbaSJustin T. Gibbs /* Macros end on the first unescaped newline. */ 3717ce72dbaSJustin T. Gibbs BEGIN INITIAL; 3727ce72dbaSJustin T. Gibbs *string_buf_ptr = '\0'; 3737ce72dbaSJustin T. Gibbs yylval.str = string_buf; 3747ce72dbaSJustin T. Gibbs ++yylineno; 3757ce72dbaSJustin T. Gibbs return T_MACROBODY; 3767ce72dbaSJustin T. Gibbs } 3777ce72dbaSJustin T. Gibbs <MACROBODY>{MBODY} { 3787ce72dbaSJustin T. Gibbs char *yptr; 379708d2cb0SJustin T. Gibbs char c; 3807ce72dbaSJustin T. Gibbs 3817ce72dbaSJustin T. Gibbs yptr = yytext; 382b18a2ef1SXin LI while ((c = *yptr++)) { 383708d2cb0SJustin T. Gibbs /* 384708d2cb0SJustin T. Gibbs * Strip carriage returns. 385708d2cb0SJustin T. Gibbs */ 386708d2cb0SJustin T. Gibbs if (c == '\r') 387708d2cb0SJustin T. Gibbs continue; 388708d2cb0SJustin T. Gibbs *string_buf_ptr++ = c; 389708d2cb0SJustin T. Gibbs } 3907ce72dbaSJustin T. Gibbs } 3917ce72dbaSJustin T. Gibbs {WORD}\( { 3927ce72dbaSJustin T. Gibbs char *yptr; 3937ce72dbaSJustin T. Gibbs char *ycopy; 3947ce72dbaSJustin T. Gibbs 3957ce72dbaSJustin T. Gibbs /* May be a symbol or a macro invocation. */ 3967ce72dbaSJustin T. Gibbs yylval.sym = symtable_get(yytext); 3977ce72dbaSJustin T. Gibbs if (yylval.sym->type == MACRO) { 3987ce72dbaSJustin T. Gibbs YY_BUFFER_STATE old_state; 3997ce72dbaSJustin T. Gibbs YY_BUFFER_STATE temp_state; 4007ce72dbaSJustin T. Gibbs 4017ce72dbaSJustin T. Gibbs ycopy = strdup(yytext); 4027ce72dbaSJustin T. Gibbs yptr = ycopy + yyleng; 4037ce72dbaSJustin T. Gibbs while (yptr > ycopy) 4047ce72dbaSJustin T. Gibbs unput(*--yptr); 4057ce72dbaSJustin T. Gibbs old_state = YY_CURRENT_BUFFER; 4067ce72dbaSJustin T. Gibbs temp_state = 4077ce72dbaSJustin T. Gibbs yy_create_buffer(stdin, 4087ce72dbaSJustin T. Gibbs YY_BUF_SIZE); 4097ce72dbaSJustin T. Gibbs yy_switch_to_buffer(temp_state); 4107ce72dbaSJustin T. Gibbs mm_switch_to_buffer(old_state); 4117ce72dbaSJustin T. Gibbs mmparse(); 4127ce72dbaSJustin T. Gibbs mm_switch_to_buffer(temp_state); 4137ce72dbaSJustin T. Gibbs yy_switch_to_buffer(old_state); 4147ce72dbaSJustin T. Gibbs mm_delete_buffer(temp_state); 4157ce72dbaSJustin T. Gibbs expand_macro(yylval.sym); 4167ce72dbaSJustin T. Gibbs } else { 4177ce72dbaSJustin T. Gibbs if (yylval.sym->type == UNINITIALIZED) { 4187ce72dbaSJustin T. Gibbs /* Try without the '(' */ 4197ce72dbaSJustin T. Gibbs symbol_delete(yylval.sym); 4207ce72dbaSJustin T. Gibbs yytext[yyleng-1] = '\0'; 4217ce72dbaSJustin T. Gibbs yylval.sym = 4227ce72dbaSJustin T. Gibbs symtable_get(yytext); 4237ce72dbaSJustin T. Gibbs } 4247ce72dbaSJustin T. Gibbs unput('('); 4257ce72dbaSJustin T. Gibbs return T_SYMBOL; 4267ce72dbaSJustin T. Gibbs } 4277ce72dbaSJustin T. Gibbs } 4287ce72dbaSJustin T. Gibbs {WORD} { 4297ce72dbaSJustin T. Gibbs yylval.sym = symtable_get(yytext); 4307ce72dbaSJustin T. Gibbs if (yylval.sym->type == MACRO) { 4317ce72dbaSJustin T. Gibbs expand_macro(yylval.sym); 4327ce72dbaSJustin T. Gibbs } else { 4337ce72dbaSJustin T. Gibbs return T_SYMBOL; 4347ce72dbaSJustin T. Gibbs } 4357ce72dbaSJustin T. Gibbs } 436c5cb3888SJustin T. Gibbs . { 437b18a2ef1SXin LI snprintf(msgbuf, sizeof(msgbuf), "Invalid character " 438c5cb3888SJustin T. Gibbs "'%c'", yytext[0]); 439b18a2ef1SXin LI stop(msgbuf, EX_DATAERR); 440c5cb3888SJustin T. Gibbs } 441c5cb3888SJustin T. Gibbs %% 442c5cb3888SJustin T. Gibbs 443c5cb3888SJustin T. Gibbs typedef struct include { 444c5cb3888SJustin T. Gibbs YY_BUFFER_STATE buffer; 445c5cb3888SJustin T. Gibbs int lineno; 446c5cb3888SJustin T. Gibbs char *filename; 447e3975643SJake Burkholder SLIST_ENTRY(include) links; 448c5cb3888SJustin T. Gibbs }include_t; 449c5cb3888SJustin T. Gibbs 450e3975643SJake Burkholder SLIST_HEAD(, include) include_stack; 451c5cb3888SJustin T. Gibbs 452c5cb3888SJustin T. Gibbs void 45332da3127SJustin T. Gibbs include_file(char *file_name, include_type type) 454c5cb3888SJustin T. Gibbs { 455c5cb3888SJustin T. Gibbs FILE *newfile; 456c5cb3888SJustin T. Gibbs include_t *include; 457c5cb3888SJustin T. Gibbs 458c5cb3888SJustin T. Gibbs newfile = NULL; 459c5cb3888SJustin T. Gibbs /* Try the current directory first */ 460c5cb3888SJustin T. Gibbs if (includes_search_curdir != 0 || type == SOURCE_FILE) 461c5cb3888SJustin T. Gibbs newfile = fopen(file_name, "r"); 462c5cb3888SJustin T. Gibbs 463c5cb3888SJustin T. Gibbs if (newfile == NULL && type != SOURCE_FILE) { 464c5cb3888SJustin T. Gibbs path_entry_t include_dir; 465c5cb3888SJustin T. Gibbs for (include_dir = search_path.slh_first; 466c5cb3888SJustin T. Gibbs include_dir != NULL; 467c5cb3888SJustin T. Gibbs include_dir = include_dir->links.sle_next) { 468c5cb3888SJustin T. Gibbs char fullname[PATH_MAX]; 469c5cb3888SJustin T. Gibbs 470c5cb3888SJustin T. Gibbs if ((include_dir->quoted_includes_only == TRUE) 471c5cb3888SJustin T. Gibbs && (type != QUOTED_INCLUDE)) 472c5cb3888SJustin T. Gibbs continue; 473c5cb3888SJustin T. Gibbs 474c5cb3888SJustin T. Gibbs snprintf(fullname, sizeof(fullname), 475c5cb3888SJustin T. Gibbs "%s/%s", include_dir->directory, file_name); 476c5cb3888SJustin T. Gibbs 477c5cb3888SJustin T. Gibbs if ((newfile = fopen(fullname, "r")) != NULL) 478c5cb3888SJustin T. Gibbs break; 479c5cb3888SJustin T. Gibbs } 480c5cb3888SJustin T. Gibbs } 481c5cb3888SJustin T. Gibbs 482c5cb3888SJustin T. Gibbs if (newfile == NULL) { 483c5cb3888SJustin T. Gibbs perror(file_name); 484c5cb3888SJustin T. Gibbs stop("Unable to open input file", EX_SOFTWARE); 485c5cb3888SJustin T. Gibbs /* NOTREACHED */ 486c5cb3888SJustin T. Gibbs } 487f68f348bSJustin T. Gibbs 488f68f348bSJustin T. Gibbs if (type != SOURCE_FILE) { 489c5cb3888SJustin T. Gibbs include = (include_t *)malloc(sizeof(include_t)); 490c5cb3888SJustin T. Gibbs if (include == NULL) { 491f68f348bSJustin T. Gibbs stop("Unable to allocate include stack entry", 492f68f348bSJustin T. Gibbs EX_SOFTWARE); 493c5cb3888SJustin T. Gibbs /* NOTREACHED */ 494c5cb3888SJustin T. Gibbs } 495c5cb3888SJustin T. Gibbs include->buffer = YY_CURRENT_BUFFER; 496c5cb3888SJustin T. Gibbs include->lineno = yylineno; 497c5cb3888SJustin T. Gibbs include->filename = yyfilename; 498c5cb3888SJustin T. Gibbs SLIST_INSERT_HEAD(&include_stack, include, links); 499f68f348bSJustin T. Gibbs } 500c5cb3888SJustin T. Gibbs yy_switch_to_buffer(yy_create_buffer(newfile, YY_BUF_SIZE)); 501c5cb3888SJustin T. Gibbs yylineno = 1; 502c5cb3888SJustin T. Gibbs yyfilename = strdup(file_name); 503c5cb3888SJustin T. Gibbs } 504c5cb3888SJustin T. Gibbs 5057ce72dbaSJustin T. Gibbs static void next_substitution(struct symbol *mac_symbol, const char *body_pos, 5067ce72dbaSJustin T. Gibbs const char **next_match, 5077ce72dbaSJustin T. Gibbs struct macro_arg **match_marg, regmatch_t *match); 5087ce72dbaSJustin T. Gibbs 5097ce72dbaSJustin T. Gibbs void 5107ce72dbaSJustin T. Gibbs expand_macro(struct symbol *macro_symbol) 5117ce72dbaSJustin T. Gibbs { 5127ce72dbaSJustin T. Gibbs struct macro_arg *marg; 5137ce72dbaSJustin T. Gibbs struct macro_arg *match_marg; 5147ce72dbaSJustin T. Gibbs const char *body_head; 5157ce72dbaSJustin T. Gibbs const char *body_pos; 5167ce72dbaSJustin T. Gibbs const char *next_match; 5175bb0de05SXin LI regmatch_t match = { .rm_so = 0, .rm_eo = 0 }; 5187ce72dbaSJustin T. Gibbs 5197ce72dbaSJustin T. Gibbs /* 5207ce72dbaSJustin T. Gibbs * Due to the nature of unput, we must work 5217ce72dbaSJustin T. Gibbs * backwards through the macro body performing 5227ce72dbaSJustin T. Gibbs * any expansions. 5237ce72dbaSJustin T. Gibbs */ 5247ce72dbaSJustin T. Gibbs body_head = macro_symbol->info.macroinfo->body; 5257ce72dbaSJustin T. Gibbs body_pos = body_head + strlen(body_head); 5267ce72dbaSJustin T. Gibbs while (body_pos > body_head) { 5277ce72dbaSJustin T. Gibbs next_match = body_head; 5287ce72dbaSJustin T. Gibbs match_marg = NULL; 5297ce72dbaSJustin T. Gibbs next_substitution(macro_symbol, body_pos, &next_match, 5307ce72dbaSJustin T. Gibbs &match_marg, &match); 5317ce72dbaSJustin T. Gibbs 5327ce72dbaSJustin T. Gibbs /* Put back everything up until the replacement. */ 5337ce72dbaSJustin T. Gibbs while (body_pos > next_match) 5347ce72dbaSJustin T. Gibbs unput(*--body_pos); 5357ce72dbaSJustin T. Gibbs 5367ce72dbaSJustin T. Gibbs /* Perform the replacement. */ 5377ce72dbaSJustin T. Gibbs if (match_marg != NULL) { 5387ce72dbaSJustin T. Gibbs const char *strp; 5397ce72dbaSJustin T. Gibbs 5407ce72dbaSJustin T. Gibbs next_match = match_marg->replacement_text; 5417ce72dbaSJustin T. Gibbs strp = next_match + strlen(next_match); 5427ce72dbaSJustin T. Gibbs while (strp > next_match) 5437ce72dbaSJustin T. Gibbs unput(*--strp); 5447ce72dbaSJustin T. Gibbs 5457ce72dbaSJustin T. Gibbs /* Skip past the unexpanded macro arg. */ 5467ce72dbaSJustin T. Gibbs body_pos -= match.rm_eo - match.rm_so; 5477ce72dbaSJustin T. Gibbs } 5487ce72dbaSJustin T. Gibbs } 5497ce72dbaSJustin T. Gibbs 5507ce72dbaSJustin T. Gibbs /* Cleanup replacement text. */ 5517ce72dbaSJustin T. Gibbs STAILQ_FOREACH(marg, ¯o_symbol->info.macroinfo->args, links) { 5527ce72dbaSJustin T. Gibbs free(marg->replacement_text); 5537ce72dbaSJustin T. Gibbs } 5547ce72dbaSJustin T. Gibbs } 5557ce72dbaSJustin T. Gibbs 5567ce72dbaSJustin T. Gibbs /* 5577ce72dbaSJustin T. Gibbs * Find the next substitution in the macro working backwards from 5587ce72dbaSJustin T. Gibbs * body_pos until the beginning of the macro buffer. next_match 5597ce72dbaSJustin T. Gibbs * should be initialized to the beginning of the macro buffer prior 5607ce72dbaSJustin T. Gibbs * to calling this routine. 5617ce72dbaSJustin T. Gibbs */ 5627ce72dbaSJustin T. Gibbs static void 5637ce72dbaSJustin T. Gibbs next_substitution(struct symbol *mac_symbol, const char *body_pos, 5647ce72dbaSJustin T. Gibbs const char **next_match, struct macro_arg **match_marg, 5657ce72dbaSJustin T. Gibbs regmatch_t *match) 5667ce72dbaSJustin T. Gibbs { 5677ce72dbaSJustin T. Gibbs regmatch_t matches[2]; 5687ce72dbaSJustin T. Gibbs struct macro_arg *marg; 5697ce72dbaSJustin T. Gibbs const char *search_pos; 5707ce72dbaSJustin T. Gibbs int retval; 5717ce72dbaSJustin T. Gibbs 5727ce72dbaSJustin T. Gibbs do { 5737ce72dbaSJustin T. Gibbs search_pos = *next_match; 5747ce72dbaSJustin T. Gibbs 5757ce72dbaSJustin T. Gibbs STAILQ_FOREACH(marg, &mac_symbol->info.macroinfo->args, links) { 5767ce72dbaSJustin T. Gibbs 5777ce72dbaSJustin T. Gibbs retval = regexec(&marg->arg_regex, search_pos, 2, 5787ce72dbaSJustin T. Gibbs matches, 0); 5797ce72dbaSJustin T. Gibbs if (retval == 0 5807ce72dbaSJustin T. Gibbs && (matches[1].rm_eo + search_pos) <= body_pos 5817ce72dbaSJustin T. Gibbs && (matches[1].rm_eo + search_pos) > *next_match) { 5827ce72dbaSJustin T. Gibbs *match = matches[1]; 5837ce72dbaSJustin T. Gibbs *next_match = match->rm_eo + search_pos; 5847ce72dbaSJustin T. Gibbs *match_marg = marg; 5857ce72dbaSJustin T. Gibbs } 5867ce72dbaSJustin T. Gibbs } 5877ce72dbaSJustin T. Gibbs } while (search_pos != *next_match); 5887ce72dbaSJustin T. Gibbs } 5897ce72dbaSJustin T. Gibbs 590c5cb3888SJustin T. Gibbs int 59173c4bad0SEd Schouten yywrap(void) 592c5cb3888SJustin T. Gibbs { 593c5cb3888SJustin T. Gibbs include_t *include; 594c5cb3888SJustin T. Gibbs 595c5cb3888SJustin T. Gibbs yy_delete_buffer(YY_CURRENT_BUFFER); 596c5cb3888SJustin T. Gibbs (void)fclose(yyin); 597c5cb3888SJustin T. Gibbs if (yyfilename != NULL) 598c5cb3888SJustin T. Gibbs free(yyfilename); 599f68f348bSJustin T. Gibbs yyfilename = NULL; 600c5cb3888SJustin T. Gibbs include = include_stack.slh_first; 601c5cb3888SJustin T. Gibbs if (include != NULL) { 602c5cb3888SJustin T. Gibbs yy_switch_to_buffer(include->buffer); 603c5cb3888SJustin T. Gibbs yylineno = include->lineno; 604c5cb3888SJustin T. Gibbs yyfilename = include->filename; 605c5cb3888SJustin T. Gibbs SLIST_REMOVE_HEAD(&include_stack, links); 606c5cb3888SJustin T. Gibbs free(include); 607c5cb3888SJustin T. Gibbs return (0); 608c5cb3888SJustin T. Gibbs } 609c5cb3888SJustin T. Gibbs return (1); 610c5cb3888SJustin T. Gibbs } 611