11da177e4SLinus Torvalds %{ 21da177e4SLinus Torvalds /* 31da177e4SLinus Torvalds * Lexical Analyzer for the Aic7xxx SCSI Host adapter sequencer assembler. 41da177e4SLinus Torvalds * 51da177e4SLinus Torvalds * Copyright (c) 1997, 1998, 2000 Justin T. Gibbs. 61da177e4SLinus Torvalds * Copyright (c) 2001, 2002 Adaptec Inc. 71da177e4SLinus Torvalds * All rights reserved. 81da177e4SLinus Torvalds * 91da177e4SLinus Torvalds * Redistribution and use in source and binary forms, with or without 101da177e4SLinus Torvalds * modification, are permitted provided that the following conditions 111da177e4SLinus Torvalds * are met: 121da177e4SLinus Torvalds * 1. Redistributions of source code must retain the above copyright 131da177e4SLinus Torvalds * notice, this list of conditions, and the following disclaimer, 141da177e4SLinus Torvalds * without modification. 151da177e4SLinus Torvalds * 2. Redistributions in binary form must reproduce at minimum a disclaimer 161da177e4SLinus Torvalds * substantially similar to the "NO WARRANTY" disclaimer below 171da177e4SLinus Torvalds * ("Disclaimer") and any redistribution must be conditioned upon 181da177e4SLinus Torvalds * including a substantially similar Disclaimer requirement for further 191da177e4SLinus Torvalds * binary redistribution. 201da177e4SLinus Torvalds * 3. Neither the names of the above-listed copyright holders nor the names 211da177e4SLinus Torvalds * of any contributors may be used to endorse or promote products derived 221da177e4SLinus Torvalds * from this software without specific prior written permission. 231da177e4SLinus Torvalds * 241da177e4SLinus Torvalds * Alternatively, this software may be distributed under the terms of the 251da177e4SLinus Torvalds * GNU General Public License ("GPL") version 2 as published by the Free 261da177e4SLinus Torvalds * Software Foundation. 271da177e4SLinus Torvalds * 281da177e4SLinus Torvalds * NO WARRANTY 291da177e4SLinus Torvalds * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 301da177e4SLinus Torvalds * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 311da177e4SLinus Torvalds * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 321da177e4SLinus Torvalds * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 331da177e4SLinus Torvalds * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 341da177e4SLinus Torvalds * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 351da177e4SLinus Torvalds * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 361da177e4SLinus Torvalds * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 371da177e4SLinus Torvalds * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 381da177e4SLinus Torvalds * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 391da177e4SLinus Torvalds * POSSIBILITY OF SUCH DAMAGES. 401da177e4SLinus Torvalds * 412628ed2bSHannes Reinecke * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_scan.l#20 $ 421da177e4SLinus Torvalds * 431da177e4SLinus Torvalds * $FreeBSD$ 441da177e4SLinus Torvalds */ 451da177e4SLinus Torvalds 461da177e4SLinus Torvalds #include <sys/types.h> 471da177e4SLinus Torvalds 481da177e4SLinus Torvalds #include <inttypes.h> 491da177e4SLinus Torvalds #include <limits.h> 501da177e4SLinus Torvalds #include <regex.h> 511da177e4SLinus Torvalds #include <stdio.h> 521da177e4SLinus Torvalds #include <string.h> 531da177e4SLinus Torvalds #include <sysexits.h> 541da177e4SLinus Torvalds #include "../queue.h" 551da177e4SLinus Torvalds 561da177e4SLinus Torvalds #include "aicasm.h" 571da177e4SLinus Torvalds #include "aicasm_symbol.h" 581da177e4SLinus Torvalds #include "aicasm_gram.h" 591da177e4SLinus Torvalds 601da177e4SLinus Torvalds /* This is used for macro body capture too, so err on the large size. */ 611da177e4SLinus Torvalds #define MAX_STR_CONST 4096 621da177e4SLinus Torvalds static char string_buf[MAX_STR_CONST]; 631da177e4SLinus Torvalds static char *string_buf_ptr; 641da177e4SLinus Torvalds static int parren_count; 651da177e4SLinus Torvalds static int quote_count; 661da177e4SLinus Torvalds static char buf[255]; 671da177e4SLinus Torvalds %} 681da177e4SLinus Torvalds 691da177e4SLinus Torvalds PATH ([/]*[-A-Za-z0-9_.])+ 701da177e4SLinus Torvalds WORD [A-Za-z_][-A-Za-z_0-9]* 711da177e4SLinus Torvalds SPACE [ \t]+ 721da177e4SLinus Torvalds MCARG [^(), \t]+ 731da177e4SLinus Torvalds MBODY ((\\[^\n])*[^\n\\]*)+ 741da177e4SLinus Torvalds 751da177e4SLinus Torvalds %x COMMENT 761da177e4SLinus Torvalds %x CEXPR 771da177e4SLinus Torvalds %x INCLUDE 781da177e4SLinus Torvalds %x STRING 791da177e4SLinus Torvalds %x MACRODEF 801da177e4SLinus Torvalds %x MACROARGLIST 811da177e4SLinus Torvalds %x MACROCALLARGS 821da177e4SLinus Torvalds %x MACROBODY 831da177e4SLinus Torvalds 841da177e4SLinus Torvalds %% 851da177e4SLinus Torvalds \n { ++yylineno; } 861da177e4SLinus Torvalds \r ; 871da177e4SLinus Torvalds "/*" { BEGIN COMMENT; /* Enter comment eating state */ } 881da177e4SLinus Torvalds <COMMENT>"/*" { fprintf(stderr, "Warning! Comment within comment."); } 891da177e4SLinus Torvalds <COMMENT>\n { ++yylineno; } 901da177e4SLinus Torvalds <COMMENT>[^*/\n]* ; 911da177e4SLinus Torvalds <COMMENT>"*"+[^*/\n]* ; 921da177e4SLinus Torvalds <COMMENT>"/"+[^*/\n]* ; 931da177e4SLinus Torvalds <COMMENT>"*"+"/" { BEGIN INITIAL; } 941da177e4SLinus Torvalds if[ \t]*\( { 951da177e4SLinus Torvalds string_buf_ptr = string_buf; 961da177e4SLinus Torvalds parren_count = 1; 971da177e4SLinus Torvalds BEGIN CEXPR; 981da177e4SLinus Torvalds return T_IF; 991da177e4SLinus Torvalds } 1001da177e4SLinus Torvalds <CEXPR>\( { *string_buf_ptr++ = '('; parren_count++; } 1011da177e4SLinus Torvalds <CEXPR>\) { 1021da177e4SLinus Torvalds parren_count--; 1031da177e4SLinus Torvalds if (parren_count == 0) { 1041da177e4SLinus Torvalds /* All done */ 1051da177e4SLinus Torvalds BEGIN INITIAL; 1061da177e4SLinus Torvalds *string_buf_ptr = '\0'; 1071da177e4SLinus Torvalds yylval.sym = symtable_get(string_buf); 1081da177e4SLinus Torvalds return T_CEXPR; 1091da177e4SLinus Torvalds } else { 1101da177e4SLinus Torvalds *string_buf_ptr++ = ')'; 1111da177e4SLinus Torvalds } 1121da177e4SLinus Torvalds } 1131da177e4SLinus Torvalds <CEXPR>\n { ++yylineno; } 1141da177e4SLinus Torvalds <CEXPR>\r ; 1151da177e4SLinus Torvalds <CEXPR>[^()\n]+ { 1161da177e4SLinus Torvalds char *yptr; 1171da177e4SLinus Torvalds 1181da177e4SLinus Torvalds yptr = yytext; 1191da177e4SLinus Torvalds while (*yptr != '\0') { 1201da177e4SLinus Torvalds /* Remove duplicate spaces */ 1211da177e4SLinus Torvalds if (*yptr == '\t') 1221da177e4SLinus Torvalds *yptr = ' '; 1231da177e4SLinus Torvalds if (*yptr == ' ' 1241da177e4SLinus Torvalds && string_buf_ptr != string_buf 1251da177e4SLinus Torvalds && string_buf_ptr[-1] == ' ') 1261da177e4SLinus Torvalds yptr++; 1271da177e4SLinus Torvalds else 1281da177e4SLinus Torvalds *string_buf_ptr++ = *yptr++; 1291da177e4SLinus Torvalds } 1301da177e4SLinus Torvalds } 1312628ed2bSHannes Reinecke else { return T_ELSE; } 1321da177e4SLinus Torvalds VERSION { return T_VERSION; } 1331da177e4SLinus Torvalds PREFIX { return T_PREFIX; } 1341da177e4SLinus Torvalds PATCH_ARG_LIST { return T_PATCH_ARG_LIST; } 1351da177e4SLinus Torvalds \" { 1361da177e4SLinus Torvalds string_buf_ptr = string_buf; 1371da177e4SLinus Torvalds BEGIN STRING; 1381da177e4SLinus Torvalds } 1391da177e4SLinus Torvalds <STRING>[^"]+ { 1401da177e4SLinus Torvalds char *yptr; 1411da177e4SLinus Torvalds 1421da177e4SLinus Torvalds yptr = yytext; 1431da177e4SLinus Torvalds while (*yptr) 1441da177e4SLinus Torvalds *string_buf_ptr++ = *yptr++; 1451da177e4SLinus Torvalds } 1461da177e4SLinus Torvalds <STRING>\" { 1471da177e4SLinus Torvalds /* All done */ 1481da177e4SLinus Torvalds BEGIN INITIAL; 1491da177e4SLinus Torvalds *string_buf_ptr = '\0'; 1501da177e4SLinus Torvalds yylval.str = string_buf; 1511da177e4SLinus Torvalds return T_STRING; 1521da177e4SLinus Torvalds } 1531da177e4SLinus Torvalds {SPACE} ; 1541da177e4SLinus Torvalds 1551da177e4SLinus Torvalds /* Register/SCB/SRAM definition keywords */ 1561da177e4SLinus Torvalds export { return T_EXPORT; } 1571da177e4SLinus Torvalds register { return T_REGISTER; } 1581da177e4SLinus Torvalds const { yylval.value = FALSE; return T_CONST; } 1591da177e4SLinus Torvalds download { return T_DOWNLOAD; } 1601da177e4SLinus Torvalds address { return T_ADDRESS; } 1613dbd10f3SHannes Reinecke count { return T_COUNT; } 1621da177e4SLinus Torvalds access_mode { return T_ACCESS_MODE; } 163*fa25b99aSDenys Vlasenko dont_generate_debug_code { return T_DONT_GENERATE_DEBUG_CODE; } 1641da177e4SLinus Torvalds modes { return T_MODES; } 1651da177e4SLinus Torvalds RW|RO|WO { 1661da177e4SLinus Torvalds if (strcmp(yytext, "RW") == 0) 1671da177e4SLinus Torvalds yylval.value = RW; 1681da177e4SLinus Torvalds else if (strcmp(yytext, "RO") == 0) 1691da177e4SLinus Torvalds yylval.value = RO; 1701da177e4SLinus Torvalds else 1711da177e4SLinus Torvalds yylval.value = WO; 1721da177e4SLinus Torvalds return T_MODE; 1731da177e4SLinus Torvalds } 1741da177e4SLinus Torvalds field { return T_FIELD; } 1751da177e4SLinus Torvalds enum { return T_ENUM; } 1761da177e4SLinus Torvalds mask { return T_MASK; } 1771da177e4SLinus Torvalds alias { return T_ALIAS; } 1781da177e4SLinus Torvalds size { return T_SIZE; } 1791da177e4SLinus Torvalds scb { return T_SCB; } 1801da177e4SLinus Torvalds scratch_ram { return T_SRAM; } 1811da177e4SLinus Torvalds accumulator { return T_ACCUM; } 1821da177e4SLinus Torvalds mode_pointer { return T_MODE_PTR; } 1831da177e4SLinus Torvalds allones { return T_ALLONES; } 1841da177e4SLinus Torvalds allzeros { return T_ALLZEROS; } 1851da177e4SLinus Torvalds none { return T_NONE; } 1861da177e4SLinus Torvalds sindex { return T_SINDEX; } 1871da177e4SLinus Torvalds A { return T_A; } 1881da177e4SLinus Torvalds 1892628ed2bSHannes Reinecke /* Instruction Formatting */ 1902628ed2bSHannes Reinecke PAD_PAGE { return T_PAD_PAGE; } 1912628ed2bSHannes Reinecke BEGIN_CRITICAL { return T_BEGIN_CS; } 1922628ed2bSHannes Reinecke END_CRITICAL { return T_END_CS; } 1932628ed2bSHannes Reinecke SET_SRC_MODE { return T_SET_SRC_MODE; } 1942628ed2bSHannes Reinecke SET_DST_MODE { return T_SET_DST_MODE; } 1952628ed2bSHannes Reinecke 1961da177e4SLinus Torvalds /* Opcodes */ 1971da177e4SLinus Torvalds shl { return T_SHL; } 1981da177e4SLinus Torvalds shr { return T_SHR; } 1991da177e4SLinus Torvalds ror { return T_ROR; } 2001da177e4SLinus Torvalds rol { return T_ROL; } 2011da177e4SLinus Torvalds mvi { return T_MVI; } 2021da177e4SLinus Torvalds mov { return T_MOV; } 2031da177e4SLinus Torvalds clr { return T_CLR; } 2041da177e4SLinus Torvalds jmp { return T_JMP; } 2051da177e4SLinus Torvalds jc { return T_JC; } 2061da177e4SLinus Torvalds jnc { return T_JNC; } 2071da177e4SLinus Torvalds je { return T_JE; } 2081da177e4SLinus Torvalds jne { return T_JNE; } 2091da177e4SLinus Torvalds jz { return T_JZ; } 2101da177e4SLinus Torvalds jnz { return T_JNZ; } 2111da177e4SLinus Torvalds call { return T_CALL; } 2121da177e4SLinus Torvalds add { return T_ADD; } 2131da177e4SLinus Torvalds adc { return T_ADC; } 2141da177e4SLinus Torvalds bmov { return T_BMOV; } 2151da177e4SLinus Torvalds inc { return T_INC; } 2161da177e4SLinus Torvalds dec { return T_DEC; } 2171da177e4SLinus Torvalds stc { return T_STC; } 2181da177e4SLinus Torvalds clc { return T_CLC; } 2191da177e4SLinus Torvalds cmp { return T_CMP; } 2201da177e4SLinus Torvalds not { return T_NOT; } 2211da177e4SLinus Torvalds xor { return T_XOR; } 2221da177e4SLinus Torvalds test { return T_TEST;} 2231da177e4SLinus Torvalds and { return T_AND; } 2241da177e4SLinus Torvalds or { return T_OR; } 2251da177e4SLinus Torvalds ret { return T_RET; } 2261da177e4SLinus Torvalds nop { return T_NOP; } 2272628ed2bSHannes Reinecke 2282628ed2bSHannes Reinecke /* ARP2 16bit extensions */ 2292b48aed1SHannes Reinecke /* or16 { return T_OR16; } */ 2302b48aed1SHannes Reinecke /* and16 { return T_AND16; }*/ 2312b48aed1SHannes Reinecke /* xor16 { return T_XOR16; }*/ 2322b48aed1SHannes Reinecke /* add16 { return T_ADD16; }*/ 2332b48aed1SHannes Reinecke /* adc16 { return T_ADC16; }*/ 2342b48aed1SHannes Reinecke /* mvi16 { return T_MVI16; }*/ 2352b48aed1SHannes Reinecke /* test16 { return T_TEST16; }*/ 2362b48aed1SHannes Reinecke /* cmp16 { return T_CMP16; }*/ 2372b48aed1SHannes Reinecke /* cmpxchg { return T_CMPXCHG; }*/ 2381da177e4SLinus Torvalds 2391da177e4SLinus Torvalds /* Allowed Symbols */ 2401da177e4SLinus Torvalds \<\< { return T_EXPR_LSHIFT; } 2411da177e4SLinus Torvalds \>\> { return T_EXPR_RSHIFT; } 2421da177e4SLinus Torvalds [-+,:()~|&."{};<>[\]/*!=] { return yytext[0]; } 2431da177e4SLinus Torvalds 2441da177e4SLinus Torvalds /* Number processing */ 2451da177e4SLinus Torvalds 0[0-7]* { 2461da177e4SLinus Torvalds yylval.value = strtol(yytext, NULL, 8); 2471da177e4SLinus Torvalds return T_NUMBER; 2481da177e4SLinus Torvalds } 2491da177e4SLinus Torvalds 2501da177e4SLinus Torvalds 0[xX][0-9a-fA-F]+ { 2511da177e4SLinus Torvalds yylval.value = strtoul(yytext + 2, NULL, 16); 2521da177e4SLinus Torvalds return T_NUMBER; 2531da177e4SLinus Torvalds } 2541da177e4SLinus Torvalds 2551da177e4SLinus Torvalds [1-9][0-9]* { 2561da177e4SLinus Torvalds yylval.value = strtol(yytext, NULL, 10); 2571da177e4SLinus Torvalds return T_NUMBER; 2581da177e4SLinus Torvalds } 2591da177e4SLinus Torvalds /* Include Files */ 2601da177e4SLinus Torvalds #include{SPACE} { 2611da177e4SLinus Torvalds BEGIN INCLUDE; 2621da177e4SLinus Torvalds quote_count = 0; 2631da177e4SLinus Torvalds return T_INCLUDE; 2641da177e4SLinus Torvalds } 2651da177e4SLinus Torvalds <INCLUDE>[<] { return yytext[0]; } 2661da177e4SLinus Torvalds <INCLUDE>[>] { BEGIN INITIAL; return yytext[0]; } 2671da177e4SLinus Torvalds <INCLUDE>[\"] { 2681da177e4SLinus Torvalds if (quote_count != 0) 2691da177e4SLinus Torvalds BEGIN INITIAL; 2701da177e4SLinus Torvalds quote_count++; 2711da177e4SLinus Torvalds return yytext[0]; 2721da177e4SLinus Torvalds } 2731da177e4SLinus Torvalds <INCLUDE>{PATH} { 2741da177e4SLinus Torvalds char *yptr; 2751da177e4SLinus Torvalds 2761da177e4SLinus Torvalds yptr = yytext; 2771da177e4SLinus Torvalds string_buf_ptr = string_buf; 2781da177e4SLinus Torvalds while (*yptr) 2791da177e4SLinus Torvalds *string_buf_ptr++ = *yptr++; 2801da177e4SLinus Torvalds yylval.str = string_buf; 2811da177e4SLinus Torvalds *string_buf_ptr = '\0'; 2821da177e4SLinus Torvalds return T_PATH; 2831da177e4SLinus Torvalds } 2841da177e4SLinus Torvalds <INCLUDE>. { stop("Invalid include line", EX_DATAERR); } 2851da177e4SLinus Torvalds #define{SPACE} { 2861da177e4SLinus Torvalds BEGIN MACRODEF; 2871da177e4SLinus Torvalds return T_DEFINE; 2881da177e4SLinus Torvalds } 2891da177e4SLinus Torvalds <MACRODEF>{WORD}{SPACE} { 2901da177e4SLinus Torvalds char *yptr; 2911da177e4SLinus Torvalds 2921da177e4SLinus Torvalds /* Strip space and return as a normal symbol */ 2931da177e4SLinus Torvalds yptr = yytext; 2941da177e4SLinus Torvalds while (*yptr != ' ' && *yptr != '\t') 2951da177e4SLinus Torvalds yptr++; 2961da177e4SLinus Torvalds *yptr = '\0'; 2971da177e4SLinus Torvalds yylval.sym = symtable_get(yytext); 2981da177e4SLinus Torvalds string_buf_ptr = string_buf; 2991da177e4SLinus Torvalds BEGIN MACROBODY; 3001da177e4SLinus Torvalds return T_SYMBOL; 3011da177e4SLinus Torvalds } 3021da177e4SLinus Torvalds <MACRODEF>{WORD}\( { 3031da177e4SLinus Torvalds /* 3041da177e4SLinus Torvalds * We store the symbol with its opening 3051da177e4SLinus Torvalds * parren so we can differentiate macros 3061da177e4SLinus Torvalds * that take args from macros with the 3071da177e4SLinus Torvalds * same name that do not take args as 3081da177e4SLinus Torvalds * is allowed in C. 3091da177e4SLinus Torvalds */ 3101da177e4SLinus Torvalds BEGIN MACROARGLIST; 3111da177e4SLinus Torvalds yylval.sym = symtable_get(yytext); 3121da177e4SLinus Torvalds unput('('); 3131da177e4SLinus Torvalds return T_SYMBOL; 3141da177e4SLinus Torvalds } 3151da177e4SLinus Torvalds <MACROARGLIST>{WORD} { 3161da177e4SLinus Torvalds yylval.str = yytext; 3171da177e4SLinus Torvalds return T_ARG; 3181da177e4SLinus Torvalds } 3191da177e4SLinus Torvalds <MACROARGLIST>{SPACE} ; 3201da177e4SLinus Torvalds <MACROARGLIST>[(,] { 3211da177e4SLinus Torvalds return yytext[0]; 3221da177e4SLinus Torvalds } 3231da177e4SLinus Torvalds <MACROARGLIST>[)] { 3241da177e4SLinus Torvalds string_buf_ptr = string_buf; 3251da177e4SLinus Torvalds BEGIN MACROBODY; 3261da177e4SLinus Torvalds return ')'; 3271da177e4SLinus Torvalds } 3281da177e4SLinus Torvalds <MACROARGLIST>. { 3291da177e4SLinus Torvalds snprintf(buf, sizeof(buf), "Invalid character " 3301da177e4SLinus Torvalds "'%c' in macro argument list", 3311da177e4SLinus Torvalds yytext[0]); 3321da177e4SLinus Torvalds stop(buf, EX_DATAERR); 3331da177e4SLinus Torvalds } 3341da177e4SLinus Torvalds <MACROCALLARGS>{SPACE} ; 3351da177e4SLinus Torvalds <MACROCALLARGS>\( { 3361da177e4SLinus Torvalds parren_count++; 3371da177e4SLinus Torvalds if (parren_count == 1) 3381da177e4SLinus Torvalds return ('('); 3391da177e4SLinus Torvalds *string_buf_ptr++ = '('; 3401da177e4SLinus Torvalds } 3411da177e4SLinus Torvalds <MACROCALLARGS>\) { 3421da177e4SLinus Torvalds parren_count--; 3431da177e4SLinus Torvalds if (parren_count == 0) { 3441da177e4SLinus Torvalds BEGIN INITIAL; 3451da177e4SLinus Torvalds return (')'); 3461da177e4SLinus Torvalds } 3471da177e4SLinus Torvalds *string_buf_ptr++ = ')'; 3481da177e4SLinus Torvalds } 3491da177e4SLinus Torvalds <MACROCALLARGS>{MCARG} { 3501da177e4SLinus Torvalds char *yptr; 3511da177e4SLinus Torvalds 3521da177e4SLinus Torvalds yptr = yytext; 3531da177e4SLinus Torvalds while (*yptr) 3541da177e4SLinus Torvalds *string_buf_ptr++ = *yptr++; 3551da177e4SLinus Torvalds } 3561da177e4SLinus Torvalds <MACROCALLARGS>\, { 3571da177e4SLinus Torvalds if (string_buf_ptr != string_buf) { 3581da177e4SLinus Torvalds /* 3591da177e4SLinus Torvalds * Return an argument and 3601da177e4SLinus Torvalds * rescan this comma so we 3611da177e4SLinus Torvalds * can return it as well. 3621da177e4SLinus Torvalds */ 3631da177e4SLinus Torvalds *string_buf_ptr = '\0'; 3641da177e4SLinus Torvalds yylval.str = string_buf; 3651da177e4SLinus Torvalds string_buf_ptr = string_buf; 3661da177e4SLinus Torvalds unput(','); 3671da177e4SLinus Torvalds return T_ARG; 3681da177e4SLinus Torvalds } 3691da177e4SLinus Torvalds return ','; 3701da177e4SLinus Torvalds } 3711da177e4SLinus Torvalds <MACROBODY>\\\n { 3721da177e4SLinus Torvalds /* Eat escaped newlines. */ 3731da177e4SLinus Torvalds ++yylineno; 3741da177e4SLinus Torvalds } 3751da177e4SLinus Torvalds <MACROBODY>\r ; 3761da177e4SLinus Torvalds <MACROBODY>\n { 3771da177e4SLinus Torvalds /* Macros end on the first unescaped newline. */ 3781da177e4SLinus Torvalds BEGIN INITIAL; 3791da177e4SLinus Torvalds *string_buf_ptr = '\0'; 3801da177e4SLinus Torvalds yylval.str = string_buf; 3811da177e4SLinus Torvalds ++yylineno; 3821da177e4SLinus Torvalds return T_MACROBODY; 3831da177e4SLinus Torvalds } 3841da177e4SLinus Torvalds <MACROBODY>{MBODY} { 3851da177e4SLinus Torvalds char *yptr; 3861da177e4SLinus Torvalds char c; 3871da177e4SLinus Torvalds 3881da177e4SLinus Torvalds yptr = yytext; 3891da177e4SLinus Torvalds while (c = *yptr++) { 3901da177e4SLinus Torvalds /* 3911da177e4SLinus Torvalds * Strip carriage returns. 3921da177e4SLinus Torvalds */ 3931da177e4SLinus Torvalds if (c == '\r') 3941da177e4SLinus Torvalds continue; 3951da177e4SLinus Torvalds *string_buf_ptr++ = c; 3961da177e4SLinus Torvalds } 3971da177e4SLinus Torvalds } 3981da177e4SLinus Torvalds {WORD}\( { 3991da177e4SLinus Torvalds char *yptr; 4001da177e4SLinus Torvalds char *ycopy; 4011da177e4SLinus Torvalds 4021da177e4SLinus Torvalds /* May be a symbol or a macro invocation. */ 4031da177e4SLinus Torvalds yylval.sym = symtable_get(yytext); 4041da177e4SLinus Torvalds if (yylval.sym->type == MACRO) { 4051da177e4SLinus Torvalds YY_BUFFER_STATE old_state; 4061da177e4SLinus Torvalds YY_BUFFER_STATE temp_state; 4071da177e4SLinus Torvalds 4081da177e4SLinus Torvalds ycopy = strdup(yytext); 4091da177e4SLinus Torvalds yptr = ycopy + yyleng; 4101da177e4SLinus Torvalds while (yptr > ycopy) 4111da177e4SLinus Torvalds unput(*--yptr); 4121da177e4SLinus Torvalds old_state = YY_CURRENT_BUFFER; 4131da177e4SLinus Torvalds temp_state = 4141da177e4SLinus Torvalds yy_create_buffer(stdin, 4151da177e4SLinus Torvalds YY_BUF_SIZE); 4161da177e4SLinus Torvalds yy_switch_to_buffer(temp_state); 4171da177e4SLinus Torvalds mm_switch_to_buffer(old_state); 4181da177e4SLinus Torvalds mmparse(); 4191da177e4SLinus Torvalds mm_switch_to_buffer(temp_state); 4201da177e4SLinus Torvalds yy_switch_to_buffer(old_state); 4211da177e4SLinus Torvalds mm_delete_buffer(temp_state); 4221da177e4SLinus Torvalds expand_macro(yylval.sym); 4231da177e4SLinus Torvalds } else { 4241da177e4SLinus Torvalds if (yylval.sym->type == UNINITIALIZED) { 4251da177e4SLinus Torvalds /* Try without the '(' */ 4261da177e4SLinus Torvalds symbol_delete(yylval.sym); 4271da177e4SLinus Torvalds yytext[yyleng-1] = '\0'; 4281da177e4SLinus Torvalds yylval.sym = 4291da177e4SLinus Torvalds symtable_get(yytext); 4301da177e4SLinus Torvalds } 4311da177e4SLinus Torvalds unput('('); 4321da177e4SLinus Torvalds return T_SYMBOL; 4331da177e4SLinus Torvalds } 4341da177e4SLinus Torvalds } 4351da177e4SLinus Torvalds {WORD} { 4361da177e4SLinus Torvalds yylval.sym = symtable_get(yytext); 4371da177e4SLinus Torvalds if (yylval.sym->type == MACRO) { 4381da177e4SLinus Torvalds expand_macro(yylval.sym); 4391da177e4SLinus Torvalds } else { 4401da177e4SLinus Torvalds return T_SYMBOL; 4411da177e4SLinus Torvalds } 4421da177e4SLinus Torvalds } 4431da177e4SLinus Torvalds . { 4441da177e4SLinus Torvalds snprintf(buf, sizeof(buf), "Invalid character " 4451da177e4SLinus Torvalds "'%c'", yytext[0]); 4461da177e4SLinus Torvalds stop(buf, EX_DATAERR); 4471da177e4SLinus Torvalds } 4481da177e4SLinus Torvalds %% 4491da177e4SLinus Torvalds 4501da177e4SLinus Torvalds typedef struct include { 4511da177e4SLinus Torvalds YY_BUFFER_STATE buffer; 4521da177e4SLinus Torvalds int lineno; 4531da177e4SLinus Torvalds char *filename; 4541da177e4SLinus Torvalds SLIST_ENTRY(include) links; 4551da177e4SLinus Torvalds }include_t; 4561da177e4SLinus Torvalds 4571da177e4SLinus Torvalds SLIST_HEAD(, include) include_stack; 4581da177e4SLinus Torvalds 4591da177e4SLinus Torvalds void 4601da177e4SLinus Torvalds include_file(char *file_name, include_type type) 4611da177e4SLinus Torvalds { 4621da177e4SLinus Torvalds FILE *newfile; 4631da177e4SLinus Torvalds include_t *include; 4641da177e4SLinus Torvalds 4651da177e4SLinus Torvalds newfile = NULL; 4661da177e4SLinus Torvalds /* Try the current directory first */ 4671da177e4SLinus Torvalds if (includes_search_curdir != 0 || type == SOURCE_FILE) 4681da177e4SLinus Torvalds newfile = fopen(file_name, "r"); 4691da177e4SLinus Torvalds 4701da177e4SLinus Torvalds if (newfile == NULL && type != SOURCE_FILE) { 4711da177e4SLinus Torvalds path_entry_t include_dir; 4721da177e4SLinus Torvalds for (include_dir = search_path.slh_first; 4731da177e4SLinus Torvalds include_dir != NULL; 4741da177e4SLinus Torvalds include_dir = include_dir->links.sle_next) { 4751da177e4SLinus Torvalds char fullname[PATH_MAX]; 4761da177e4SLinus Torvalds 4771da177e4SLinus Torvalds if ((include_dir->quoted_includes_only == TRUE) 4781da177e4SLinus Torvalds && (type != QUOTED_INCLUDE)) 4791da177e4SLinus Torvalds continue; 4801da177e4SLinus Torvalds 4811da177e4SLinus Torvalds snprintf(fullname, sizeof(fullname), 4821da177e4SLinus Torvalds "%s/%s", include_dir->directory, file_name); 4831da177e4SLinus Torvalds 4841da177e4SLinus Torvalds if ((newfile = fopen(fullname, "r")) != NULL) 4851da177e4SLinus Torvalds break; 4861da177e4SLinus Torvalds } 4871da177e4SLinus Torvalds } 4881da177e4SLinus Torvalds 4891da177e4SLinus Torvalds if (newfile == NULL) { 4901da177e4SLinus Torvalds perror(file_name); 4911da177e4SLinus Torvalds stop("Unable to open input file", EX_SOFTWARE); 4921da177e4SLinus Torvalds /* NOTREACHED */ 4931da177e4SLinus Torvalds } 4941da177e4SLinus Torvalds 4951da177e4SLinus Torvalds if (type != SOURCE_FILE) { 4961da177e4SLinus Torvalds include = (include_t *)malloc(sizeof(include_t)); 4971da177e4SLinus Torvalds if (include == NULL) { 4981da177e4SLinus Torvalds stop("Unable to allocate include stack entry", 4991da177e4SLinus Torvalds EX_SOFTWARE); 5001da177e4SLinus Torvalds /* NOTREACHED */ 5011da177e4SLinus Torvalds } 5021da177e4SLinus Torvalds include->buffer = YY_CURRENT_BUFFER; 5031da177e4SLinus Torvalds include->lineno = yylineno; 5041da177e4SLinus Torvalds include->filename = yyfilename; 5051da177e4SLinus Torvalds SLIST_INSERT_HEAD(&include_stack, include, links); 5061da177e4SLinus Torvalds } 5071da177e4SLinus Torvalds yy_switch_to_buffer(yy_create_buffer(newfile, YY_BUF_SIZE)); 5081da177e4SLinus Torvalds yylineno = 1; 5091da177e4SLinus Torvalds yyfilename = strdup(file_name); 5101da177e4SLinus Torvalds } 5111da177e4SLinus Torvalds 5121da177e4SLinus Torvalds static void next_substitution(struct symbol *mac_symbol, const char *body_pos, 5131da177e4SLinus Torvalds const char **next_match, 5141da177e4SLinus Torvalds struct macro_arg **match_marg, regmatch_t *match); 5151da177e4SLinus Torvalds 5161da177e4SLinus Torvalds void 5171da177e4SLinus Torvalds expand_macro(struct symbol *macro_symbol) 5181da177e4SLinus Torvalds { 5191da177e4SLinus Torvalds struct macro_arg *marg; 5201da177e4SLinus Torvalds struct macro_arg *match_marg; 5211da177e4SLinus Torvalds const char *body_head; 5221da177e4SLinus Torvalds const char *body_pos; 5231da177e4SLinus Torvalds const char *next_match; 5241da177e4SLinus Torvalds 5251da177e4SLinus Torvalds /* 5261da177e4SLinus Torvalds * Due to the nature of unput, we must work 5271da177e4SLinus Torvalds * backwards through the macro body performing 5281da177e4SLinus Torvalds * any expansions. 5291da177e4SLinus Torvalds */ 5301da177e4SLinus Torvalds body_head = macro_symbol->info.macroinfo->body; 5311da177e4SLinus Torvalds body_pos = body_head + strlen(body_head); 5321da177e4SLinus Torvalds while (body_pos > body_head) { 5331da177e4SLinus Torvalds regmatch_t match; 5341da177e4SLinus Torvalds 5351da177e4SLinus Torvalds next_match = body_head; 5361da177e4SLinus Torvalds match_marg = NULL; 5371da177e4SLinus Torvalds next_substitution(macro_symbol, body_pos, &next_match, 5381da177e4SLinus Torvalds &match_marg, &match); 5391da177e4SLinus Torvalds 5401da177e4SLinus Torvalds /* Put back everything up until the replacement. */ 5411da177e4SLinus Torvalds while (body_pos > next_match) 5421da177e4SLinus Torvalds unput(*--body_pos); 5431da177e4SLinus Torvalds 5441da177e4SLinus Torvalds /* Perform the replacement. */ 5451da177e4SLinus Torvalds if (match_marg != NULL) { 5461da177e4SLinus Torvalds const char *strp; 5471da177e4SLinus Torvalds 5481da177e4SLinus Torvalds next_match = match_marg->replacement_text; 5491da177e4SLinus Torvalds strp = next_match + strlen(next_match); 5501da177e4SLinus Torvalds while (strp > next_match) 5511da177e4SLinus Torvalds unput(*--strp); 5521da177e4SLinus Torvalds 5531da177e4SLinus Torvalds /* Skip past the unexpanded macro arg. */ 5541da177e4SLinus Torvalds body_pos -= match.rm_eo - match.rm_so; 5551da177e4SLinus Torvalds } 5561da177e4SLinus Torvalds } 5571da177e4SLinus Torvalds 5581da177e4SLinus Torvalds /* Cleanup replacement text. */ 5591da177e4SLinus Torvalds STAILQ_FOREACH(marg, ¯o_symbol->info.macroinfo->args, links) { 5601da177e4SLinus Torvalds free(marg->replacement_text); 5611da177e4SLinus Torvalds } 5621da177e4SLinus Torvalds } 5631da177e4SLinus Torvalds 5641da177e4SLinus Torvalds /* 5651da177e4SLinus Torvalds * Find the next substitution in the macro working backwards from 5661da177e4SLinus Torvalds * body_pos until the beginning of the macro buffer. next_match 5671da177e4SLinus Torvalds * should be initialized to the beginning of the macro buffer prior 5681da177e4SLinus Torvalds * to calling this routine. 5691da177e4SLinus Torvalds */ 5701da177e4SLinus Torvalds static void 5711da177e4SLinus Torvalds next_substitution(struct symbol *mac_symbol, const char *body_pos, 5721da177e4SLinus Torvalds const char **next_match, struct macro_arg **match_marg, 5731da177e4SLinus Torvalds regmatch_t *match) 5741da177e4SLinus Torvalds { 5751da177e4SLinus Torvalds regmatch_t matches[2]; 5761da177e4SLinus Torvalds struct macro_arg *marg; 5771da177e4SLinus Torvalds const char *search_pos; 5781da177e4SLinus Torvalds int retval; 5791da177e4SLinus Torvalds 5801da177e4SLinus Torvalds do { 5811da177e4SLinus Torvalds search_pos = *next_match; 5821da177e4SLinus Torvalds 5831da177e4SLinus Torvalds STAILQ_FOREACH(marg, &mac_symbol->info.macroinfo->args, links) { 5841da177e4SLinus Torvalds 5851da177e4SLinus Torvalds retval = regexec(&marg->arg_regex, search_pos, 2, 5861da177e4SLinus Torvalds matches, 0); 5871da177e4SLinus Torvalds if (retval == 0 5881da177e4SLinus Torvalds && (matches[1].rm_eo + search_pos) <= body_pos 5891da177e4SLinus Torvalds && (matches[1].rm_eo + search_pos) > *next_match) { 5901da177e4SLinus Torvalds *match = matches[1]; 5911da177e4SLinus Torvalds *next_match = match->rm_eo + search_pos; 5921da177e4SLinus Torvalds *match_marg = marg; 5931da177e4SLinus Torvalds } 5941da177e4SLinus Torvalds } 5951da177e4SLinus Torvalds } while (search_pos != *next_match); 5961da177e4SLinus Torvalds } 5971da177e4SLinus Torvalds 5981da177e4SLinus Torvalds int 5991da177e4SLinus Torvalds yywrap() 6001da177e4SLinus Torvalds { 6011da177e4SLinus Torvalds include_t *include; 6021da177e4SLinus Torvalds 6031da177e4SLinus Torvalds yy_delete_buffer(YY_CURRENT_BUFFER); 6041da177e4SLinus Torvalds (void)fclose(yyin); 6051da177e4SLinus Torvalds if (yyfilename != NULL) 6061da177e4SLinus Torvalds free(yyfilename); 6071da177e4SLinus Torvalds yyfilename = NULL; 6081da177e4SLinus Torvalds include = include_stack.slh_first; 6091da177e4SLinus Torvalds if (include != NULL) { 6101da177e4SLinus Torvalds yy_switch_to_buffer(include->buffer); 6111da177e4SLinus Torvalds yylineno = include->lineno; 6121da177e4SLinus Torvalds yyfilename = include->filename; 6131da177e4SLinus Torvalds SLIST_REMOVE_HEAD(&include_stack, links); 6141da177e4SLinus Torvalds free(include); 6151da177e4SLinus Torvalds return (0); 6161da177e4SLinus Torvalds } 6171da177e4SLinus Torvalds return (1); 6181da177e4SLinus Torvalds } 619