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