162306a36Sopenharmony_ci%{ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Lexical Analyzer for the Aic7xxx SCSI Host adapter sequencer assembler. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 1997, 1998, 2000 Justin T. Gibbs. 662306a36Sopenharmony_ci * Copyright (c) 2001, 2002 Adaptec Inc. 762306a36Sopenharmony_ci * All rights reserved. 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * Redistribution and use in source and binary forms, with or without 1062306a36Sopenharmony_ci * modification, are permitted provided that the following conditions 1162306a36Sopenharmony_ci * are met: 1262306a36Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright 1362306a36Sopenharmony_ci * notice, this list of conditions, and the following disclaimer, 1462306a36Sopenharmony_ci * without modification. 1562306a36Sopenharmony_ci * 2. Redistributions in binary form must reproduce at minimum a disclaimer 1662306a36Sopenharmony_ci * substantially similar to the "NO WARRANTY" disclaimer below 1762306a36Sopenharmony_ci * ("Disclaimer") and any redistribution must be conditioned upon 1862306a36Sopenharmony_ci * including a substantially similar Disclaimer requirement for further 1962306a36Sopenharmony_ci * binary redistribution. 2062306a36Sopenharmony_ci * 3. Neither the names of the above-listed copyright holders nor the names 2162306a36Sopenharmony_ci * of any contributors may be used to endorse or promote products derived 2262306a36Sopenharmony_ci * from this software without specific prior written permission. 2362306a36Sopenharmony_ci * 2462306a36Sopenharmony_ci * Alternatively, this software may be distributed under the terms of the 2562306a36Sopenharmony_ci * GNU General Public License ("GPL") version 2 as published by the Free 2662306a36Sopenharmony_ci * Software Foundation. 2762306a36Sopenharmony_ci * 2862306a36Sopenharmony_ci * NO WARRANTY 2962306a36Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 3062306a36Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3162306a36Sopenharmony_ci * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 3262306a36Sopenharmony_ci * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3362306a36Sopenharmony_ci * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3462306a36Sopenharmony_ci * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3562306a36Sopenharmony_ci * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3662306a36Sopenharmony_ci * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 3762306a36Sopenharmony_ci * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 3862306a36Sopenharmony_ci * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3962306a36Sopenharmony_ci * POSSIBILITY OF SUCH DAMAGES. 4062306a36Sopenharmony_ci * 4162306a36Sopenharmony_ci * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_scan.l#20 $ 4262306a36Sopenharmony_ci * 4362306a36Sopenharmony_ci * $FreeBSD$ 4462306a36Sopenharmony_ci */ 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci#include <sys/types.h> 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci#include <inttypes.h> 4962306a36Sopenharmony_ci#include <limits.h> 5062306a36Sopenharmony_ci#include <regex.h> 5162306a36Sopenharmony_ci#include <stdio.h> 5262306a36Sopenharmony_ci#include <string.h> 5362306a36Sopenharmony_ci#include <sysexits.h> 5462306a36Sopenharmony_ci#include "../queue.h" 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci#include "aicasm.h" 5762306a36Sopenharmony_ci#include "aicasm_symbol.h" 5862306a36Sopenharmony_ci#include "aicasm_gram.h" 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci/* This is used for macro body capture too, so err on the large size. */ 6162306a36Sopenharmony_ci#define MAX_STR_CONST 4096 6262306a36Sopenharmony_cistatic char string_buf[MAX_STR_CONST]; 6362306a36Sopenharmony_cistatic char *string_buf_ptr; 6462306a36Sopenharmony_cistatic int parren_count; 6562306a36Sopenharmony_cistatic int quote_count; 6662306a36Sopenharmony_cistatic char buf[255]; 6762306a36Sopenharmony_ci%} 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ciPATH ([/]*[-A-Za-z0-9_.])+ 7062306a36Sopenharmony_ciWORD [A-Za-z_][-A-Za-z_0-9]* 7162306a36Sopenharmony_ciSPACE [ \t]+ 7262306a36Sopenharmony_ciMCARG [^(), \t]+ 7362306a36Sopenharmony_ciMBODY ((\\[^\n])*[^\n\\]*)+ 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci%x COMMENT 7662306a36Sopenharmony_ci%x CEXPR 7762306a36Sopenharmony_ci%x INCLUDE 7862306a36Sopenharmony_ci%x STRING 7962306a36Sopenharmony_ci%x MACRODEF 8062306a36Sopenharmony_ci%x MACROARGLIST 8162306a36Sopenharmony_ci%x MACROCALLARGS 8262306a36Sopenharmony_ci%x MACROBODY 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci%% 8562306a36Sopenharmony_ci\n { ++yylineno; } 8662306a36Sopenharmony_ci\r ; 8762306a36Sopenharmony_ci"/*" { BEGIN COMMENT; /* Enter comment eating state */ } 8862306a36Sopenharmony_ci<COMMENT>"/*" { fprintf(stderr, "Warning! Comment within comment."); } 8962306a36Sopenharmony_ci<COMMENT>\n { ++yylineno; } 9062306a36Sopenharmony_ci<COMMENT>[^*/\n]* ; 9162306a36Sopenharmony_ci<COMMENT>"*"+[^*/\n]* ; 9262306a36Sopenharmony_ci<COMMENT>"/"+[^*/\n]* ; 9362306a36Sopenharmony_ci<COMMENT>"*"+"/" { BEGIN INITIAL; } 9462306a36Sopenharmony_ciif[ \t]*\( { 9562306a36Sopenharmony_ci string_buf_ptr = string_buf; 9662306a36Sopenharmony_ci parren_count = 1; 9762306a36Sopenharmony_ci BEGIN CEXPR; 9862306a36Sopenharmony_ci return T_IF; 9962306a36Sopenharmony_ci } 10062306a36Sopenharmony_ci<CEXPR>\( { *string_buf_ptr++ = '('; parren_count++; } 10162306a36Sopenharmony_ci<CEXPR>\) { 10262306a36Sopenharmony_ci parren_count--; 10362306a36Sopenharmony_ci if (parren_count == 0) { 10462306a36Sopenharmony_ci /* All done */ 10562306a36Sopenharmony_ci BEGIN INITIAL; 10662306a36Sopenharmony_ci *string_buf_ptr = '\0'; 10762306a36Sopenharmony_ci yylval.sym = symtable_get(string_buf); 10862306a36Sopenharmony_ci return T_CEXPR; 10962306a36Sopenharmony_ci } else { 11062306a36Sopenharmony_ci *string_buf_ptr++ = ')'; 11162306a36Sopenharmony_ci } 11262306a36Sopenharmony_ci } 11362306a36Sopenharmony_ci<CEXPR>\n { ++yylineno; } 11462306a36Sopenharmony_ci<CEXPR>\r ; 11562306a36Sopenharmony_ci<CEXPR>[^()\n]+ { 11662306a36Sopenharmony_ci char *yptr; 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci yptr = yytext; 11962306a36Sopenharmony_ci while (*yptr != '\0') { 12062306a36Sopenharmony_ci /* Remove duplicate spaces */ 12162306a36Sopenharmony_ci if (*yptr == '\t') 12262306a36Sopenharmony_ci *yptr = ' '; 12362306a36Sopenharmony_ci if (*yptr == ' ' 12462306a36Sopenharmony_ci && string_buf_ptr != string_buf 12562306a36Sopenharmony_ci && string_buf_ptr[-1] == ' ') 12662306a36Sopenharmony_ci yptr++; 12762306a36Sopenharmony_ci else 12862306a36Sopenharmony_ci *string_buf_ptr++ = *yptr++; 12962306a36Sopenharmony_ci } 13062306a36Sopenharmony_ci } 13162306a36Sopenharmony_cielse { return T_ELSE; } 13262306a36Sopenharmony_ciVERSION { return T_VERSION; } 13362306a36Sopenharmony_ciPREFIX { return T_PREFIX; } 13462306a36Sopenharmony_ciPATCH_ARG_LIST { return T_PATCH_ARG_LIST; } 13562306a36Sopenharmony_ci\" { 13662306a36Sopenharmony_ci string_buf_ptr = string_buf; 13762306a36Sopenharmony_ci BEGIN STRING; 13862306a36Sopenharmony_ci } 13962306a36Sopenharmony_ci<STRING>[^"]+ { 14062306a36Sopenharmony_ci char *yptr; 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci yptr = yytext; 14362306a36Sopenharmony_ci while (*yptr) 14462306a36Sopenharmony_ci *string_buf_ptr++ = *yptr++; 14562306a36Sopenharmony_ci } 14662306a36Sopenharmony_ci<STRING>\" { 14762306a36Sopenharmony_ci /* All done */ 14862306a36Sopenharmony_ci BEGIN INITIAL; 14962306a36Sopenharmony_ci *string_buf_ptr = '\0'; 15062306a36Sopenharmony_ci yylval.str = string_buf; 15162306a36Sopenharmony_ci return T_STRING; 15262306a36Sopenharmony_ci } 15362306a36Sopenharmony_ci{SPACE} ; 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci /* Register/SCB/SRAM definition keywords */ 15662306a36Sopenharmony_ciexport { return T_EXPORT; } 15762306a36Sopenharmony_ciregister { return T_REGISTER; } 15862306a36Sopenharmony_ciconst { yylval.value = FALSE; return T_CONST; } 15962306a36Sopenharmony_cidownload { return T_DOWNLOAD; } 16062306a36Sopenharmony_ciaddress { return T_ADDRESS; } 16162306a36Sopenharmony_cicount { return T_COUNT; } 16262306a36Sopenharmony_ciaccess_mode { return T_ACCESS_MODE; } 16362306a36Sopenharmony_cidont_generate_debug_code { return T_DONT_GENERATE_DEBUG_CODE; } 16462306a36Sopenharmony_cimodes { return T_MODES; } 16562306a36Sopenharmony_ciRW|RO|WO { 16662306a36Sopenharmony_ci if (strcmp(yytext, "RW") == 0) 16762306a36Sopenharmony_ci yylval.value = RW; 16862306a36Sopenharmony_ci else if (strcmp(yytext, "RO") == 0) 16962306a36Sopenharmony_ci yylval.value = RO; 17062306a36Sopenharmony_ci else 17162306a36Sopenharmony_ci yylval.value = WO; 17262306a36Sopenharmony_ci return T_MODE; 17362306a36Sopenharmony_ci } 17462306a36Sopenharmony_cifield { return T_FIELD; } 17562306a36Sopenharmony_cienum { return T_ENUM; } 17662306a36Sopenharmony_cimask { return T_MASK; } 17762306a36Sopenharmony_cialias { return T_ALIAS; } 17862306a36Sopenharmony_cisize { return T_SIZE; } 17962306a36Sopenharmony_ciscb { return T_SCB; } 18062306a36Sopenharmony_ciscratch_ram { return T_SRAM; } 18162306a36Sopenharmony_ciaccumulator { return T_ACCUM; } 18262306a36Sopenharmony_cimode_pointer { return T_MODE_PTR; } 18362306a36Sopenharmony_ciallones { return T_ALLONES; } 18462306a36Sopenharmony_ciallzeros { return T_ALLZEROS; } 18562306a36Sopenharmony_cinone { return T_NONE; } 18662306a36Sopenharmony_cisindex { return T_SINDEX; } 18762306a36Sopenharmony_ciA { return T_A; } 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci /* Instruction Formatting */ 19062306a36Sopenharmony_ciPAD_PAGE { return T_PAD_PAGE; } 19162306a36Sopenharmony_ciBEGIN_CRITICAL { return T_BEGIN_CS; } 19262306a36Sopenharmony_ciEND_CRITICAL { return T_END_CS; } 19362306a36Sopenharmony_ciSET_SRC_MODE { return T_SET_SRC_MODE; } 19462306a36Sopenharmony_ciSET_DST_MODE { return T_SET_DST_MODE; } 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci /* Opcodes */ 19762306a36Sopenharmony_cishl { return T_SHL; } 19862306a36Sopenharmony_cishr { return T_SHR; } 19962306a36Sopenharmony_ciror { return T_ROR; } 20062306a36Sopenharmony_cirol { return T_ROL; } 20162306a36Sopenharmony_cimvi { return T_MVI; } 20262306a36Sopenharmony_cimov { return T_MOV; } 20362306a36Sopenharmony_ciclr { return T_CLR; } 20462306a36Sopenharmony_cijmp { return T_JMP; } 20562306a36Sopenharmony_cijc { return T_JC; } 20662306a36Sopenharmony_cijnc { return T_JNC; } 20762306a36Sopenharmony_cije { return T_JE; } 20862306a36Sopenharmony_cijne { return T_JNE; } 20962306a36Sopenharmony_cijz { return T_JZ; } 21062306a36Sopenharmony_cijnz { return T_JNZ; } 21162306a36Sopenharmony_cicall { return T_CALL; } 21262306a36Sopenharmony_ciadd { return T_ADD; } 21362306a36Sopenharmony_ciadc { return T_ADC; } 21462306a36Sopenharmony_cibmov { return T_BMOV; } 21562306a36Sopenharmony_ciinc { return T_INC; } 21662306a36Sopenharmony_cidec { return T_DEC; } 21762306a36Sopenharmony_cistc { return T_STC; } 21862306a36Sopenharmony_ciclc { return T_CLC; } 21962306a36Sopenharmony_cicmp { return T_CMP; } 22062306a36Sopenharmony_cinot { return T_NOT; } 22162306a36Sopenharmony_cixor { return T_XOR; } 22262306a36Sopenharmony_citest { return T_TEST;} 22362306a36Sopenharmony_ciand { return T_AND; } 22462306a36Sopenharmony_cior { return T_OR; } 22562306a36Sopenharmony_ciret { return T_RET; } 22662306a36Sopenharmony_cinop { return T_NOP; } 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci /* ARP2 16bit extensions */ 22962306a36Sopenharmony_ci /* or16 { return T_OR16; } */ 23062306a36Sopenharmony_ci /* and16 { return T_AND16; }*/ 23162306a36Sopenharmony_ci /* xor16 { return T_XOR16; }*/ 23262306a36Sopenharmony_ci /* add16 { return T_ADD16; }*/ 23362306a36Sopenharmony_ci /* adc16 { return T_ADC16; }*/ 23462306a36Sopenharmony_ci /* mvi16 { return T_MVI16; }*/ 23562306a36Sopenharmony_ci /* test16 { return T_TEST16; }*/ 23662306a36Sopenharmony_ci /* cmp16 { return T_CMP16; }*/ 23762306a36Sopenharmony_ci /* cmpxchg { return T_CMPXCHG; }*/ 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci /* Allowed Symbols */ 24062306a36Sopenharmony_ci\<\< { return T_EXPR_LSHIFT; } 24162306a36Sopenharmony_ci\>\> { return T_EXPR_RSHIFT; } 24262306a36Sopenharmony_ci[-+,:()~|&."{};<>[\]/*!=] { return yytext[0]; } 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci /* Number processing */ 24562306a36Sopenharmony_ci0[0-7]* { 24662306a36Sopenharmony_ci yylval.value = strtol(yytext, NULL, 8); 24762306a36Sopenharmony_ci return T_NUMBER; 24862306a36Sopenharmony_ci } 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci0[xX][0-9a-fA-F]+ { 25162306a36Sopenharmony_ci yylval.value = strtoul(yytext + 2, NULL, 16); 25262306a36Sopenharmony_ci return T_NUMBER; 25362306a36Sopenharmony_ci } 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci[1-9][0-9]* { 25662306a36Sopenharmony_ci yylval.value = strtol(yytext, NULL, 10); 25762306a36Sopenharmony_ci return T_NUMBER; 25862306a36Sopenharmony_ci } 25962306a36Sopenharmony_ci /* Include Files */ 26062306a36Sopenharmony_ci#include{SPACE} { 26162306a36Sopenharmony_ci BEGIN INCLUDE; 26262306a36Sopenharmony_ci quote_count = 0; 26362306a36Sopenharmony_ci return T_INCLUDE; 26462306a36Sopenharmony_ci } 26562306a36Sopenharmony_ci<INCLUDE>[<] { return yytext[0]; } 26662306a36Sopenharmony_ci<INCLUDE>[>] { BEGIN INITIAL; return yytext[0]; } 26762306a36Sopenharmony_ci<INCLUDE>[\"] { 26862306a36Sopenharmony_ci if (quote_count != 0) 26962306a36Sopenharmony_ci BEGIN INITIAL; 27062306a36Sopenharmony_ci quote_count++; 27162306a36Sopenharmony_ci return yytext[0]; 27262306a36Sopenharmony_ci } 27362306a36Sopenharmony_ci<INCLUDE>{PATH} { 27462306a36Sopenharmony_ci char *yptr; 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci yptr = yytext; 27762306a36Sopenharmony_ci string_buf_ptr = string_buf; 27862306a36Sopenharmony_ci while (*yptr) 27962306a36Sopenharmony_ci *string_buf_ptr++ = *yptr++; 28062306a36Sopenharmony_ci yylval.str = string_buf; 28162306a36Sopenharmony_ci *string_buf_ptr = '\0'; 28262306a36Sopenharmony_ci return T_PATH; 28362306a36Sopenharmony_ci } 28462306a36Sopenharmony_ci<INCLUDE>. { stop("Invalid include line", EX_DATAERR); } 28562306a36Sopenharmony_ci#define{SPACE} { 28662306a36Sopenharmony_ci BEGIN MACRODEF; 28762306a36Sopenharmony_ci return T_DEFINE; 28862306a36Sopenharmony_ci } 28962306a36Sopenharmony_ci<MACRODEF>{WORD}{SPACE} { 29062306a36Sopenharmony_ci char *yptr; 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci /* Strip space and return as a normal symbol */ 29362306a36Sopenharmony_ci yptr = yytext; 29462306a36Sopenharmony_ci while (*yptr != ' ' && *yptr != '\t') 29562306a36Sopenharmony_ci yptr++; 29662306a36Sopenharmony_ci *yptr = '\0'; 29762306a36Sopenharmony_ci yylval.sym = symtable_get(yytext); 29862306a36Sopenharmony_ci string_buf_ptr = string_buf; 29962306a36Sopenharmony_ci BEGIN MACROBODY; 30062306a36Sopenharmony_ci return T_SYMBOL; 30162306a36Sopenharmony_ci } 30262306a36Sopenharmony_ci<MACRODEF>{WORD}\( { 30362306a36Sopenharmony_ci /* 30462306a36Sopenharmony_ci * We store the symbol with its opening 30562306a36Sopenharmony_ci * parren so we can differentiate macros 30662306a36Sopenharmony_ci * that take args from macros with the 30762306a36Sopenharmony_ci * same name that do not take args as 30862306a36Sopenharmony_ci * is allowed in C. 30962306a36Sopenharmony_ci */ 31062306a36Sopenharmony_ci BEGIN MACROARGLIST; 31162306a36Sopenharmony_ci yylval.sym = symtable_get(yytext); 31262306a36Sopenharmony_ci unput('('); 31362306a36Sopenharmony_ci return T_SYMBOL; 31462306a36Sopenharmony_ci } 31562306a36Sopenharmony_ci<MACROARGLIST>{WORD} { 31662306a36Sopenharmony_ci yylval.str = yytext; 31762306a36Sopenharmony_ci return T_ARG; 31862306a36Sopenharmony_ci } 31962306a36Sopenharmony_ci<MACROARGLIST>{SPACE} ; 32062306a36Sopenharmony_ci<MACROARGLIST>[(,] { 32162306a36Sopenharmony_ci return yytext[0]; 32262306a36Sopenharmony_ci } 32362306a36Sopenharmony_ci<MACROARGLIST>[)] { 32462306a36Sopenharmony_ci string_buf_ptr = string_buf; 32562306a36Sopenharmony_ci BEGIN MACROBODY; 32662306a36Sopenharmony_ci return ')'; 32762306a36Sopenharmony_ci } 32862306a36Sopenharmony_ci<MACROARGLIST>. { 32962306a36Sopenharmony_ci snprintf(buf, sizeof(buf), "Invalid character " 33062306a36Sopenharmony_ci "'%c' in macro argument list", 33162306a36Sopenharmony_ci yytext[0]); 33262306a36Sopenharmony_ci stop(buf, EX_DATAERR); 33362306a36Sopenharmony_ci } 33462306a36Sopenharmony_ci<MACROCALLARGS>{SPACE} ; 33562306a36Sopenharmony_ci<MACROCALLARGS>\( { 33662306a36Sopenharmony_ci parren_count++; 33762306a36Sopenharmony_ci if (parren_count == 1) 33862306a36Sopenharmony_ci return ('('); 33962306a36Sopenharmony_ci *string_buf_ptr++ = '('; 34062306a36Sopenharmony_ci } 34162306a36Sopenharmony_ci<MACROCALLARGS>\) { 34262306a36Sopenharmony_ci parren_count--; 34362306a36Sopenharmony_ci if (parren_count == 0) { 34462306a36Sopenharmony_ci BEGIN INITIAL; 34562306a36Sopenharmony_ci return (')'); 34662306a36Sopenharmony_ci } 34762306a36Sopenharmony_ci *string_buf_ptr++ = ')'; 34862306a36Sopenharmony_ci } 34962306a36Sopenharmony_ci<MACROCALLARGS>{MCARG} { 35062306a36Sopenharmony_ci char *yptr; 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci yptr = yytext; 35362306a36Sopenharmony_ci while (*yptr) 35462306a36Sopenharmony_ci *string_buf_ptr++ = *yptr++; 35562306a36Sopenharmony_ci } 35662306a36Sopenharmony_ci<MACROCALLARGS>\, { 35762306a36Sopenharmony_ci if (string_buf_ptr != string_buf) { 35862306a36Sopenharmony_ci /* 35962306a36Sopenharmony_ci * Return an argument and 36062306a36Sopenharmony_ci * rescan this comma so we 36162306a36Sopenharmony_ci * can return it as well. 36262306a36Sopenharmony_ci */ 36362306a36Sopenharmony_ci *string_buf_ptr = '\0'; 36462306a36Sopenharmony_ci yylval.str = string_buf; 36562306a36Sopenharmony_ci string_buf_ptr = string_buf; 36662306a36Sopenharmony_ci unput(','); 36762306a36Sopenharmony_ci return T_ARG; 36862306a36Sopenharmony_ci } 36962306a36Sopenharmony_ci return ','; 37062306a36Sopenharmony_ci } 37162306a36Sopenharmony_ci<MACROBODY>\\\n { 37262306a36Sopenharmony_ci /* Eat escaped newlines. */ 37362306a36Sopenharmony_ci ++yylineno; 37462306a36Sopenharmony_ci } 37562306a36Sopenharmony_ci<MACROBODY>\r ; 37662306a36Sopenharmony_ci<MACROBODY>\n { 37762306a36Sopenharmony_ci /* Macros end on the first unescaped newline. */ 37862306a36Sopenharmony_ci BEGIN INITIAL; 37962306a36Sopenharmony_ci *string_buf_ptr = '\0'; 38062306a36Sopenharmony_ci yylval.str = string_buf; 38162306a36Sopenharmony_ci ++yylineno; 38262306a36Sopenharmony_ci return T_MACROBODY; 38362306a36Sopenharmony_ci } 38462306a36Sopenharmony_ci<MACROBODY>{MBODY} { 38562306a36Sopenharmony_ci char *yptr; 38662306a36Sopenharmony_ci char c; 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci yptr = yytext; 38962306a36Sopenharmony_ci while (c = *yptr++) { 39062306a36Sopenharmony_ci /* 39162306a36Sopenharmony_ci * Strip carriage returns. 39262306a36Sopenharmony_ci */ 39362306a36Sopenharmony_ci if (c == '\r') 39462306a36Sopenharmony_ci continue; 39562306a36Sopenharmony_ci *string_buf_ptr++ = c; 39662306a36Sopenharmony_ci } 39762306a36Sopenharmony_ci } 39862306a36Sopenharmony_ci{WORD}\( { 39962306a36Sopenharmony_ci char *yptr; 40062306a36Sopenharmony_ci char *ycopy; 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_ci /* May be a symbol or a macro invocation. */ 40362306a36Sopenharmony_ci yylval.sym = symtable_get(yytext); 40462306a36Sopenharmony_ci if (yylval.sym->type == MACRO) { 40562306a36Sopenharmony_ci YY_BUFFER_STATE old_state; 40662306a36Sopenharmony_ci YY_BUFFER_STATE temp_state; 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci ycopy = strdup(yytext); 40962306a36Sopenharmony_ci yptr = ycopy + yyleng; 41062306a36Sopenharmony_ci while (yptr > ycopy) 41162306a36Sopenharmony_ci unput(*--yptr); 41262306a36Sopenharmony_ci old_state = YY_CURRENT_BUFFER; 41362306a36Sopenharmony_ci temp_state = 41462306a36Sopenharmony_ci yy_create_buffer(stdin, 41562306a36Sopenharmony_ci YY_BUF_SIZE); 41662306a36Sopenharmony_ci yy_switch_to_buffer(temp_state); 41762306a36Sopenharmony_ci mm_switch_to_buffer(old_state); 41862306a36Sopenharmony_ci mmparse(); 41962306a36Sopenharmony_ci mm_switch_to_buffer(temp_state); 42062306a36Sopenharmony_ci yy_switch_to_buffer(old_state); 42162306a36Sopenharmony_ci mm_delete_buffer(temp_state); 42262306a36Sopenharmony_ci expand_macro(yylval.sym); 42362306a36Sopenharmony_ci } else { 42462306a36Sopenharmony_ci if (yylval.sym->type == UNINITIALIZED) { 42562306a36Sopenharmony_ci /* Try without the '(' */ 42662306a36Sopenharmony_ci symbol_delete(yylval.sym); 42762306a36Sopenharmony_ci yytext[yyleng-1] = '\0'; 42862306a36Sopenharmony_ci yylval.sym = 42962306a36Sopenharmony_ci symtable_get(yytext); 43062306a36Sopenharmony_ci } 43162306a36Sopenharmony_ci unput('('); 43262306a36Sopenharmony_ci return T_SYMBOL; 43362306a36Sopenharmony_ci } 43462306a36Sopenharmony_ci } 43562306a36Sopenharmony_ci{WORD} { 43662306a36Sopenharmony_ci yylval.sym = symtable_get(yytext); 43762306a36Sopenharmony_ci if (yylval.sym->type == MACRO) { 43862306a36Sopenharmony_ci expand_macro(yylval.sym); 43962306a36Sopenharmony_ci } else { 44062306a36Sopenharmony_ci return T_SYMBOL; 44162306a36Sopenharmony_ci } 44262306a36Sopenharmony_ci } 44362306a36Sopenharmony_ci. { 44462306a36Sopenharmony_ci snprintf(buf, sizeof(buf), "Invalid character " 44562306a36Sopenharmony_ci "'%c'", yytext[0]); 44662306a36Sopenharmony_ci stop(buf, EX_DATAERR); 44762306a36Sopenharmony_ci } 44862306a36Sopenharmony_ci%% 44962306a36Sopenharmony_ci 45062306a36Sopenharmony_citypedef struct include { 45162306a36Sopenharmony_ci YY_BUFFER_STATE buffer; 45262306a36Sopenharmony_ci int lineno; 45362306a36Sopenharmony_ci char *filename; 45462306a36Sopenharmony_ci SLIST_ENTRY(include) links; 45562306a36Sopenharmony_ci}include_t; 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ciSLIST_HEAD(, include) include_stack; 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_civoid 46062306a36Sopenharmony_ciinclude_file(char *file_name, include_type type) 46162306a36Sopenharmony_ci{ 46262306a36Sopenharmony_ci FILE *newfile; 46362306a36Sopenharmony_ci include_t *include; 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_ci newfile = NULL; 46662306a36Sopenharmony_ci /* Try the current directory first */ 46762306a36Sopenharmony_ci if (includes_search_curdir != 0 || type == SOURCE_FILE) 46862306a36Sopenharmony_ci newfile = fopen(file_name, "r"); 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_ci if (newfile == NULL && type != SOURCE_FILE) { 47162306a36Sopenharmony_ci path_entry_t include_dir; 47262306a36Sopenharmony_ci for (include_dir = search_path.slh_first; 47362306a36Sopenharmony_ci include_dir != NULL; 47462306a36Sopenharmony_ci include_dir = include_dir->links.sle_next) { 47562306a36Sopenharmony_ci char fullname[PATH_MAX]; 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_ci if ((include_dir->quoted_includes_only == TRUE) 47862306a36Sopenharmony_ci && (type != QUOTED_INCLUDE)) 47962306a36Sopenharmony_ci continue; 48062306a36Sopenharmony_ci 48162306a36Sopenharmony_ci snprintf(fullname, sizeof(fullname), 48262306a36Sopenharmony_ci "%s/%s", include_dir->directory, file_name); 48362306a36Sopenharmony_ci 48462306a36Sopenharmony_ci if ((newfile = fopen(fullname, "r")) != NULL) 48562306a36Sopenharmony_ci break; 48662306a36Sopenharmony_ci } 48762306a36Sopenharmony_ci } 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_ci if (newfile == NULL) { 49062306a36Sopenharmony_ci perror(file_name); 49162306a36Sopenharmony_ci stop("Unable to open input file", EX_SOFTWARE); 49262306a36Sopenharmony_ci /* NOTREACHED */ 49362306a36Sopenharmony_ci } 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_ci if (type != SOURCE_FILE) { 49662306a36Sopenharmony_ci include = (include_t *)malloc(sizeof(include_t)); 49762306a36Sopenharmony_ci if (include == NULL) { 49862306a36Sopenharmony_ci stop("Unable to allocate include stack entry", 49962306a36Sopenharmony_ci EX_SOFTWARE); 50062306a36Sopenharmony_ci /* NOTREACHED */ 50162306a36Sopenharmony_ci } 50262306a36Sopenharmony_ci include->buffer = YY_CURRENT_BUFFER; 50362306a36Sopenharmony_ci include->lineno = yylineno; 50462306a36Sopenharmony_ci include->filename = yyfilename; 50562306a36Sopenharmony_ci SLIST_INSERT_HEAD(&include_stack, include, links); 50662306a36Sopenharmony_ci } 50762306a36Sopenharmony_ci yy_switch_to_buffer(yy_create_buffer(newfile, YY_BUF_SIZE)); 50862306a36Sopenharmony_ci yylineno = 1; 50962306a36Sopenharmony_ci yyfilename = strdup(file_name); 51062306a36Sopenharmony_ci} 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_cistatic void next_substitution(struct symbol *mac_symbol, const char *body_pos, 51362306a36Sopenharmony_ci const char **next_match, 51462306a36Sopenharmony_ci struct macro_arg **match_marg, regmatch_t *match); 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_civoid 51762306a36Sopenharmony_ciexpand_macro(struct symbol *macro_symbol) 51862306a36Sopenharmony_ci{ 51962306a36Sopenharmony_ci struct macro_arg *marg; 52062306a36Sopenharmony_ci struct macro_arg *match_marg; 52162306a36Sopenharmony_ci const char *body_head; 52262306a36Sopenharmony_ci const char *body_pos; 52362306a36Sopenharmony_ci const char *next_match; 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_ci /* 52662306a36Sopenharmony_ci * Due to the nature of unput, we must work 52762306a36Sopenharmony_ci * backwards through the macro body performing 52862306a36Sopenharmony_ci * any expansions. 52962306a36Sopenharmony_ci */ 53062306a36Sopenharmony_ci body_head = macro_symbol->info.macroinfo->body; 53162306a36Sopenharmony_ci body_pos = body_head + strlen(body_head); 53262306a36Sopenharmony_ci while (body_pos > body_head) { 53362306a36Sopenharmony_ci regmatch_t match; 53462306a36Sopenharmony_ci 53562306a36Sopenharmony_ci next_match = body_head; 53662306a36Sopenharmony_ci match_marg = NULL; 53762306a36Sopenharmony_ci next_substitution(macro_symbol, body_pos, &next_match, 53862306a36Sopenharmony_ci &match_marg, &match); 53962306a36Sopenharmony_ci 54062306a36Sopenharmony_ci /* Put back everything up until the replacement. */ 54162306a36Sopenharmony_ci while (body_pos > next_match) 54262306a36Sopenharmony_ci unput(*--body_pos); 54362306a36Sopenharmony_ci 54462306a36Sopenharmony_ci /* Perform the replacement. */ 54562306a36Sopenharmony_ci if (match_marg != NULL) { 54662306a36Sopenharmony_ci const char *strp; 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_ci next_match = match_marg->replacement_text; 54962306a36Sopenharmony_ci strp = next_match + strlen(next_match); 55062306a36Sopenharmony_ci while (strp > next_match) 55162306a36Sopenharmony_ci unput(*--strp); 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci /* Skip past the unexpanded macro arg. */ 55462306a36Sopenharmony_ci body_pos -= match.rm_eo - match.rm_so; 55562306a36Sopenharmony_ci } 55662306a36Sopenharmony_ci } 55762306a36Sopenharmony_ci 55862306a36Sopenharmony_ci /* Cleanup replacement text. */ 55962306a36Sopenharmony_ci STAILQ_FOREACH(marg, ¯o_symbol->info.macroinfo->args, links) { 56062306a36Sopenharmony_ci free(marg->replacement_text); 56162306a36Sopenharmony_ci } 56262306a36Sopenharmony_ci} 56362306a36Sopenharmony_ci 56462306a36Sopenharmony_ci/* 56562306a36Sopenharmony_ci * Find the next substitution in the macro working backwards from 56662306a36Sopenharmony_ci * body_pos until the beginning of the macro buffer. next_match 56762306a36Sopenharmony_ci * should be initialized to the beginning of the macro buffer prior 56862306a36Sopenharmony_ci * to calling this routine. 56962306a36Sopenharmony_ci */ 57062306a36Sopenharmony_cistatic void 57162306a36Sopenharmony_cinext_substitution(struct symbol *mac_symbol, const char *body_pos, 57262306a36Sopenharmony_ci const char **next_match, struct macro_arg **match_marg, 57362306a36Sopenharmony_ci regmatch_t *match) 57462306a36Sopenharmony_ci{ 57562306a36Sopenharmony_ci regmatch_t matches[2]; 57662306a36Sopenharmony_ci struct macro_arg *marg; 57762306a36Sopenharmony_ci const char *search_pos; 57862306a36Sopenharmony_ci int retval; 57962306a36Sopenharmony_ci 58062306a36Sopenharmony_ci do { 58162306a36Sopenharmony_ci search_pos = *next_match; 58262306a36Sopenharmony_ci 58362306a36Sopenharmony_ci STAILQ_FOREACH(marg, &mac_symbol->info.macroinfo->args, links) { 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_ci retval = regexec(&marg->arg_regex, search_pos, 2, 58662306a36Sopenharmony_ci matches, 0); 58762306a36Sopenharmony_ci if (retval == 0 58862306a36Sopenharmony_ci && (matches[1].rm_eo + search_pos) <= body_pos 58962306a36Sopenharmony_ci && (matches[1].rm_eo + search_pos) > *next_match) { 59062306a36Sopenharmony_ci *match = matches[1]; 59162306a36Sopenharmony_ci *next_match = match->rm_eo + search_pos; 59262306a36Sopenharmony_ci *match_marg = marg; 59362306a36Sopenharmony_ci } 59462306a36Sopenharmony_ci } 59562306a36Sopenharmony_ci } while (search_pos != *next_match); 59662306a36Sopenharmony_ci} 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_ciint 59962306a36Sopenharmony_ciyywrap() 60062306a36Sopenharmony_ci{ 60162306a36Sopenharmony_ci include_t *include; 60262306a36Sopenharmony_ci 60362306a36Sopenharmony_ci yy_delete_buffer(YY_CURRENT_BUFFER); 60462306a36Sopenharmony_ci (void)fclose(yyin); 60562306a36Sopenharmony_ci if (yyfilename != NULL) 60662306a36Sopenharmony_ci free(yyfilename); 60762306a36Sopenharmony_ci yyfilename = NULL; 60862306a36Sopenharmony_ci include = include_stack.slh_first; 60962306a36Sopenharmony_ci if (include != NULL) { 61062306a36Sopenharmony_ci yy_switch_to_buffer(include->buffer); 61162306a36Sopenharmony_ci yylineno = include->lineno; 61262306a36Sopenharmony_ci yyfilename = include->filename; 61362306a36Sopenharmony_ci SLIST_REMOVE_HEAD(&include_stack, links); 61462306a36Sopenharmony_ci free(include); 61562306a36Sopenharmony_ci return (0); 61662306a36Sopenharmony_ci } 61762306a36Sopenharmony_ci return (1); 61862306a36Sopenharmony_ci} 619