18c2ecf20Sopenharmony_ci%{ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Lexical Analyzer for the Aic7xxx SCSI Host adapter sequencer assembler. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (c) 1997, 1998, 2000 Justin T. Gibbs. 68c2ecf20Sopenharmony_ci * Copyright (c) 2001, 2002 Adaptec Inc. 78c2ecf20Sopenharmony_ci * All rights reserved. 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or without 108c2ecf20Sopenharmony_ci * modification, are permitted provided that the following conditions 118c2ecf20Sopenharmony_ci * are met: 128c2ecf20Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright 138c2ecf20Sopenharmony_ci * notice, this list of conditions, and the following disclaimer, 148c2ecf20Sopenharmony_ci * without modification. 158c2ecf20Sopenharmony_ci * 2. Redistributions in binary form must reproduce at minimum a disclaimer 168c2ecf20Sopenharmony_ci * substantially similar to the "NO WARRANTY" disclaimer below 178c2ecf20Sopenharmony_ci * ("Disclaimer") and any redistribution must be conditioned upon 188c2ecf20Sopenharmony_ci * including a substantially similar Disclaimer requirement for further 198c2ecf20Sopenharmony_ci * binary redistribution. 208c2ecf20Sopenharmony_ci * 3. Neither the names of the above-listed copyright holders nor the names 218c2ecf20Sopenharmony_ci * of any contributors may be used to endorse or promote products derived 228c2ecf20Sopenharmony_ci * from this software without specific prior written permission. 238c2ecf20Sopenharmony_ci * 248c2ecf20Sopenharmony_ci * Alternatively, this software may be distributed under the terms of the 258c2ecf20Sopenharmony_ci * GNU General Public License ("GPL") version 2 as published by the Free 268c2ecf20Sopenharmony_ci * Software Foundation. 278c2ecf20Sopenharmony_ci * 288c2ecf20Sopenharmony_ci * NO WARRANTY 298c2ecf20Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 308c2ecf20Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 318c2ecf20Sopenharmony_ci * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 328c2ecf20Sopenharmony_ci * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 338c2ecf20Sopenharmony_ci * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 348c2ecf20Sopenharmony_ci * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 358c2ecf20Sopenharmony_ci * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 368c2ecf20Sopenharmony_ci * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 378c2ecf20Sopenharmony_ci * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 388c2ecf20Sopenharmony_ci * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 398c2ecf20Sopenharmony_ci * POSSIBILITY OF SUCH DAMAGES. 408c2ecf20Sopenharmony_ci * 418c2ecf20Sopenharmony_ci * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_scan.l#20 $ 428c2ecf20Sopenharmony_ci * 438c2ecf20Sopenharmony_ci * $FreeBSD$ 448c2ecf20Sopenharmony_ci */ 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci#include <sys/types.h> 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci#include <inttypes.h> 498c2ecf20Sopenharmony_ci#include <limits.h> 508c2ecf20Sopenharmony_ci#include <regex.h> 518c2ecf20Sopenharmony_ci#include <stdio.h> 528c2ecf20Sopenharmony_ci#include <string.h> 538c2ecf20Sopenharmony_ci#include <sysexits.h> 548c2ecf20Sopenharmony_ci#include "../queue.h" 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci#include "aicasm.h" 578c2ecf20Sopenharmony_ci#include "aicasm_symbol.h" 588c2ecf20Sopenharmony_ci#include "aicasm_gram.h" 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci/* This is used for macro body capture too, so err on the large size. */ 618c2ecf20Sopenharmony_ci#define MAX_STR_CONST 4096 628c2ecf20Sopenharmony_cistatic char string_buf[MAX_STR_CONST]; 638c2ecf20Sopenharmony_cistatic char *string_buf_ptr; 648c2ecf20Sopenharmony_cistatic int parren_count; 658c2ecf20Sopenharmony_cistatic int quote_count; 668c2ecf20Sopenharmony_cistatic char buf[255]; 678c2ecf20Sopenharmony_ci%} 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ciPATH ([/]*[-A-Za-z0-9_.])+ 708c2ecf20Sopenharmony_ciWORD [A-Za-z_][-A-Za-z_0-9]* 718c2ecf20Sopenharmony_ciSPACE [ \t]+ 728c2ecf20Sopenharmony_ciMCARG [^(), \t]+ 738c2ecf20Sopenharmony_ciMBODY ((\\[^\n])*[^\n\\]*)+ 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci%x COMMENT 768c2ecf20Sopenharmony_ci%x CEXPR 778c2ecf20Sopenharmony_ci%x INCLUDE 788c2ecf20Sopenharmony_ci%x STRING 798c2ecf20Sopenharmony_ci%x MACRODEF 808c2ecf20Sopenharmony_ci%x MACROARGLIST 818c2ecf20Sopenharmony_ci%x MACROCALLARGS 828c2ecf20Sopenharmony_ci%x MACROBODY 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci%% 858c2ecf20Sopenharmony_ci\n { ++yylineno; } 868c2ecf20Sopenharmony_ci\r ; 878c2ecf20Sopenharmony_ci"/*" { BEGIN COMMENT; /* Enter comment eating state */ } 888c2ecf20Sopenharmony_ci<COMMENT>"/*" { fprintf(stderr, "Warning! Comment within comment."); } 898c2ecf20Sopenharmony_ci<COMMENT>\n { ++yylineno; } 908c2ecf20Sopenharmony_ci<COMMENT>[^*/\n]* ; 918c2ecf20Sopenharmony_ci<COMMENT>"*"+[^*/\n]* ; 928c2ecf20Sopenharmony_ci<COMMENT>"/"+[^*/\n]* ; 938c2ecf20Sopenharmony_ci<COMMENT>"*"+"/" { BEGIN INITIAL; } 948c2ecf20Sopenharmony_ciif[ \t]*\( { 958c2ecf20Sopenharmony_ci string_buf_ptr = string_buf; 968c2ecf20Sopenharmony_ci parren_count = 1; 978c2ecf20Sopenharmony_ci BEGIN CEXPR; 988c2ecf20Sopenharmony_ci return T_IF; 998c2ecf20Sopenharmony_ci } 1008c2ecf20Sopenharmony_ci<CEXPR>\( { *string_buf_ptr++ = '('; parren_count++; } 1018c2ecf20Sopenharmony_ci<CEXPR>\) { 1028c2ecf20Sopenharmony_ci parren_count--; 1038c2ecf20Sopenharmony_ci if (parren_count == 0) { 1048c2ecf20Sopenharmony_ci /* All done */ 1058c2ecf20Sopenharmony_ci BEGIN INITIAL; 1068c2ecf20Sopenharmony_ci *string_buf_ptr = '\0'; 1078c2ecf20Sopenharmony_ci yylval.sym = symtable_get(string_buf); 1088c2ecf20Sopenharmony_ci return T_CEXPR; 1098c2ecf20Sopenharmony_ci } else { 1108c2ecf20Sopenharmony_ci *string_buf_ptr++ = ')'; 1118c2ecf20Sopenharmony_ci } 1128c2ecf20Sopenharmony_ci } 1138c2ecf20Sopenharmony_ci<CEXPR>\n { ++yylineno; } 1148c2ecf20Sopenharmony_ci<CEXPR>\r ; 1158c2ecf20Sopenharmony_ci<CEXPR>[^()\n]+ { 1168c2ecf20Sopenharmony_ci char *yptr; 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci yptr = yytext; 1198c2ecf20Sopenharmony_ci while (*yptr != '\0') { 1208c2ecf20Sopenharmony_ci /* Remove duplicate spaces */ 1218c2ecf20Sopenharmony_ci if (*yptr == '\t') 1228c2ecf20Sopenharmony_ci *yptr = ' '; 1238c2ecf20Sopenharmony_ci if (*yptr == ' ' 1248c2ecf20Sopenharmony_ci && string_buf_ptr != string_buf 1258c2ecf20Sopenharmony_ci && string_buf_ptr[-1] == ' ') 1268c2ecf20Sopenharmony_ci yptr++; 1278c2ecf20Sopenharmony_ci else 1288c2ecf20Sopenharmony_ci *string_buf_ptr++ = *yptr++; 1298c2ecf20Sopenharmony_ci } 1308c2ecf20Sopenharmony_ci } 1318c2ecf20Sopenharmony_cielse { return T_ELSE; } 1328c2ecf20Sopenharmony_ciVERSION { return T_VERSION; } 1338c2ecf20Sopenharmony_ciPREFIX { return T_PREFIX; } 1348c2ecf20Sopenharmony_ciPATCH_ARG_LIST { return T_PATCH_ARG_LIST; } 1358c2ecf20Sopenharmony_ci\" { 1368c2ecf20Sopenharmony_ci string_buf_ptr = string_buf; 1378c2ecf20Sopenharmony_ci BEGIN STRING; 1388c2ecf20Sopenharmony_ci } 1398c2ecf20Sopenharmony_ci<STRING>[^"]+ { 1408c2ecf20Sopenharmony_ci char *yptr; 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci yptr = yytext; 1438c2ecf20Sopenharmony_ci while (*yptr) 1448c2ecf20Sopenharmony_ci *string_buf_ptr++ = *yptr++; 1458c2ecf20Sopenharmony_ci } 1468c2ecf20Sopenharmony_ci<STRING>\" { 1478c2ecf20Sopenharmony_ci /* All done */ 1488c2ecf20Sopenharmony_ci BEGIN INITIAL; 1498c2ecf20Sopenharmony_ci *string_buf_ptr = '\0'; 1508c2ecf20Sopenharmony_ci yylval.str = string_buf; 1518c2ecf20Sopenharmony_ci return T_STRING; 1528c2ecf20Sopenharmony_ci } 1538c2ecf20Sopenharmony_ci{SPACE} ; 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci /* Register/SCB/SRAM definition keywords */ 1568c2ecf20Sopenharmony_ciexport { return T_EXPORT; } 1578c2ecf20Sopenharmony_ciregister { return T_REGISTER; } 1588c2ecf20Sopenharmony_ciconst { yylval.value = FALSE; return T_CONST; } 1598c2ecf20Sopenharmony_cidownload { return T_DOWNLOAD; } 1608c2ecf20Sopenharmony_ciaddress { return T_ADDRESS; } 1618c2ecf20Sopenharmony_cicount { return T_COUNT; } 1628c2ecf20Sopenharmony_ciaccess_mode { return T_ACCESS_MODE; } 1638c2ecf20Sopenharmony_cidont_generate_debug_code { return T_DONT_GENERATE_DEBUG_CODE; } 1648c2ecf20Sopenharmony_cimodes { return T_MODES; } 1658c2ecf20Sopenharmony_ciRW|RO|WO { 1668c2ecf20Sopenharmony_ci if (strcmp(yytext, "RW") == 0) 1678c2ecf20Sopenharmony_ci yylval.value = RW; 1688c2ecf20Sopenharmony_ci else if (strcmp(yytext, "RO") == 0) 1698c2ecf20Sopenharmony_ci yylval.value = RO; 1708c2ecf20Sopenharmony_ci else 1718c2ecf20Sopenharmony_ci yylval.value = WO; 1728c2ecf20Sopenharmony_ci return T_MODE; 1738c2ecf20Sopenharmony_ci } 1748c2ecf20Sopenharmony_cifield { return T_FIELD; } 1758c2ecf20Sopenharmony_cienum { return T_ENUM; } 1768c2ecf20Sopenharmony_cimask { return T_MASK; } 1778c2ecf20Sopenharmony_cialias { return T_ALIAS; } 1788c2ecf20Sopenharmony_cisize { return T_SIZE; } 1798c2ecf20Sopenharmony_ciscb { return T_SCB; } 1808c2ecf20Sopenharmony_ciscratch_ram { return T_SRAM; } 1818c2ecf20Sopenharmony_ciaccumulator { return T_ACCUM; } 1828c2ecf20Sopenharmony_cimode_pointer { return T_MODE_PTR; } 1838c2ecf20Sopenharmony_ciallones { return T_ALLONES; } 1848c2ecf20Sopenharmony_ciallzeros { return T_ALLZEROS; } 1858c2ecf20Sopenharmony_cinone { return T_NONE; } 1868c2ecf20Sopenharmony_cisindex { return T_SINDEX; } 1878c2ecf20Sopenharmony_ciA { return T_A; } 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci /* Instruction Formatting */ 1908c2ecf20Sopenharmony_ciPAD_PAGE { return T_PAD_PAGE; } 1918c2ecf20Sopenharmony_ciBEGIN_CRITICAL { return T_BEGIN_CS; } 1928c2ecf20Sopenharmony_ciEND_CRITICAL { return T_END_CS; } 1938c2ecf20Sopenharmony_ciSET_SRC_MODE { return T_SET_SRC_MODE; } 1948c2ecf20Sopenharmony_ciSET_DST_MODE { return T_SET_DST_MODE; } 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci /* Opcodes */ 1978c2ecf20Sopenharmony_cishl { return T_SHL; } 1988c2ecf20Sopenharmony_cishr { return T_SHR; } 1998c2ecf20Sopenharmony_ciror { return T_ROR; } 2008c2ecf20Sopenharmony_cirol { return T_ROL; } 2018c2ecf20Sopenharmony_cimvi { return T_MVI; } 2028c2ecf20Sopenharmony_cimov { return T_MOV; } 2038c2ecf20Sopenharmony_ciclr { return T_CLR; } 2048c2ecf20Sopenharmony_cijmp { return T_JMP; } 2058c2ecf20Sopenharmony_cijc { return T_JC; } 2068c2ecf20Sopenharmony_cijnc { return T_JNC; } 2078c2ecf20Sopenharmony_cije { return T_JE; } 2088c2ecf20Sopenharmony_cijne { return T_JNE; } 2098c2ecf20Sopenharmony_cijz { return T_JZ; } 2108c2ecf20Sopenharmony_cijnz { return T_JNZ; } 2118c2ecf20Sopenharmony_cicall { return T_CALL; } 2128c2ecf20Sopenharmony_ciadd { return T_ADD; } 2138c2ecf20Sopenharmony_ciadc { return T_ADC; } 2148c2ecf20Sopenharmony_cibmov { return T_BMOV; } 2158c2ecf20Sopenharmony_ciinc { return T_INC; } 2168c2ecf20Sopenharmony_cidec { return T_DEC; } 2178c2ecf20Sopenharmony_cistc { return T_STC; } 2188c2ecf20Sopenharmony_ciclc { return T_CLC; } 2198c2ecf20Sopenharmony_cicmp { return T_CMP; } 2208c2ecf20Sopenharmony_cinot { return T_NOT; } 2218c2ecf20Sopenharmony_cixor { return T_XOR; } 2228c2ecf20Sopenharmony_citest { return T_TEST;} 2238c2ecf20Sopenharmony_ciand { return T_AND; } 2248c2ecf20Sopenharmony_cior { return T_OR; } 2258c2ecf20Sopenharmony_ciret { return T_RET; } 2268c2ecf20Sopenharmony_cinop { return T_NOP; } 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci /* ARP2 16bit extensions */ 2298c2ecf20Sopenharmony_ci /* or16 { return T_OR16; } */ 2308c2ecf20Sopenharmony_ci /* and16 { return T_AND16; }*/ 2318c2ecf20Sopenharmony_ci /* xor16 { return T_XOR16; }*/ 2328c2ecf20Sopenharmony_ci /* add16 { return T_ADD16; }*/ 2338c2ecf20Sopenharmony_ci /* adc16 { return T_ADC16; }*/ 2348c2ecf20Sopenharmony_ci /* mvi16 { return T_MVI16; }*/ 2358c2ecf20Sopenharmony_ci /* test16 { return T_TEST16; }*/ 2368c2ecf20Sopenharmony_ci /* cmp16 { return T_CMP16; }*/ 2378c2ecf20Sopenharmony_ci /* cmpxchg { return T_CMPXCHG; }*/ 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci /* Allowed Symbols */ 2408c2ecf20Sopenharmony_ci\<\< { return T_EXPR_LSHIFT; } 2418c2ecf20Sopenharmony_ci\>\> { return T_EXPR_RSHIFT; } 2428c2ecf20Sopenharmony_ci[-+,:()~|&."{};<>[\]/*!=] { return yytext[0]; } 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci /* Number processing */ 2458c2ecf20Sopenharmony_ci0[0-7]* { 2468c2ecf20Sopenharmony_ci yylval.value = strtol(yytext, NULL, 8); 2478c2ecf20Sopenharmony_ci return T_NUMBER; 2488c2ecf20Sopenharmony_ci } 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci0[xX][0-9a-fA-F]+ { 2518c2ecf20Sopenharmony_ci yylval.value = strtoul(yytext + 2, NULL, 16); 2528c2ecf20Sopenharmony_ci return T_NUMBER; 2538c2ecf20Sopenharmony_ci } 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci[1-9][0-9]* { 2568c2ecf20Sopenharmony_ci yylval.value = strtol(yytext, NULL, 10); 2578c2ecf20Sopenharmony_ci return T_NUMBER; 2588c2ecf20Sopenharmony_ci } 2598c2ecf20Sopenharmony_ci /* Include Files */ 2608c2ecf20Sopenharmony_ci#include{SPACE} { 2618c2ecf20Sopenharmony_ci BEGIN INCLUDE; 2628c2ecf20Sopenharmony_ci quote_count = 0; 2638c2ecf20Sopenharmony_ci return T_INCLUDE; 2648c2ecf20Sopenharmony_ci } 2658c2ecf20Sopenharmony_ci<INCLUDE>[<] { return yytext[0]; } 2668c2ecf20Sopenharmony_ci<INCLUDE>[>] { BEGIN INITIAL; return yytext[0]; } 2678c2ecf20Sopenharmony_ci<INCLUDE>[\"] { 2688c2ecf20Sopenharmony_ci if (quote_count != 0) 2698c2ecf20Sopenharmony_ci BEGIN INITIAL; 2708c2ecf20Sopenharmony_ci quote_count++; 2718c2ecf20Sopenharmony_ci return yytext[0]; 2728c2ecf20Sopenharmony_ci } 2738c2ecf20Sopenharmony_ci<INCLUDE>{PATH} { 2748c2ecf20Sopenharmony_ci char *yptr; 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci yptr = yytext; 2778c2ecf20Sopenharmony_ci string_buf_ptr = string_buf; 2788c2ecf20Sopenharmony_ci while (*yptr) 2798c2ecf20Sopenharmony_ci *string_buf_ptr++ = *yptr++; 2808c2ecf20Sopenharmony_ci yylval.str = string_buf; 2818c2ecf20Sopenharmony_ci *string_buf_ptr = '\0'; 2828c2ecf20Sopenharmony_ci return T_PATH; 2838c2ecf20Sopenharmony_ci } 2848c2ecf20Sopenharmony_ci<INCLUDE>. { stop("Invalid include line", EX_DATAERR); } 2858c2ecf20Sopenharmony_ci#define{SPACE} { 2868c2ecf20Sopenharmony_ci BEGIN MACRODEF; 2878c2ecf20Sopenharmony_ci return T_DEFINE; 2888c2ecf20Sopenharmony_ci } 2898c2ecf20Sopenharmony_ci<MACRODEF>{WORD}{SPACE} { 2908c2ecf20Sopenharmony_ci char *yptr; 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci /* Strip space and return as a normal symbol */ 2938c2ecf20Sopenharmony_ci yptr = yytext; 2948c2ecf20Sopenharmony_ci while (*yptr != ' ' && *yptr != '\t') 2958c2ecf20Sopenharmony_ci yptr++; 2968c2ecf20Sopenharmony_ci *yptr = '\0'; 2978c2ecf20Sopenharmony_ci yylval.sym = symtable_get(yytext); 2988c2ecf20Sopenharmony_ci string_buf_ptr = string_buf; 2998c2ecf20Sopenharmony_ci BEGIN MACROBODY; 3008c2ecf20Sopenharmony_ci return T_SYMBOL; 3018c2ecf20Sopenharmony_ci } 3028c2ecf20Sopenharmony_ci<MACRODEF>{WORD}\( { 3038c2ecf20Sopenharmony_ci /* 3048c2ecf20Sopenharmony_ci * We store the symbol with its opening 3058c2ecf20Sopenharmony_ci * parren so we can differentiate macros 3068c2ecf20Sopenharmony_ci * that take args from macros with the 3078c2ecf20Sopenharmony_ci * same name that do not take args as 3088c2ecf20Sopenharmony_ci * is allowed in C. 3098c2ecf20Sopenharmony_ci */ 3108c2ecf20Sopenharmony_ci BEGIN MACROARGLIST; 3118c2ecf20Sopenharmony_ci yylval.sym = symtable_get(yytext); 3128c2ecf20Sopenharmony_ci unput('('); 3138c2ecf20Sopenharmony_ci return T_SYMBOL; 3148c2ecf20Sopenharmony_ci } 3158c2ecf20Sopenharmony_ci<MACROARGLIST>{WORD} { 3168c2ecf20Sopenharmony_ci yylval.str = yytext; 3178c2ecf20Sopenharmony_ci return T_ARG; 3188c2ecf20Sopenharmony_ci } 3198c2ecf20Sopenharmony_ci<MACROARGLIST>{SPACE} ; 3208c2ecf20Sopenharmony_ci<MACROARGLIST>[(,] { 3218c2ecf20Sopenharmony_ci return yytext[0]; 3228c2ecf20Sopenharmony_ci } 3238c2ecf20Sopenharmony_ci<MACROARGLIST>[)] { 3248c2ecf20Sopenharmony_ci string_buf_ptr = string_buf; 3258c2ecf20Sopenharmony_ci BEGIN MACROBODY; 3268c2ecf20Sopenharmony_ci return ')'; 3278c2ecf20Sopenharmony_ci } 3288c2ecf20Sopenharmony_ci<MACROARGLIST>. { 3298c2ecf20Sopenharmony_ci snprintf(buf, sizeof(buf), "Invalid character " 3308c2ecf20Sopenharmony_ci "'%c' in macro argument list", 3318c2ecf20Sopenharmony_ci yytext[0]); 3328c2ecf20Sopenharmony_ci stop(buf, EX_DATAERR); 3338c2ecf20Sopenharmony_ci } 3348c2ecf20Sopenharmony_ci<MACROCALLARGS>{SPACE} ; 3358c2ecf20Sopenharmony_ci<MACROCALLARGS>\( { 3368c2ecf20Sopenharmony_ci parren_count++; 3378c2ecf20Sopenharmony_ci if (parren_count == 1) 3388c2ecf20Sopenharmony_ci return ('('); 3398c2ecf20Sopenharmony_ci *string_buf_ptr++ = '('; 3408c2ecf20Sopenharmony_ci } 3418c2ecf20Sopenharmony_ci<MACROCALLARGS>\) { 3428c2ecf20Sopenharmony_ci parren_count--; 3438c2ecf20Sopenharmony_ci if (parren_count == 0) { 3448c2ecf20Sopenharmony_ci BEGIN INITIAL; 3458c2ecf20Sopenharmony_ci return (')'); 3468c2ecf20Sopenharmony_ci } 3478c2ecf20Sopenharmony_ci *string_buf_ptr++ = ')'; 3488c2ecf20Sopenharmony_ci } 3498c2ecf20Sopenharmony_ci<MACROCALLARGS>{MCARG} { 3508c2ecf20Sopenharmony_ci char *yptr; 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci yptr = yytext; 3538c2ecf20Sopenharmony_ci while (*yptr) 3548c2ecf20Sopenharmony_ci *string_buf_ptr++ = *yptr++; 3558c2ecf20Sopenharmony_ci } 3568c2ecf20Sopenharmony_ci<MACROCALLARGS>\, { 3578c2ecf20Sopenharmony_ci if (string_buf_ptr != string_buf) { 3588c2ecf20Sopenharmony_ci /* 3598c2ecf20Sopenharmony_ci * Return an argument and 3608c2ecf20Sopenharmony_ci * rescan this comma so we 3618c2ecf20Sopenharmony_ci * can return it as well. 3628c2ecf20Sopenharmony_ci */ 3638c2ecf20Sopenharmony_ci *string_buf_ptr = '\0'; 3648c2ecf20Sopenharmony_ci yylval.str = string_buf; 3658c2ecf20Sopenharmony_ci string_buf_ptr = string_buf; 3668c2ecf20Sopenharmony_ci unput(','); 3678c2ecf20Sopenharmony_ci return T_ARG; 3688c2ecf20Sopenharmony_ci } 3698c2ecf20Sopenharmony_ci return ','; 3708c2ecf20Sopenharmony_ci } 3718c2ecf20Sopenharmony_ci<MACROBODY>\\\n { 3728c2ecf20Sopenharmony_ci /* Eat escaped newlines. */ 3738c2ecf20Sopenharmony_ci ++yylineno; 3748c2ecf20Sopenharmony_ci } 3758c2ecf20Sopenharmony_ci<MACROBODY>\r ; 3768c2ecf20Sopenharmony_ci<MACROBODY>\n { 3778c2ecf20Sopenharmony_ci /* Macros end on the first unescaped newline. */ 3788c2ecf20Sopenharmony_ci BEGIN INITIAL; 3798c2ecf20Sopenharmony_ci *string_buf_ptr = '\0'; 3808c2ecf20Sopenharmony_ci yylval.str = string_buf; 3818c2ecf20Sopenharmony_ci ++yylineno; 3828c2ecf20Sopenharmony_ci return T_MACROBODY; 3838c2ecf20Sopenharmony_ci } 3848c2ecf20Sopenharmony_ci<MACROBODY>{MBODY} { 3858c2ecf20Sopenharmony_ci char *yptr; 3868c2ecf20Sopenharmony_ci char c; 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_ci yptr = yytext; 3898c2ecf20Sopenharmony_ci while (c = *yptr++) { 3908c2ecf20Sopenharmony_ci /* 3918c2ecf20Sopenharmony_ci * Strip carriage returns. 3928c2ecf20Sopenharmony_ci */ 3938c2ecf20Sopenharmony_ci if (c == '\r') 3948c2ecf20Sopenharmony_ci continue; 3958c2ecf20Sopenharmony_ci *string_buf_ptr++ = c; 3968c2ecf20Sopenharmony_ci } 3978c2ecf20Sopenharmony_ci } 3988c2ecf20Sopenharmony_ci{WORD}\( { 3998c2ecf20Sopenharmony_ci char *yptr; 4008c2ecf20Sopenharmony_ci char *ycopy; 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_ci /* May be a symbol or a macro invocation. */ 4038c2ecf20Sopenharmony_ci yylval.sym = symtable_get(yytext); 4048c2ecf20Sopenharmony_ci if (yylval.sym->type == MACRO) { 4058c2ecf20Sopenharmony_ci YY_BUFFER_STATE old_state; 4068c2ecf20Sopenharmony_ci YY_BUFFER_STATE temp_state; 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ci ycopy = strdup(yytext); 4098c2ecf20Sopenharmony_ci yptr = ycopy + yyleng; 4108c2ecf20Sopenharmony_ci while (yptr > ycopy) 4118c2ecf20Sopenharmony_ci unput(*--yptr); 4128c2ecf20Sopenharmony_ci old_state = YY_CURRENT_BUFFER; 4138c2ecf20Sopenharmony_ci temp_state = 4148c2ecf20Sopenharmony_ci yy_create_buffer(stdin, 4158c2ecf20Sopenharmony_ci YY_BUF_SIZE); 4168c2ecf20Sopenharmony_ci yy_switch_to_buffer(temp_state); 4178c2ecf20Sopenharmony_ci mm_switch_to_buffer(old_state); 4188c2ecf20Sopenharmony_ci mmparse(); 4198c2ecf20Sopenharmony_ci mm_switch_to_buffer(temp_state); 4208c2ecf20Sopenharmony_ci yy_switch_to_buffer(old_state); 4218c2ecf20Sopenharmony_ci mm_delete_buffer(temp_state); 4228c2ecf20Sopenharmony_ci expand_macro(yylval.sym); 4238c2ecf20Sopenharmony_ci } else { 4248c2ecf20Sopenharmony_ci if (yylval.sym->type == UNINITIALIZED) { 4258c2ecf20Sopenharmony_ci /* Try without the '(' */ 4268c2ecf20Sopenharmony_ci symbol_delete(yylval.sym); 4278c2ecf20Sopenharmony_ci yytext[yyleng-1] = '\0'; 4288c2ecf20Sopenharmony_ci yylval.sym = 4298c2ecf20Sopenharmony_ci symtable_get(yytext); 4308c2ecf20Sopenharmony_ci } 4318c2ecf20Sopenharmony_ci unput('('); 4328c2ecf20Sopenharmony_ci return T_SYMBOL; 4338c2ecf20Sopenharmony_ci } 4348c2ecf20Sopenharmony_ci } 4358c2ecf20Sopenharmony_ci{WORD} { 4368c2ecf20Sopenharmony_ci yylval.sym = symtable_get(yytext); 4378c2ecf20Sopenharmony_ci if (yylval.sym->type == MACRO) { 4388c2ecf20Sopenharmony_ci expand_macro(yylval.sym); 4398c2ecf20Sopenharmony_ci } else { 4408c2ecf20Sopenharmony_ci return T_SYMBOL; 4418c2ecf20Sopenharmony_ci } 4428c2ecf20Sopenharmony_ci } 4438c2ecf20Sopenharmony_ci. { 4448c2ecf20Sopenharmony_ci snprintf(buf, sizeof(buf), "Invalid character " 4458c2ecf20Sopenharmony_ci "'%c'", yytext[0]); 4468c2ecf20Sopenharmony_ci stop(buf, EX_DATAERR); 4478c2ecf20Sopenharmony_ci } 4488c2ecf20Sopenharmony_ci%% 4498c2ecf20Sopenharmony_ci 4508c2ecf20Sopenharmony_citypedef struct include { 4518c2ecf20Sopenharmony_ci YY_BUFFER_STATE buffer; 4528c2ecf20Sopenharmony_ci int lineno; 4538c2ecf20Sopenharmony_ci char *filename; 4548c2ecf20Sopenharmony_ci SLIST_ENTRY(include) links; 4558c2ecf20Sopenharmony_ci}include_t; 4568c2ecf20Sopenharmony_ci 4578c2ecf20Sopenharmony_ciSLIST_HEAD(, include) include_stack; 4588c2ecf20Sopenharmony_ci 4598c2ecf20Sopenharmony_civoid 4608c2ecf20Sopenharmony_ciinclude_file(char *file_name, include_type type) 4618c2ecf20Sopenharmony_ci{ 4628c2ecf20Sopenharmony_ci FILE *newfile; 4638c2ecf20Sopenharmony_ci include_t *include; 4648c2ecf20Sopenharmony_ci 4658c2ecf20Sopenharmony_ci newfile = NULL; 4668c2ecf20Sopenharmony_ci /* Try the current directory first */ 4678c2ecf20Sopenharmony_ci if (includes_search_curdir != 0 || type == SOURCE_FILE) 4688c2ecf20Sopenharmony_ci newfile = fopen(file_name, "r"); 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_ci if (newfile == NULL && type != SOURCE_FILE) { 4718c2ecf20Sopenharmony_ci path_entry_t include_dir; 4728c2ecf20Sopenharmony_ci for (include_dir = search_path.slh_first; 4738c2ecf20Sopenharmony_ci include_dir != NULL; 4748c2ecf20Sopenharmony_ci include_dir = include_dir->links.sle_next) { 4758c2ecf20Sopenharmony_ci char fullname[PATH_MAX]; 4768c2ecf20Sopenharmony_ci 4778c2ecf20Sopenharmony_ci if ((include_dir->quoted_includes_only == TRUE) 4788c2ecf20Sopenharmony_ci && (type != QUOTED_INCLUDE)) 4798c2ecf20Sopenharmony_ci continue; 4808c2ecf20Sopenharmony_ci 4818c2ecf20Sopenharmony_ci snprintf(fullname, sizeof(fullname), 4828c2ecf20Sopenharmony_ci "%s/%s", include_dir->directory, file_name); 4838c2ecf20Sopenharmony_ci 4848c2ecf20Sopenharmony_ci if ((newfile = fopen(fullname, "r")) != NULL) 4858c2ecf20Sopenharmony_ci break; 4868c2ecf20Sopenharmony_ci } 4878c2ecf20Sopenharmony_ci } 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_ci if (newfile == NULL) { 4908c2ecf20Sopenharmony_ci perror(file_name); 4918c2ecf20Sopenharmony_ci stop("Unable to open input file", EX_SOFTWARE); 4928c2ecf20Sopenharmony_ci /* NOTREACHED */ 4938c2ecf20Sopenharmony_ci } 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_ci if (type != SOURCE_FILE) { 4968c2ecf20Sopenharmony_ci include = (include_t *)malloc(sizeof(include_t)); 4978c2ecf20Sopenharmony_ci if (include == NULL) { 4988c2ecf20Sopenharmony_ci stop("Unable to allocate include stack entry", 4998c2ecf20Sopenharmony_ci EX_SOFTWARE); 5008c2ecf20Sopenharmony_ci /* NOTREACHED */ 5018c2ecf20Sopenharmony_ci } 5028c2ecf20Sopenharmony_ci include->buffer = YY_CURRENT_BUFFER; 5038c2ecf20Sopenharmony_ci include->lineno = yylineno; 5048c2ecf20Sopenharmony_ci include->filename = yyfilename; 5058c2ecf20Sopenharmony_ci SLIST_INSERT_HEAD(&include_stack, include, links); 5068c2ecf20Sopenharmony_ci } 5078c2ecf20Sopenharmony_ci yy_switch_to_buffer(yy_create_buffer(newfile, YY_BUF_SIZE)); 5088c2ecf20Sopenharmony_ci yylineno = 1; 5098c2ecf20Sopenharmony_ci yyfilename = strdup(file_name); 5108c2ecf20Sopenharmony_ci} 5118c2ecf20Sopenharmony_ci 5128c2ecf20Sopenharmony_cistatic void next_substitution(struct symbol *mac_symbol, const char *body_pos, 5138c2ecf20Sopenharmony_ci const char **next_match, 5148c2ecf20Sopenharmony_ci struct macro_arg **match_marg, regmatch_t *match); 5158c2ecf20Sopenharmony_ci 5168c2ecf20Sopenharmony_civoid 5178c2ecf20Sopenharmony_ciexpand_macro(struct symbol *macro_symbol) 5188c2ecf20Sopenharmony_ci{ 5198c2ecf20Sopenharmony_ci struct macro_arg *marg; 5208c2ecf20Sopenharmony_ci struct macro_arg *match_marg; 5218c2ecf20Sopenharmony_ci const char *body_head; 5228c2ecf20Sopenharmony_ci const char *body_pos; 5238c2ecf20Sopenharmony_ci const char *next_match; 5248c2ecf20Sopenharmony_ci 5258c2ecf20Sopenharmony_ci /* 5268c2ecf20Sopenharmony_ci * Due to the nature of unput, we must work 5278c2ecf20Sopenharmony_ci * backwards through the macro body performing 5288c2ecf20Sopenharmony_ci * any expansions. 5298c2ecf20Sopenharmony_ci */ 5308c2ecf20Sopenharmony_ci body_head = macro_symbol->info.macroinfo->body; 5318c2ecf20Sopenharmony_ci body_pos = body_head + strlen(body_head); 5328c2ecf20Sopenharmony_ci while (body_pos > body_head) { 5338c2ecf20Sopenharmony_ci regmatch_t match; 5348c2ecf20Sopenharmony_ci 5358c2ecf20Sopenharmony_ci next_match = body_head; 5368c2ecf20Sopenharmony_ci match_marg = NULL; 5378c2ecf20Sopenharmony_ci next_substitution(macro_symbol, body_pos, &next_match, 5388c2ecf20Sopenharmony_ci &match_marg, &match); 5398c2ecf20Sopenharmony_ci 5408c2ecf20Sopenharmony_ci /* Put back everything up until the replacement. */ 5418c2ecf20Sopenharmony_ci while (body_pos > next_match) 5428c2ecf20Sopenharmony_ci unput(*--body_pos); 5438c2ecf20Sopenharmony_ci 5448c2ecf20Sopenharmony_ci /* Perform the replacement. */ 5458c2ecf20Sopenharmony_ci if (match_marg != NULL) { 5468c2ecf20Sopenharmony_ci const char *strp; 5478c2ecf20Sopenharmony_ci 5488c2ecf20Sopenharmony_ci next_match = match_marg->replacement_text; 5498c2ecf20Sopenharmony_ci strp = next_match + strlen(next_match); 5508c2ecf20Sopenharmony_ci while (strp > next_match) 5518c2ecf20Sopenharmony_ci unput(*--strp); 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_ci /* Skip past the unexpanded macro arg. */ 5548c2ecf20Sopenharmony_ci body_pos -= match.rm_eo - match.rm_so; 5558c2ecf20Sopenharmony_ci } 5568c2ecf20Sopenharmony_ci } 5578c2ecf20Sopenharmony_ci 5588c2ecf20Sopenharmony_ci /* Cleanup replacement text. */ 5598c2ecf20Sopenharmony_ci STAILQ_FOREACH(marg, ¯o_symbol->info.macroinfo->args, links) { 5608c2ecf20Sopenharmony_ci free(marg->replacement_text); 5618c2ecf20Sopenharmony_ci } 5628c2ecf20Sopenharmony_ci} 5638c2ecf20Sopenharmony_ci 5648c2ecf20Sopenharmony_ci/* 5658c2ecf20Sopenharmony_ci * Find the next substitution in the macro working backwards from 5668c2ecf20Sopenharmony_ci * body_pos until the beginning of the macro buffer. next_match 5678c2ecf20Sopenharmony_ci * should be initialized to the beginning of the macro buffer prior 5688c2ecf20Sopenharmony_ci * to calling this routine. 5698c2ecf20Sopenharmony_ci */ 5708c2ecf20Sopenharmony_cistatic void 5718c2ecf20Sopenharmony_cinext_substitution(struct symbol *mac_symbol, const char *body_pos, 5728c2ecf20Sopenharmony_ci const char **next_match, struct macro_arg **match_marg, 5738c2ecf20Sopenharmony_ci regmatch_t *match) 5748c2ecf20Sopenharmony_ci{ 5758c2ecf20Sopenharmony_ci regmatch_t matches[2]; 5768c2ecf20Sopenharmony_ci struct macro_arg *marg; 5778c2ecf20Sopenharmony_ci const char *search_pos; 5788c2ecf20Sopenharmony_ci int retval; 5798c2ecf20Sopenharmony_ci 5808c2ecf20Sopenharmony_ci do { 5818c2ecf20Sopenharmony_ci search_pos = *next_match; 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_ci STAILQ_FOREACH(marg, &mac_symbol->info.macroinfo->args, links) { 5848c2ecf20Sopenharmony_ci 5858c2ecf20Sopenharmony_ci retval = regexec(&marg->arg_regex, search_pos, 2, 5868c2ecf20Sopenharmony_ci matches, 0); 5878c2ecf20Sopenharmony_ci if (retval == 0 5888c2ecf20Sopenharmony_ci && (matches[1].rm_eo + search_pos) <= body_pos 5898c2ecf20Sopenharmony_ci && (matches[1].rm_eo + search_pos) > *next_match) { 5908c2ecf20Sopenharmony_ci *match = matches[1]; 5918c2ecf20Sopenharmony_ci *next_match = match->rm_eo + search_pos; 5928c2ecf20Sopenharmony_ci *match_marg = marg; 5938c2ecf20Sopenharmony_ci } 5948c2ecf20Sopenharmony_ci } 5958c2ecf20Sopenharmony_ci } while (search_pos != *next_match); 5968c2ecf20Sopenharmony_ci} 5978c2ecf20Sopenharmony_ci 5988c2ecf20Sopenharmony_ciint 5998c2ecf20Sopenharmony_ciyywrap() 6008c2ecf20Sopenharmony_ci{ 6018c2ecf20Sopenharmony_ci include_t *include; 6028c2ecf20Sopenharmony_ci 6038c2ecf20Sopenharmony_ci yy_delete_buffer(YY_CURRENT_BUFFER); 6048c2ecf20Sopenharmony_ci (void)fclose(yyin); 6058c2ecf20Sopenharmony_ci if (yyfilename != NULL) 6068c2ecf20Sopenharmony_ci free(yyfilename); 6078c2ecf20Sopenharmony_ci yyfilename = NULL; 6088c2ecf20Sopenharmony_ci include = include_stack.slh_first; 6098c2ecf20Sopenharmony_ci if (include != NULL) { 6108c2ecf20Sopenharmony_ci yy_switch_to_buffer(include->buffer); 6118c2ecf20Sopenharmony_ci yylineno = include->lineno; 6128c2ecf20Sopenharmony_ci yyfilename = include->filename; 6138c2ecf20Sopenharmony_ci SLIST_REMOVE_HEAD(&include_stack, links); 6148c2ecf20Sopenharmony_ci free(include); 6158c2ecf20Sopenharmony_ci return (0); 6168c2ecf20Sopenharmony_ci } 6178c2ecf20Sopenharmony_ci return (1); 6188c2ecf20Sopenharmony_ci} 619