xref: /linux/drivers/scsi/aic7xxx/aicasm/aicasm_scan.l (revision 3eb66e91a25497065c5322b1268cbc3953642227)
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, &macro_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