xref: /freebsd/sys/dev/aic7xxx/aicasm/aicasm_scan.l (revision 95ee2897e98f5d444f26ed2334cc7c439f9c16c6)
1c5cb3888SJustin T. Gibbs %{
2098ca2bdSWarner Losh /*-
3c5cb3888SJustin T. Gibbs  * Lexical Analyzer for the Aic7xxx SCSI Host adapter sequencer assembler.
4c5cb3888SJustin T. Gibbs  *
5*718cf2ccSPedro F. Giffuni  * SPDX-License-Identifier: BSD-3-Clause
6*718cf2ccSPedro F. Giffuni  *
77ce72dbaSJustin T. Gibbs  * Copyright (c) 1997, 1998, 2000 Justin T. Gibbs.
863183d8cSJustin T. Gibbs  * Copyright (c) 2001, 2002 Adaptec Inc.
9c5cb3888SJustin T. Gibbs  * All rights reserved.
10c5cb3888SJustin T. Gibbs  *
11c5cb3888SJustin T. Gibbs  * Redistribution and use in source and binary forms, with or without
12c5cb3888SJustin T. Gibbs  * modification, are permitted provided that the following conditions
13c5cb3888SJustin T. Gibbs  * are met:
14c5cb3888SJustin T. Gibbs  * 1. Redistributions of source code must retain the above copyright
15f68f348bSJustin T. Gibbs  *    notice, this list of conditions, and the following disclaimer,
1641c47eeeSJustin T. Gibbs  *    without modification.
177ce72dbaSJustin T. Gibbs  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
187ce72dbaSJustin T. Gibbs  *    substantially similar to the "NO WARRANTY" disclaimer below
197ce72dbaSJustin T. Gibbs  *    ("Disclaimer") and any redistribution must be conditioned upon
207ce72dbaSJustin T. Gibbs  *    including a substantially similar Disclaimer requirement for further
217ce72dbaSJustin T. Gibbs  *    binary redistribution.
227ce72dbaSJustin T. Gibbs  * 3. Neither the names of the above-listed copyright holders nor the names
237ce72dbaSJustin T. Gibbs  *    of any contributors may be used to endorse or promote products derived
247ce72dbaSJustin T. Gibbs  *    from this software without specific prior written permission.
25c5cb3888SJustin T. Gibbs  *
26aa6dfd9dSJustin T. Gibbs  * Alternatively, this software may be distributed under the terms of the
277ce72dbaSJustin T. Gibbs  * GNU General Public License ("GPL") version 2 as published by the Free
287ce72dbaSJustin T. Gibbs  * Software Foundation.
29aa6dfd9dSJustin T. Gibbs  *
307ce72dbaSJustin T. Gibbs  * NO WARRANTY
317ce72dbaSJustin T. Gibbs  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
327ce72dbaSJustin T. Gibbs  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
337ce72dbaSJustin T. Gibbs  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
347ce72dbaSJustin T. Gibbs  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
357ce72dbaSJustin T. Gibbs  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36c5cb3888SJustin T. Gibbs  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37c5cb3888SJustin T. Gibbs  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
387ce72dbaSJustin T. Gibbs  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
397ce72dbaSJustin T. Gibbs  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
407ce72dbaSJustin T. Gibbs  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
417ce72dbaSJustin T. Gibbs  * POSSIBILITY OF SUCH DAMAGES.
42c5cb3888SJustin T. Gibbs  *
43708d2cb0SJustin T. Gibbs  * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_scan.l#19 $
44c5cb3888SJustin T. Gibbs  */
45c5cb3888SJustin T. Gibbs 
4660b161a9SBruce Evans #include <sys/types.h>
4760b161a9SBruce Evans 
4899ddedd8SJustin T. Gibbs #include <inttypes.h>
49c5cb3888SJustin T. Gibbs #include <limits.h>
507ce72dbaSJustin T. Gibbs #include <regex.h>
51c5cb3888SJustin T. Gibbs #include <stdio.h>
52c5cb3888SJustin T. Gibbs #include <string.h>
53c5cb3888SJustin T. Gibbs #include <sysexits.h>
54c5cb3888SJustin T. Gibbs #include <sys/queue.h>
55c5cb3888SJustin T. Gibbs 
56c66dbc92SJustin T. Gibbs #include "aicasm.h"
57c66dbc92SJustin T. Gibbs #include "aicasm_symbol.h"
587ce72dbaSJustin T. Gibbs #include "aicasm_gram.h"
593bafc9d4SJustin T. Gibbs 
607ce72dbaSJustin T. Gibbs /* This is used for macro body capture too, so err on the large size. */
617ce72dbaSJustin T. Gibbs #define MAX_STR_CONST 4096
627ce72dbaSJustin T. Gibbs static char string_buf[MAX_STR_CONST];
637ce72dbaSJustin T. Gibbs static char *string_buf_ptr;
647ce72dbaSJustin T. Gibbs static int  parren_count;
657ce72dbaSJustin T. Gibbs static int  quote_count;
66b18a2ef1SXin LI static char msgbuf[255];
67b18a2ef1SXin LI 
68b18a2ef1SXin LI extern int yylex(void);
69b18a2ef1SXin LI extern int mmlex(void);
70b18a2ef1SXin LI extern int mmparse(void);
71b18a2ef1SXin LI extern void mm_switch_to_buffer(YY_BUFFER_STATE);
72b18a2ef1SXin LI extern void mm_delete_buffer(YY_BUFFER_STATE);
73c5cb3888SJustin T. Gibbs %}
74c5cb3888SJustin T. Gibbs 
75487d088eSDimitry Andric %option noinput
76487d088eSDimitry Andric 
777ce72dbaSJustin T. Gibbs PATH		([/]*[-A-Za-z0-9_.])+
78c5cb3888SJustin T. Gibbs WORD		[A-Za-z_][-A-Za-z_0-9]*
79c5cb3888SJustin T. Gibbs SPACE		[ \t]+
807ce72dbaSJustin T. Gibbs MCARG		[^(), \t]+
817ce72dbaSJustin T. Gibbs MBODY		((\\[^\n])*[^\n\\]*)+
82c5cb3888SJustin T. Gibbs 
83c5cb3888SJustin T. Gibbs %x COMMENT
843bafc9d4SJustin T. Gibbs %x CEXPR
853bafc9d4SJustin T. Gibbs %x INCLUDE
862d0fbde8SJustin T. Gibbs %x STRING
877ce72dbaSJustin T. Gibbs %x MACRODEF
887ce72dbaSJustin T. Gibbs %x MACROARGLIST
897ce72dbaSJustin T. Gibbs %x MACROCALLARGS
907ce72dbaSJustin T. Gibbs %x MACROBODY
91c5cb3888SJustin T. Gibbs 
92c5cb3888SJustin T. Gibbs %%
93c5cb3888SJustin T. Gibbs \n			{ ++yylineno; }
94708d2cb0SJustin T. Gibbs \r			;
95c5cb3888SJustin T. Gibbs "/*"			{ BEGIN COMMENT;  /* Enter comment eating state */ }
96c5cb3888SJustin T. Gibbs <COMMENT>"/*"		{ fprintf(stderr, "Warning! Comment within comment."); }
97c5cb3888SJustin T. Gibbs <COMMENT>\n		{ ++yylineno; }
98c5cb3888SJustin T. Gibbs <COMMENT>[^*/\n]*	;
99c5cb3888SJustin T. Gibbs <COMMENT>"*"+[^*/\n]*	;
100c5cb3888SJustin T. Gibbs <COMMENT>"/"+[^*/\n]*	;
101c5cb3888SJustin T. Gibbs <COMMENT>"*"+"/"	{ BEGIN INITIAL; }
1023bafc9d4SJustin T. Gibbs if[ \t]*\(		{
1033bafc9d4SJustin T. Gibbs 				string_buf_ptr = string_buf;
1043bafc9d4SJustin T. Gibbs 				parren_count = 1;
1053bafc9d4SJustin T. Gibbs 				BEGIN CEXPR;
1063bafc9d4SJustin T. Gibbs 				return T_IF;
1073bafc9d4SJustin T. Gibbs 			}
1083bafc9d4SJustin T. Gibbs <CEXPR>\(		{	*string_buf_ptr++ = '('; parren_count++; }
1093bafc9d4SJustin T. Gibbs <CEXPR>\)		{
1103bafc9d4SJustin T. Gibbs 				parren_count--;
1113bafc9d4SJustin T. Gibbs 				if (parren_count == 0) {
1123bafc9d4SJustin T. Gibbs 					/* All done */
1133bafc9d4SJustin T. Gibbs 					BEGIN INITIAL;
1143bafc9d4SJustin T. Gibbs 					*string_buf_ptr = '\0';
1153bafc9d4SJustin T. Gibbs 					yylval.sym = symtable_get(string_buf);
1163bafc9d4SJustin T. Gibbs 					return T_CEXPR;
1173bafc9d4SJustin T. Gibbs 				} else {
1183bafc9d4SJustin T. Gibbs 					*string_buf_ptr++ = ')';
1193bafc9d4SJustin T. Gibbs 				}
1203bafc9d4SJustin T. Gibbs 			}
1213bafc9d4SJustin T. Gibbs <CEXPR>\n		{ ++yylineno; }
122708d2cb0SJustin T. Gibbs <CEXPR>\r		;
1233bafc9d4SJustin T. Gibbs <CEXPR>[^()\n]+	{
1242d0fbde8SJustin T. Gibbs 				char *yptr;
1253bafc9d4SJustin T. Gibbs 
1262d0fbde8SJustin T. Gibbs 				yptr = yytext;
12732da3127SJustin T. Gibbs 				while (*yptr != '\0') {
12832da3127SJustin T. Gibbs 					/* Remove duplicate spaces */
12932da3127SJustin T. Gibbs 					if (*yptr == '\t')
13032da3127SJustin T. Gibbs 						*yptr = ' ';
13132da3127SJustin T. Gibbs 					if (*yptr == ' '
13232da3127SJustin T. Gibbs 					 && string_buf_ptr != string_buf
13332da3127SJustin T. Gibbs 					 && string_buf_ptr[-1] == ' ')
13432da3127SJustin T. Gibbs 						yptr++;
13532da3127SJustin T. Gibbs 					else
1363bafc9d4SJustin T. Gibbs 						*string_buf_ptr++ = *yptr++;
1373bafc9d4SJustin T. Gibbs 				}
13832da3127SJustin T. Gibbs 			}
139c5cb3888SJustin T. Gibbs 
1402d0fbde8SJustin T. Gibbs VERSION			{ return T_VERSION; }
14163183d8cSJustin T. Gibbs PREFIX			{ return T_PREFIX; }
1427ce72dbaSJustin T. Gibbs PATCH_ARG_LIST		{ return T_PATCH_ARG_LIST; }
1432d0fbde8SJustin T. Gibbs \"			{
1442d0fbde8SJustin T. Gibbs 				string_buf_ptr = string_buf;
1452d0fbde8SJustin T. Gibbs 				BEGIN STRING;
1462d0fbde8SJustin T. Gibbs 			}
1472d0fbde8SJustin T. Gibbs <STRING>[^"]+		{
1482d0fbde8SJustin T. Gibbs 				char *yptr;
1492d0fbde8SJustin T. Gibbs 
1502d0fbde8SJustin T. Gibbs 				yptr = yytext;
1512d0fbde8SJustin T. Gibbs 				while (*yptr)
1522d0fbde8SJustin T. Gibbs 					*string_buf_ptr++ = *yptr++;
1532d0fbde8SJustin T. Gibbs 			}
1542d0fbde8SJustin T. Gibbs <STRING>\"		{
1552d0fbde8SJustin T. Gibbs 				/* All done */
1562d0fbde8SJustin T. Gibbs 				BEGIN INITIAL;
1572d0fbde8SJustin T. Gibbs 				*string_buf_ptr = '\0';
1582d0fbde8SJustin T. Gibbs 				yylval.str = string_buf;
1592d0fbde8SJustin T. Gibbs 				return T_STRING;
1602d0fbde8SJustin T. Gibbs 			}
161c5cb3888SJustin T. Gibbs {SPACE}			 ;
162c5cb3888SJustin T. Gibbs 
163c5cb3888SJustin T. Gibbs 	/* Register/SCB/SRAM definition keywords */
1647ce72dbaSJustin T. Gibbs export			{ return T_EXPORT; }
165c5cb3888SJustin T. Gibbs register		{ return T_REGISTER; }
166c5cb3888SJustin T. Gibbs const			{ yylval.value = FALSE; return T_CONST; }
16737507c1bSJustin T. Gibbs download		{ return T_DOWNLOAD; }
168c5cb3888SJustin T. Gibbs address			{ return T_ADDRESS; }
169c5cb3888SJustin T. Gibbs access_mode		{ return T_ACCESS_MODE; }
1707ce72dbaSJustin T. Gibbs modes			{ return T_MODES; }
171c5cb3888SJustin T. Gibbs RW|RO|WO		{
172c5cb3888SJustin T. Gibbs 				 if (strcmp(yytext, "RW") == 0)
173c5cb3888SJustin T. Gibbs 					yylval.value = RW;
174c5cb3888SJustin T. Gibbs 				 else if (strcmp(yytext, "RO") == 0)
175c5cb3888SJustin T. Gibbs 					yylval.value = RO;
176c5cb3888SJustin T. Gibbs 				 else
177c5cb3888SJustin T. Gibbs 					yylval.value = WO;
178c5cb3888SJustin T. Gibbs 				 return T_MODE;
179c5cb3888SJustin T. Gibbs 			}
180083d01f2SJustin T. Gibbs BEGIN_CRITICAL		{ return T_BEGIN_CS; }
181083d01f2SJustin T. Gibbs END_CRITICAL		{ return T_END_CS; }
1827ce72dbaSJustin T. Gibbs SET_SRC_MODE		{ return T_SET_SRC_MODE; }
1837ce72dbaSJustin T. Gibbs SET_DST_MODE		{ return T_SET_DST_MODE; }
18463183d8cSJustin T. Gibbs field			{ return T_FIELD; }
18563183d8cSJustin T. Gibbs enum			{ return T_ENUM; }
186c5cb3888SJustin T. Gibbs mask			{ return T_MASK; }
187c5cb3888SJustin T. Gibbs alias			{ return T_ALIAS; }
188c5cb3888SJustin T. Gibbs size			{ return T_SIZE; }
189c5cb3888SJustin T. Gibbs scb			{ return T_SCB; }
190c5cb3888SJustin T. Gibbs scratch_ram		{ return T_SRAM; }
191c5cb3888SJustin T. Gibbs accumulator		{ return T_ACCUM; }
1927ce72dbaSJustin T. Gibbs mode_pointer		{ return T_MODE_PTR; }
193c5cb3888SJustin T. Gibbs allones			{ return T_ALLONES; }
194c5cb3888SJustin T. Gibbs allzeros		{ return T_ALLZEROS; }
195c5cb3888SJustin T. Gibbs none			{ return T_NONE; }
196c5cb3888SJustin T. Gibbs sindex			{ return T_SINDEX; }
197c5cb3888SJustin T. Gibbs A			{ return T_A; }
198c5cb3888SJustin T. Gibbs 
199c5cb3888SJustin T. Gibbs 	/* Opcodes */
200c5cb3888SJustin T. Gibbs shl			{ return T_SHL; }
201c5cb3888SJustin T. Gibbs shr			{ return T_SHR; }
202c5cb3888SJustin T. Gibbs ror			{ return T_ROR; }
203c5cb3888SJustin T. Gibbs rol			{ return T_ROL; }
204c5cb3888SJustin T. Gibbs mvi			{ return T_MVI; }
205c5cb3888SJustin T. Gibbs mov			{ return T_MOV; }
206c5cb3888SJustin T. Gibbs clr			{ return T_CLR; }
207c5cb3888SJustin T. Gibbs jmp			{ return T_JMP; }
208c5cb3888SJustin T. Gibbs jc			{ return T_JC;	}
209c5cb3888SJustin T. Gibbs jnc			{ return T_JNC;	}
210c5cb3888SJustin T. Gibbs je			{ return T_JE;	}
211c5cb3888SJustin T. Gibbs jne			{ return T_JNE;	}
212c5cb3888SJustin T. Gibbs jz			{ return T_JZ;	}
213c5cb3888SJustin T. Gibbs jnz			{ return T_JNZ;	}
214c5cb3888SJustin T. Gibbs call			{ return T_CALL; }
215c5cb3888SJustin T. Gibbs add			{ return T_ADD; }
216c5cb3888SJustin T. Gibbs adc			{ return T_ADC; }
2173bafc9d4SJustin T. Gibbs bmov			{ return T_BMOV; }
218c5cb3888SJustin T. Gibbs inc			{ return T_INC; }
219c5cb3888SJustin T. Gibbs dec			{ return T_DEC; }
220c5cb3888SJustin T. Gibbs stc			{ return T_STC;	}
221c5cb3888SJustin T. Gibbs clc			{ return T_CLC; }
222c5cb3888SJustin T. Gibbs cmp			{ return T_CMP;	}
223aa6dfd9dSJustin T. Gibbs not			{ return T_NOT;	}
224c5cb3888SJustin T. Gibbs xor			{ return T_XOR;	}
225c5cb3888SJustin T. Gibbs test			{ return T_TEST;}
226c5cb3888SJustin T. Gibbs and			{ return T_AND;	}
227c5cb3888SJustin T. Gibbs or			{ return T_OR;	}
228c5cb3888SJustin T. Gibbs ret			{ return T_RET; }
229c5cb3888SJustin T. Gibbs nop			{ return T_NOP; }
2303bafc9d4SJustin T. Gibbs else			{ return T_ELSE; }
231c5cb3888SJustin T. Gibbs 
232c5cb3888SJustin T. Gibbs 	/* Allowed Symbols */
2337ce72dbaSJustin T. Gibbs \<\<			{ return T_EXPR_LSHIFT; }
2347ce72dbaSJustin T. Gibbs \>\>			{ return T_EXPR_RSHIFT; }
2357ce72dbaSJustin T. Gibbs [-+,:()~|&."{};<>[\]/*!=] { return yytext[0]; }
236c5cb3888SJustin T. Gibbs 
237c5cb3888SJustin T. Gibbs 	/* Number processing */
238c5cb3888SJustin T. Gibbs 0[0-7]*			{
239c5cb3888SJustin T. Gibbs 				yylval.value = strtol(yytext, NULL, 8);
240c5cb3888SJustin T. Gibbs 				return T_NUMBER;
241c5cb3888SJustin T. Gibbs 			}
242c5cb3888SJustin T. Gibbs 
243c5cb3888SJustin T. Gibbs 0[xX][0-9a-fA-F]+	{
244c5cb3888SJustin T. Gibbs 				yylval.value = strtoul(yytext + 2, NULL, 16);
245c5cb3888SJustin T. Gibbs 				return T_NUMBER;
246c5cb3888SJustin T. Gibbs 			}
247c5cb3888SJustin T. Gibbs 
248c5cb3888SJustin T. Gibbs [1-9][0-9]*		{
249c5cb3888SJustin T. Gibbs 				yylval.value = strtol(yytext, NULL, 10);
250c5cb3888SJustin T. Gibbs 				return T_NUMBER;
251c5cb3888SJustin T. Gibbs 			}
252c5cb3888SJustin T. Gibbs 	/* Include Files */
2532d0fbde8SJustin T. Gibbs #include{SPACE}		{
2542d0fbde8SJustin T. Gibbs 				BEGIN INCLUDE;
2552d0fbde8SJustin T. Gibbs 				quote_count = 0;
2562d0fbde8SJustin T. Gibbs 				return T_INCLUDE;
2572d0fbde8SJustin T. Gibbs 			}
2582d0fbde8SJustin T. Gibbs <INCLUDE>[<]		{ return yytext[0]; }
2592d0fbde8SJustin T. Gibbs <INCLUDE>[>]		{ BEGIN INITIAL; return yytext[0]; }
2602d0fbde8SJustin T. Gibbs <INCLUDE>[\"]		{
2612d0fbde8SJustin T. Gibbs 				if (quote_count != 0)
2622d0fbde8SJustin T. Gibbs 					BEGIN INITIAL;
2632d0fbde8SJustin T. Gibbs 				quote_count++;
2642d0fbde8SJustin T. Gibbs 				return yytext[0];
2652d0fbde8SJustin T. Gibbs 			}
2667ce72dbaSJustin T. Gibbs <INCLUDE>{PATH}		{
2672d0fbde8SJustin T. Gibbs 				char *yptr;
2682d0fbde8SJustin T. Gibbs 
2692d0fbde8SJustin T. Gibbs 				yptr = yytext;
2702d0fbde8SJustin T. Gibbs 				string_buf_ptr = string_buf;
2712d0fbde8SJustin T. Gibbs 				while (*yptr)
2722d0fbde8SJustin T. Gibbs 					*string_buf_ptr++ = *yptr++;
2732d0fbde8SJustin T. Gibbs 				yylval.str = string_buf;
2742d0fbde8SJustin T. Gibbs 				*string_buf_ptr = '\0';
2752d0fbde8SJustin T. Gibbs 				return T_PATH;
2762d0fbde8SJustin T. Gibbs 			}
2777ce72dbaSJustin T. Gibbs <INCLUDE>.		{ stop("Invalid include line", EX_DATAERR); }
2787ce72dbaSJustin T. Gibbs #define{SPACE}		{
2797ce72dbaSJustin T. Gibbs 				BEGIN MACRODEF;
2807ce72dbaSJustin T. Gibbs 				return T_DEFINE;
2817ce72dbaSJustin T. Gibbs 			}
2827ce72dbaSJustin T. Gibbs <MACRODEF>{WORD}{SPACE}	{
2837ce72dbaSJustin T. Gibbs 				char *yptr;
284c5cb3888SJustin T. Gibbs 
2857ce72dbaSJustin T. Gibbs 				/* Strip space and return as a normal symbol */
2867ce72dbaSJustin T. Gibbs 				yptr = yytext;
2877ce72dbaSJustin T. Gibbs 				while (*yptr != ' ' && *yptr != '\t')
2887ce72dbaSJustin T. Gibbs 					yptr++;
2897ce72dbaSJustin T. Gibbs 				*yptr = '\0';
2907ce72dbaSJustin T. Gibbs 				yylval.sym = symtable_get(yytext);
2917ce72dbaSJustin T. Gibbs 				string_buf_ptr = string_buf;
2927ce72dbaSJustin T. Gibbs 				BEGIN MACROBODY;
2937ce72dbaSJustin T. Gibbs 				return T_SYMBOL;
2947ce72dbaSJustin T. Gibbs 			}
2957ce72dbaSJustin T. Gibbs <MACRODEF>{WORD}\(	{
2967ce72dbaSJustin T. Gibbs 				/*
2977ce72dbaSJustin T. Gibbs 				 * We store the symbol with its opening
2987ce72dbaSJustin T. Gibbs 				 * parren so we can differentiate macros
2997ce72dbaSJustin T. Gibbs 				 * that take args from macros with the
3007ce72dbaSJustin T. Gibbs 				 * same name that do not take args as
3017ce72dbaSJustin T. Gibbs 				 * is allowed in C.
3027ce72dbaSJustin T. Gibbs 				 */
3037ce72dbaSJustin T. Gibbs 				BEGIN MACROARGLIST;
3047ce72dbaSJustin T. Gibbs 				yylval.sym = symtable_get(yytext);
3057ce72dbaSJustin T. Gibbs 				unput('(');
3067ce72dbaSJustin T. Gibbs 				return T_SYMBOL;
3077ce72dbaSJustin T. Gibbs 			}
3087ce72dbaSJustin T. Gibbs <MACROARGLIST>{WORD}	{
3097ce72dbaSJustin T. Gibbs 				yylval.str = yytext;
3107ce72dbaSJustin T. Gibbs 				return T_ARG;
3117ce72dbaSJustin T. Gibbs 			}
3127ce72dbaSJustin T. Gibbs <MACROARGLIST>{SPACE}   ;
3137ce72dbaSJustin T. Gibbs <MACROARGLIST>[(,]	{
3147ce72dbaSJustin T. Gibbs 				return yytext[0];
3157ce72dbaSJustin T. Gibbs 			}
3167ce72dbaSJustin T. Gibbs <MACROARGLIST>[)]	{
3177ce72dbaSJustin T. Gibbs 				string_buf_ptr = string_buf;
3187ce72dbaSJustin T. Gibbs 				BEGIN MACROBODY;
3197ce72dbaSJustin T. Gibbs 				return ')';
3207ce72dbaSJustin T. Gibbs 			}
3217ce72dbaSJustin T. Gibbs <MACROARGLIST>.		{
322b18a2ef1SXin LI 				snprintf(msgbuf, sizeof(msgbuf), "Invalid character "
3237ce72dbaSJustin T. Gibbs 					 "'%c' in macro argument list",
3247ce72dbaSJustin T. Gibbs 					 yytext[0]);
325b18a2ef1SXin LI 				stop(msgbuf, EX_DATAERR);
3267ce72dbaSJustin T. Gibbs 			}
3277ce72dbaSJustin T. Gibbs <MACROCALLARGS>{SPACE}  ;
3287ce72dbaSJustin T. Gibbs <MACROCALLARGS>\(	{
3297ce72dbaSJustin T. Gibbs 				parren_count++;
3307ce72dbaSJustin T. Gibbs 				if (parren_count == 1)
3317ce72dbaSJustin T. Gibbs 					return ('(');
3327ce72dbaSJustin T. Gibbs 				*string_buf_ptr++ = '(';
3337ce72dbaSJustin T. Gibbs 			}
3347ce72dbaSJustin T. Gibbs <MACROCALLARGS>\)	{
3357ce72dbaSJustin T. Gibbs 				parren_count--;
3367ce72dbaSJustin T. Gibbs 				if (parren_count == 0) {
3377ce72dbaSJustin T. Gibbs 					BEGIN INITIAL;
3387ce72dbaSJustin T. Gibbs 					return (')');
3397ce72dbaSJustin T. Gibbs 				}
3407ce72dbaSJustin T. Gibbs 				*string_buf_ptr++ = ')';
3417ce72dbaSJustin T. Gibbs 			}
3427ce72dbaSJustin T. Gibbs <MACROCALLARGS>{MCARG}	{
3437ce72dbaSJustin T. Gibbs 				char *yptr;
344c5cb3888SJustin T. Gibbs 
3457ce72dbaSJustin T. Gibbs 				yptr = yytext;
3467ce72dbaSJustin T. Gibbs 				while (*yptr)
3477ce72dbaSJustin T. Gibbs 					*string_buf_ptr++ = *yptr++;
3487ce72dbaSJustin T. Gibbs 			}
3497ce72dbaSJustin T. Gibbs <MACROCALLARGS>\,	{
3507ce72dbaSJustin T. Gibbs 				if (string_buf_ptr != string_buf) {
3517ce72dbaSJustin T. Gibbs 					/*
3527ce72dbaSJustin T. Gibbs 					 * Return an argument and
3537ce72dbaSJustin T. Gibbs 					 * rescan this comma so we
3547ce72dbaSJustin T. Gibbs 					 * can return it as well.
3557ce72dbaSJustin T. Gibbs 					 */
3567ce72dbaSJustin T. Gibbs 					*string_buf_ptr = '\0';
3577ce72dbaSJustin T. Gibbs 					yylval.str = string_buf;
3587ce72dbaSJustin T. Gibbs 					string_buf_ptr = string_buf;
3597ce72dbaSJustin T. Gibbs 					unput(',');
3607ce72dbaSJustin T. Gibbs 					return T_ARG;
3617ce72dbaSJustin T. Gibbs 				}
3627ce72dbaSJustin T. Gibbs 				return ',';
3637ce72dbaSJustin T. Gibbs 			}
3647ce72dbaSJustin T. Gibbs <MACROBODY>\\\n		{
3657ce72dbaSJustin T. Gibbs 				/* Eat escaped newlines. */
3667ce72dbaSJustin T. Gibbs 				++yylineno;
3677ce72dbaSJustin T. Gibbs 			}
368708d2cb0SJustin T. Gibbs <MACROBODY>\r		;
3697ce72dbaSJustin T. Gibbs <MACROBODY>\n		{
3707ce72dbaSJustin T. Gibbs 				/* Macros end on the first unescaped newline. */
3717ce72dbaSJustin T. Gibbs 				BEGIN INITIAL;
3727ce72dbaSJustin T. Gibbs 				*string_buf_ptr = '\0';
3737ce72dbaSJustin T. Gibbs 				yylval.str = string_buf;
3747ce72dbaSJustin T. Gibbs 				++yylineno;
3757ce72dbaSJustin T. Gibbs 				return T_MACROBODY;
3767ce72dbaSJustin T. Gibbs 			}
3777ce72dbaSJustin T. Gibbs <MACROBODY>{MBODY}	{
3787ce72dbaSJustin T. Gibbs 				char *yptr;
379708d2cb0SJustin T. Gibbs 				char c;
3807ce72dbaSJustin T. Gibbs 
3817ce72dbaSJustin T. Gibbs 				yptr = yytext;
382b18a2ef1SXin LI 				while ((c = *yptr++)) {
383708d2cb0SJustin T. Gibbs 					/*
384708d2cb0SJustin T. Gibbs 					 * Strip carriage returns.
385708d2cb0SJustin T. Gibbs 					 */
386708d2cb0SJustin T. Gibbs 					if (c == '\r')
387708d2cb0SJustin T. Gibbs 						continue;
388708d2cb0SJustin T. Gibbs 					*string_buf_ptr++ = c;
389708d2cb0SJustin T. Gibbs 				}
3907ce72dbaSJustin T. Gibbs 			}
3917ce72dbaSJustin T. Gibbs {WORD}\(		{
3927ce72dbaSJustin T. Gibbs 				char *yptr;
3937ce72dbaSJustin T. Gibbs 				char *ycopy;
3947ce72dbaSJustin T. Gibbs 
3957ce72dbaSJustin T. Gibbs 				/* May be a symbol or a macro invocation. */
3967ce72dbaSJustin T. Gibbs 				yylval.sym = symtable_get(yytext);
3977ce72dbaSJustin T. Gibbs 				if (yylval.sym->type == MACRO) {
3987ce72dbaSJustin T. Gibbs 					YY_BUFFER_STATE old_state;
3997ce72dbaSJustin T. Gibbs 					YY_BUFFER_STATE temp_state;
4007ce72dbaSJustin T. Gibbs 
4017ce72dbaSJustin T. Gibbs 					ycopy = strdup(yytext);
4027ce72dbaSJustin T. Gibbs 					yptr = ycopy + yyleng;
4037ce72dbaSJustin T. Gibbs 					while (yptr > ycopy)
4047ce72dbaSJustin T. Gibbs 						unput(*--yptr);
4057ce72dbaSJustin T. Gibbs 					old_state = YY_CURRENT_BUFFER;
4067ce72dbaSJustin T. Gibbs 					temp_state =
4077ce72dbaSJustin T. Gibbs 					    yy_create_buffer(stdin,
4087ce72dbaSJustin T. Gibbs 							     YY_BUF_SIZE);
4097ce72dbaSJustin T. Gibbs 					yy_switch_to_buffer(temp_state);
4107ce72dbaSJustin T. Gibbs 					mm_switch_to_buffer(old_state);
4117ce72dbaSJustin T. Gibbs 					mmparse();
4127ce72dbaSJustin T. Gibbs 					mm_switch_to_buffer(temp_state);
4137ce72dbaSJustin T. Gibbs 					yy_switch_to_buffer(old_state);
4147ce72dbaSJustin T. Gibbs 					mm_delete_buffer(temp_state);
4157ce72dbaSJustin T. Gibbs 					expand_macro(yylval.sym);
4167ce72dbaSJustin T. Gibbs 				} else {
4177ce72dbaSJustin T. Gibbs 					if (yylval.sym->type == UNINITIALIZED) {
4187ce72dbaSJustin T. Gibbs 						/* Try without the '(' */
4197ce72dbaSJustin T. Gibbs 						symbol_delete(yylval.sym);
4207ce72dbaSJustin T. Gibbs 						yytext[yyleng-1] = '\0';
4217ce72dbaSJustin T. Gibbs 						yylval.sym =
4227ce72dbaSJustin T. Gibbs 						    symtable_get(yytext);
4237ce72dbaSJustin T. Gibbs 					}
4247ce72dbaSJustin T. Gibbs 					unput('(');
4257ce72dbaSJustin T. Gibbs 					return T_SYMBOL;
4267ce72dbaSJustin T. Gibbs 				}
4277ce72dbaSJustin T. Gibbs 			}
4287ce72dbaSJustin T. Gibbs {WORD}			{
4297ce72dbaSJustin T. Gibbs 				yylval.sym = symtable_get(yytext);
4307ce72dbaSJustin T. Gibbs 				if (yylval.sym->type == MACRO) {
4317ce72dbaSJustin T. Gibbs 					expand_macro(yylval.sym);
4327ce72dbaSJustin T. Gibbs 				} else {
4337ce72dbaSJustin T. Gibbs 					return T_SYMBOL;
4347ce72dbaSJustin T. Gibbs 				}
4357ce72dbaSJustin T. Gibbs 			}
436c5cb3888SJustin T. Gibbs .			{
437b18a2ef1SXin LI 				snprintf(msgbuf, sizeof(msgbuf), "Invalid character "
438c5cb3888SJustin T. Gibbs 					 "'%c'", yytext[0]);
439b18a2ef1SXin LI 				stop(msgbuf, EX_DATAERR);
440c5cb3888SJustin T. Gibbs 			}
441c5cb3888SJustin T. Gibbs %%
442c5cb3888SJustin T. Gibbs 
443c5cb3888SJustin T. Gibbs typedef struct include {
444c5cb3888SJustin T. Gibbs         YY_BUFFER_STATE  buffer;
445c5cb3888SJustin T. Gibbs         int              lineno;
446c5cb3888SJustin T. Gibbs         char            *filename;
447e3975643SJake Burkholder 	SLIST_ENTRY(include) links;
448c5cb3888SJustin T. Gibbs }include_t;
449c5cb3888SJustin T. Gibbs 
450e3975643SJake Burkholder SLIST_HEAD(, include) include_stack;
451c5cb3888SJustin T. Gibbs 
452c5cb3888SJustin T. Gibbs void
45332da3127SJustin T. Gibbs include_file(char *file_name, include_type type)
454c5cb3888SJustin T. Gibbs {
455c5cb3888SJustin T. Gibbs 	FILE *newfile;
456c5cb3888SJustin T. Gibbs 	include_t *include;
457c5cb3888SJustin T. Gibbs 
458c5cb3888SJustin T. Gibbs 	newfile = NULL;
459c5cb3888SJustin T. Gibbs 	/* Try the current directory first */
460c5cb3888SJustin T. Gibbs 	if (includes_search_curdir != 0 || type == SOURCE_FILE)
461c5cb3888SJustin T. Gibbs 		newfile = fopen(file_name, "r");
462c5cb3888SJustin T. Gibbs 
463c5cb3888SJustin T. Gibbs 	if (newfile == NULL && type != SOURCE_FILE) {
464c5cb3888SJustin T. Gibbs                 path_entry_t include_dir;
465c5cb3888SJustin T. Gibbs                 for (include_dir = search_path.slh_first;
466c5cb3888SJustin T. Gibbs                      include_dir != NULL;
467c5cb3888SJustin T. Gibbs                      include_dir = include_dir->links.sle_next) {
468c5cb3888SJustin T. Gibbs 			char fullname[PATH_MAX];
469c5cb3888SJustin T. Gibbs 
470c5cb3888SJustin T. Gibbs 			if ((include_dir->quoted_includes_only == TRUE)
471c5cb3888SJustin T. Gibbs 			 && (type != QUOTED_INCLUDE))
472c5cb3888SJustin T. Gibbs 				continue;
473c5cb3888SJustin T. Gibbs 
474c5cb3888SJustin T. Gibbs 			snprintf(fullname, sizeof(fullname),
475c5cb3888SJustin T. Gibbs 				 "%s/%s", include_dir->directory, file_name);
476c5cb3888SJustin T. Gibbs 
477c5cb3888SJustin T. Gibbs 			if ((newfile = fopen(fullname, "r")) != NULL)
478c5cb3888SJustin T. Gibbs 				break;
479c5cb3888SJustin T. Gibbs                 }
480c5cb3888SJustin T. Gibbs         }
481c5cb3888SJustin T. Gibbs 
482c5cb3888SJustin T. Gibbs 	if (newfile == NULL) {
483c5cb3888SJustin T. Gibbs 		perror(file_name);
484c5cb3888SJustin T. Gibbs 		stop("Unable to open input file", EX_SOFTWARE);
485c5cb3888SJustin T. Gibbs 		/* NOTREACHED */
486c5cb3888SJustin T. Gibbs 	}
487f68f348bSJustin T. Gibbs 
488f68f348bSJustin T. Gibbs 	if (type != SOURCE_FILE) {
489c5cb3888SJustin T. Gibbs 		include = (include_t *)malloc(sizeof(include_t));
490c5cb3888SJustin T. Gibbs 		if (include == NULL) {
491f68f348bSJustin T. Gibbs 			stop("Unable to allocate include stack entry",
492f68f348bSJustin T. Gibbs 			     EX_SOFTWARE);
493c5cb3888SJustin T. Gibbs 			/* NOTREACHED */
494c5cb3888SJustin T. Gibbs 		}
495c5cb3888SJustin T. Gibbs 		include->buffer = YY_CURRENT_BUFFER;
496c5cb3888SJustin T. Gibbs 		include->lineno = yylineno;
497c5cb3888SJustin T. Gibbs 		include->filename = yyfilename;
498c5cb3888SJustin T. Gibbs 		SLIST_INSERT_HEAD(&include_stack, include, links);
499f68f348bSJustin T. Gibbs 	}
500c5cb3888SJustin T. Gibbs 	yy_switch_to_buffer(yy_create_buffer(newfile, YY_BUF_SIZE));
501c5cb3888SJustin T. Gibbs 	yylineno = 1;
502c5cb3888SJustin T. Gibbs 	yyfilename = strdup(file_name);
503c5cb3888SJustin T. Gibbs }
504c5cb3888SJustin T. Gibbs 
5057ce72dbaSJustin T. Gibbs static void next_substitution(struct symbol *mac_symbol, const char *body_pos,
5067ce72dbaSJustin T. Gibbs 			      const char **next_match,
5077ce72dbaSJustin T. Gibbs 			      struct macro_arg **match_marg, regmatch_t *match);
5087ce72dbaSJustin T. Gibbs 
5097ce72dbaSJustin T. Gibbs void
5107ce72dbaSJustin T. Gibbs expand_macro(struct symbol *macro_symbol)
5117ce72dbaSJustin T. Gibbs {
5127ce72dbaSJustin T. Gibbs 	struct macro_arg *marg;
5137ce72dbaSJustin T. Gibbs 	struct macro_arg *match_marg;
5147ce72dbaSJustin T. Gibbs 	const char *body_head;
5157ce72dbaSJustin T. Gibbs 	const char *body_pos;
5167ce72dbaSJustin T. Gibbs 	const char *next_match;
5175bb0de05SXin LI 	regmatch_t match = { .rm_so = 0, .rm_eo = 0 };
5187ce72dbaSJustin T. Gibbs 
5197ce72dbaSJustin T. Gibbs 	/*
5207ce72dbaSJustin T. Gibbs 	 * Due to the nature of unput, we must work
5217ce72dbaSJustin T. Gibbs 	 * backwards through the macro body performing
5227ce72dbaSJustin T. Gibbs 	 * any expansions.
5237ce72dbaSJustin T. Gibbs 	 */
5247ce72dbaSJustin T. Gibbs 	body_head = macro_symbol->info.macroinfo->body;
5257ce72dbaSJustin T. Gibbs 	body_pos = body_head + strlen(body_head);
5267ce72dbaSJustin T. Gibbs 	while (body_pos > body_head) {
5277ce72dbaSJustin T. Gibbs 		next_match = body_head;
5287ce72dbaSJustin T. Gibbs 		match_marg = NULL;
5297ce72dbaSJustin T. Gibbs 		next_substitution(macro_symbol, body_pos, &next_match,
5307ce72dbaSJustin T. Gibbs 				  &match_marg, &match);
5317ce72dbaSJustin T. Gibbs 
5327ce72dbaSJustin T. Gibbs 		/* Put back everything up until the replacement. */
5337ce72dbaSJustin T. Gibbs 		while (body_pos > next_match)
5347ce72dbaSJustin T. Gibbs 			unput(*--body_pos);
5357ce72dbaSJustin T. Gibbs 
5367ce72dbaSJustin T. Gibbs 		/* Perform the replacement. */
5377ce72dbaSJustin T. Gibbs 		if (match_marg != NULL) {
5387ce72dbaSJustin T. Gibbs 			const char *strp;
5397ce72dbaSJustin T. Gibbs 
5407ce72dbaSJustin T. Gibbs 			next_match = match_marg->replacement_text;
5417ce72dbaSJustin T. Gibbs 			strp = next_match + strlen(next_match);
5427ce72dbaSJustin T. Gibbs 			while (strp > next_match)
5437ce72dbaSJustin T. Gibbs 				unput(*--strp);
5447ce72dbaSJustin T. Gibbs 
5457ce72dbaSJustin T. Gibbs 			/* Skip past the unexpanded macro arg. */
5467ce72dbaSJustin T. Gibbs 			body_pos -= match.rm_eo - match.rm_so;
5477ce72dbaSJustin T. Gibbs 		}
5487ce72dbaSJustin T. Gibbs 	}
5497ce72dbaSJustin T. Gibbs 
5507ce72dbaSJustin T. Gibbs 	/* Cleanup replacement text. */
5517ce72dbaSJustin T. Gibbs 	STAILQ_FOREACH(marg, &macro_symbol->info.macroinfo->args, links) {
5527ce72dbaSJustin T. Gibbs 		free(marg->replacement_text);
5537ce72dbaSJustin T. Gibbs 	}
5547ce72dbaSJustin T. Gibbs }
5557ce72dbaSJustin T. Gibbs 
5567ce72dbaSJustin T. Gibbs /*
5577ce72dbaSJustin T. Gibbs  * Find the next substitution in the macro working backwards from
5587ce72dbaSJustin T. Gibbs  * body_pos until the beginning of the macro buffer.  next_match
5597ce72dbaSJustin T. Gibbs  * should be initialized to the beginning of the macro buffer prior
5607ce72dbaSJustin T. Gibbs  * to calling this routine.
5617ce72dbaSJustin T. Gibbs  */
5627ce72dbaSJustin T. Gibbs static void
5637ce72dbaSJustin T. Gibbs next_substitution(struct symbol *mac_symbol, const char *body_pos,
5647ce72dbaSJustin T. Gibbs 		  const char **next_match, struct macro_arg **match_marg,
5657ce72dbaSJustin T. Gibbs 		  regmatch_t *match)
5667ce72dbaSJustin T. Gibbs {
5677ce72dbaSJustin T. Gibbs 	regmatch_t	  matches[2];
5687ce72dbaSJustin T. Gibbs 	struct macro_arg *marg;
5697ce72dbaSJustin T. Gibbs 	const char	 *search_pos;
5707ce72dbaSJustin T. Gibbs 	int		  retval;
5717ce72dbaSJustin T. Gibbs 
5727ce72dbaSJustin T. Gibbs 	do {
5737ce72dbaSJustin T. Gibbs 		search_pos = *next_match;
5747ce72dbaSJustin T. Gibbs 
5757ce72dbaSJustin T. Gibbs 		STAILQ_FOREACH(marg, &mac_symbol->info.macroinfo->args, links) {
5767ce72dbaSJustin T. Gibbs 
5777ce72dbaSJustin T. Gibbs 			retval = regexec(&marg->arg_regex, search_pos, 2,
5787ce72dbaSJustin T. Gibbs 					 matches, 0);
5797ce72dbaSJustin T. Gibbs 			if (retval == 0
5807ce72dbaSJustin T. Gibbs 			 && (matches[1].rm_eo + search_pos) <= body_pos
5817ce72dbaSJustin T. Gibbs 			 && (matches[1].rm_eo + search_pos) > *next_match) {
5827ce72dbaSJustin T. Gibbs 				*match = matches[1];
5837ce72dbaSJustin T. Gibbs 				*next_match = match->rm_eo + search_pos;
5847ce72dbaSJustin T. Gibbs 				*match_marg = marg;
5857ce72dbaSJustin T. Gibbs 			}
5867ce72dbaSJustin T. Gibbs 		}
5877ce72dbaSJustin T. Gibbs 	} while (search_pos != *next_match);
5887ce72dbaSJustin T. Gibbs }
5897ce72dbaSJustin T. Gibbs 
590c5cb3888SJustin T. Gibbs int
59173c4bad0SEd Schouten yywrap(void)
592c5cb3888SJustin T. Gibbs {
593c5cb3888SJustin T. Gibbs 	include_t *include;
594c5cb3888SJustin T. Gibbs 
595c5cb3888SJustin T. Gibbs 	yy_delete_buffer(YY_CURRENT_BUFFER);
596c5cb3888SJustin T. Gibbs 	(void)fclose(yyin);
597c5cb3888SJustin T. Gibbs 	if (yyfilename != NULL)
598c5cb3888SJustin T. Gibbs 		free(yyfilename);
599f68f348bSJustin T. Gibbs 	yyfilename = NULL;
600c5cb3888SJustin T. Gibbs 	include = include_stack.slh_first;
601c5cb3888SJustin T. Gibbs 	if (include != NULL) {
602c5cb3888SJustin T. Gibbs 		yy_switch_to_buffer(include->buffer);
603c5cb3888SJustin T. Gibbs 		yylineno = include->lineno;
604c5cb3888SJustin T. Gibbs 		yyfilename = include->filename;
605c5cb3888SJustin T. Gibbs 		SLIST_REMOVE_HEAD(&include_stack, links);
606c5cb3888SJustin T. Gibbs 		free(include);
607c5cb3888SJustin T. Gibbs 		return (0);
608c5cb3888SJustin T. Gibbs 	}
609c5cb3888SJustin T. Gibbs 	return (1);
610c5cb3888SJustin T. Gibbs }
611