123925Sgibbs%{
2139749Simp/*-
323925Sgibbs * Lexical Analyzer for the Aic7xxx SCSI Host adapter sequencer assembler.
423925Sgibbs *
595376Sgibbs * Copyright (c) 1997, 1998, 2000 Justin T. Gibbs.
6102668Sgibbs * Copyright (c) 2001, 2002 Adaptec Inc.
723925Sgibbs * All rights reserved.
823925Sgibbs *
923925Sgibbs * Redistribution and use in source and binary forms, with or without
1023925Sgibbs * modification, are permitted provided that the following conditions
1123925Sgibbs * are met:
1223925Sgibbs * 1. Redistributions of source code must retain the above copyright
1326997Sgibbs *    notice, this list of conditions, and the following disclaimer,
1454211Sgibbs *    without modification.
1595376Sgibbs * 2. Redistributions in binary form must reproduce at minimum a disclaimer
1695376Sgibbs *    substantially similar to the "NO WARRANTY" disclaimer below
1795376Sgibbs *    ("Disclaimer") and any redistribution must be conditioned upon
1895376Sgibbs *    including a substantially similar Disclaimer requirement for further
1995376Sgibbs *    binary redistribution.
2095376Sgibbs * 3. Neither the names of the above-listed copyright holders nor the names
2195376Sgibbs *    of any contributors may be used to endorse or promote products derived
2295376Sgibbs *    from this software without specific prior written permission.
2323925Sgibbs *
2463457Sgibbs * Alternatively, this software may be distributed under the terms of the
2595376Sgibbs * GNU General Public License ("GPL") version 2 as published by the Free
2695376Sgibbs * Software Foundation.
2763457Sgibbs *
2895376Sgibbs * NO WARRANTY
2995376Sgibbs * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3095376Sgibbs * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3195376Sgibbs * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
3295376Sgibbs * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3395376Sgibbs * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3423925Sgibbs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3523925Sgibbs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3695376Sgibbs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
3795376Sgibbs * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
3895376Sgibbs * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3995376Sgibbs * POSSIBILITY OF SUCH DAMAGES.
4023925Sgibbs *
41123577Sgibbs * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_scan.l#19 $
4265943Sgibbs *
4350477Speter * $FreeBSD$
4423925Sgibbs */
4523925Sgibbs
4623942Sbde#include <sys/types.h>
4723942Sbde
48104028Sgibbs#include <inttypes.h>
4923925Sgibbs#include <limits.h>
5095376Sgibbs#include <regex.h>
5123925Sgibbs#include <stdio.h>
5223925Sgibbs#include <string.h>
5323925Sgibbs#include <sysexits.h>
5423925Sgibbs#include <sys/queue.h>
5523925Sgibbs
5629050Sgibbs#include "aicasm.h"
5729050Sgibbs#include "aicasm_symbol.h"
5895376Sgibbs#include "aicasm_gram.h"
5939220Sgibbs
6095376Sgibbs/* This is used for macro body capture too, so err on the large size. */
6195376Sgibbs#define MAX_STR_CONST 4096
6295376Sgibbsstatic char string_buf[MAX_STR_CONST];
6395376Sgibbsstatic char *string_buf_ptr;
6495376Sgibbsstatic int  parren_count;
6595376Sgibbsstatic int  quote_count;
66193244Sdelphijstatic char msgbuf[255];
67193244Sdelphij
68193244Sdelphijextern int yylex(void);
69193244Sdelphijextern int mmlex(void);
70193244Sdelphijextern int mmparse(void);
71193244Sdelphijextern void mm_switch_to_buffer(YY_BUFFER_STATE);
72193244Sdelphijextern void mm_delete_buffer(YY_BUFFER_STATE);
7323925Sgibbs%}
7423925Sgibbs
75229101Sdim%option noinput
76229101Sdim
7795376SgibbsPATH		([/]*[-A-Za-z0-9_.])+
7823925SgibbsWORD		[A-Za-z_][-A-Za-z_0-9]*
7923925SgibbsSPACE		[ \t]+
8095376SgibbsMCARG		[^(), \t]+
8195376SgibbsMBODY		((\\[^\n])*[^\n\\]*)+
8223925Sgibbs
8323925Sgibbs%x COMMENT
8439220Sgibbs%x CEXPR
8539220Sgibbs%x INCLUDE
8679873Sgibbs%x STRING
8795376Sgibbs%x MACRODEF
8895376Sgibbs%x MACROARGLIST
8995376Sgibbs%x MACROCALLARGS
9095376Sgibbs%x MACROBODY
9123925Sgibbs
9223925Sgibbs%%
9323925Sgibbs\n			{ ++yylineno; }
94123577Sgibbs\r			;
9523925Sgibbs"/*"			{ BEGIN COMMENT;  /* Enter comment eating state */ }
9623925Sgibbs<COMMENT>"/*"		{ fprintf(stderr, "Warning! Comment within comment."); }
9723925Sgibbs<COMMENT>\n		{ ++yylineno; }
9823925Sgibbs<COMMENT>[^*/\n]*	;
9923925Sgibbs<COMMENT>"*"+[^*/\n]*	;
10023925Sgibbs<COMMENT>"/"+[^*/\n]*	;
10123925Sgibbs<COMMENT>"*"+"/"	{ BEGIN INITIAL; }
10239220Sgibbsif[ \t]*\(		{
10339220Sgibbs				string_buf_ptr = string_buf;
10439220Sgibbs				parren_count = 1;
10539220Sgibbs				BEGIN CEXPR;
10639220Sgibbs				return T_IF;
10739220Sgibbs			}
10839220Sgibbs<CEXPR>\(		{	*string_buf_ptr++ = '('; parren_count++; }
10939220Sgibbs<CEXPR>\)		{
11039220Sgibbs				parren_count--;
11139220Sgibbs				if (parren_count == 0) {
11239220Sgibbs					/* All done */
11339220Sgibbs					BEGIN INITIAL;
11439220Sgibbs					*string_buf_ptr = '\0';
11539220Sgibbs					yylval.sym = symtable_get(string_buf);
11639220Sgibbs					return T_CEXPR;
11739220Sgibbs				} else {
11839220Sgibbs					*string_buf_ptr++ = ')';
11939220Sgibbs				}
12039220Sgibbs			}
12139220Sgibbs<CEXPR>\n		{ ++yylineno; }
122123577Sgibbs<CEXPR>\r		;
12365943Sgibbs<CEXPR>[^()\n]+	{
12479873Sgibbs				char *yptr;
12523925Sgibbs
12679873Sgibbs				yptr = yytext;
12765943Sgibbs				while (*yptr != '\0') {
12865943Sgibbs					/* Remove duplicate spaces */
12965943Sgibbs					if (*yptr == '\t')
13065943Sgibbs						*yptr = ' ';
13165943Sgibbs					if (*yptr == ' '
13265943Sgibbs					 && string_buf_ptr != string_buf
13365943Sgibbs					 && string_buf_ptr[-1] == ' ')
13465943Sgibbs						yptr++;
13565943Sgibbs					else
13665943Sgibbs						*string_buf_ptr++ = *yptr++;
13765943Sgibbs				}
13839220Sgibbs			}
13939220Sgibbs
14079873SgibbsVERSION			{ return T_VERSION; }
141102668SgibbsPREFIX			{ return T_PREFIX; }
14295376SgibbsPATCH_ARG_LIST		{ return T_PATCH_ARG_LIST; }
14379873Sgibbs\"			{
14479873Sgibbs				string_buf_ptr = string_buf;
14579873Sgibbs				BEGIN STRING;
14679873Sgibbs			}
14779873Sgibbs<STRING>[^"]+		{
14879873Sgibbs				char *yptr;
14979873Sgibbs
15079873Sgibbs				yptr = yytext;
15179873Sgibbs				while (*yptr)
15279873Sgibbs					*string_buf_ptr++ = *yptr++;
15379873Sgibbs			}
15479873Sgibbs<STRING>\"		{
15579873Sgibbs				/* All done */
15679873Sgibbs				BEGIN INITIAL;
15779873Sgibbs				*string_buf_ptr = '\0';
15879873Sgibbs				yylval.str = string_buf;
15979873Sgibbs				return T_STRING;
16079873Sgibbs			}
16195376Sgibbs{SPACE}			 ;
16223925Sgibbs
16323925Sgibbs	/* Register/SCB/SRAM definition keywords */
16495376Sgibbsexport			{ return T_EXPORT; }
16523925Sgibbsregister		{ return T_REGISTER; }
16623925Sgibbsconst			{ yylval.value = FALSE; return T_CONST; }
16729897Sgibbsdownload		{ return T_DOWNLOAD; }
16823925Sgibbsaddress			{ return T_ADDRESS; }
16923925Sgibbsaccess_mode		{ return T_ACCESS_MODE; }
17095376Sgibbsmodes			{ return T_MODES; }
17123925SgibbsRW|RO|WO		{
17223925Sgibbs				 if (strcmp(yytext, "RW") == 0)
17323925Sgibbs					yylval.value = RW;
17423925Sgibbs				 else if (strcmp(yytext, "RO") == 0)
17523925Sgibbs					yylval.value = RO;
17623925Sgibbs				 else
17723925Sgibbs					yylval.value = WO;
17823925Sgibbs				 return T_MODE;
17923925Sgibbs			}
18066270SgibbsBEGIN_CRITICAL		{ return T_BEGIN_CS; }
18166270SgibbsEND_CRITICAL		{ return T_END_CS; }
18295376SgibbsSET_SRC_MODE		{ return T_SET_SRC_MODE; }
18395376SgibbsSET_DST_MODE		{ return T_SET_DST_MODE; }
184102668Sgibbsfield			{ return T_FIELD; }
185102668Sgibbsenum			{ return T_ENUM; }
18623925Sgibbsmask			{ return T_MASK; }
18723925Sgibbsalias			{ return T_ALIAS; }
18823925Sgibbssize			{ return T_SIZE; }
18923925Sgibbsscb			{ return T_SCB; }
19023925Sgibbsscratch_ram		{ return T_SRAM; }
19123925Sgibbsaccumulator		{ return T_ACCUM; }
19295376Sgibbsmode_pointer		{ return T_MODE_PTR; }
19323925Sgibbsallones			{ return T_ALLONES; }
19423925Sgibbsallzeros		{ return T_ALLZEROS; }
19523925Sgibbsnone			{ return T_NONE; }
19623925Sgibbssindex			{ return T_SINDEX; }
19723925SgibbsA			{ return T_A; }
19823925Sgibbs
19923925Sgibbs	/* Opcodes */
20023925Sgibbsshl			{ return T_SHL; }
20123925Sgibbsshr			{ return T_SHR; }
20223925Sgibbsror			{ return T_ROR; }
20323925Sgibbsrol			{ return T_ROL; }
20423925Sgibbsmvi			{ return T_MVI; }
20523925Sgibbsmov			{ return T_MOV; }
20623925Sgibbsclr			{ return T_CLR; }
20723925Sgibbsjmp			{ return T_JMP; }
20823925Sgibbsjc			{ return T_JC;	}
20923925Sgibbsjnc			{ return T_JNC;	}
21023925Sgibbsje			{ return T_JE;	}
21123925Sgibbsjne			{ return T_JNE;	}
21223925Sgibbsjz			{ return T_JZ;	}
21323925Sgibbsjnz			{ return T_JNZ;	}
21423925Sgibbscall			{ return T_CALL; }
21523925Sgibbsadd			{ return T_ADD; }
21623925Sgibbsadc			{ return T_ADC; }
21739220Sgibbsbmov			{ return T_BMOV; }
21823925Sgibbsinc			{ return T_INC; }
21923925Sgibbsdec			{ return T_DEC; }
22023925Sgibbsstc			{ return T_STC;	}
22123925Sgibbsclc			{ return T_CLC; }
22223925Sgibbscmp			{ return T_CMP;	}
22363457Sgibbsnot			{ return T_NOT;	}
22423925Sgibbsxor			{ return T_XOR;	}
22523925Sgibbstest			{ return T_TEST;}
22623925Sgibbsand			{ return T_AND;	}
22723925Sgibbsor			{ return T_OR;	}
22823925Sgibbsret			{ return T_RET; }
22923925Sgibbsnop			{ return T_NOP; }
23039220Sgibbselse			{ return T_ELSE; }
23123925Sgibbs
23223925Sgibbs	/* Allowed Symbols */
23395376Sgibbs\<\<			{ return T_EXPR_LSHIFT; }
23495376Sgibbs\>\>			{ return T_EXPR_RSHIFT; }
23595376Sgibbs[-+,:()~|&."{};<>[\]/*!=] { return yytext[0]; }
23623925Sgibbs
23723925Sgibbs	/* Number processing */
23823925Sgibbs0[0-7]*			{
23923925Sgibbs				yylval.value = strtol(yytext, NULL, 8);
24023925Sgibbs				return T_NUMBER;
24123925Sgibbs			}
24223925Sgibbs
24323925Sgibbs0[xX][0-9a-fA-F]+	{
24423925Sgibbs				yylval.value = strtoul(yytext + 2, NULL, 16);
24523925Sgibbs				return T_NUMBER;
24623925Sgibbs			}
24723925Sgibbs
24823925Sgibbs[1-9][0-9]*		{
24923925Sgibbs				yylval.value = strtol(yytext, NULL, 10);
25023925Sgibbs				return T_NUMBER;
25123925Sgibbs			}
25223925Sgibbs	/* Include Files */
25379873Sgibbs#include{SPACE}		{
25479873Sgibbs				BEGIN INCLUDE;
25579873Sgibbs				quote_count = 0;
25679873Sgibbs				return T_INCLUDE;
25779873Sgibbs			}
25879873Sgibbs<INCLUDE>[<]		{ return yytext[0]; }
25979873Sgibbs<INCLUDE>[>]		{ BEGIN INITIAL; return yytext[0]; }
26079873Sgibbs<INCLUDE>[\"]		{
26179873Sgibbs				if (quote_count != 0)
26279873Sgibbs					BEGIN INITIAL;
26379873Sgibbs				quote_count++;
26479873Sgibbs				return yytext[0];
26579873Sgibbs			}
26695376Sgibbs<INCLUDE>{PATH}		{
26779873Sgibbs				char *yptr;
26823925Sgibbs
26979873Sgibbs				yptr = yytext;
27079873Sgibbs				string_buf_ptr = string_buf;
27179873Sgibbs				while (*yptr)
27279873Sgibbs					*string_buf_ptr++ = *yptr++;
27379873Sgibbs				yylval.str = string_buf;
27479873Sgibbs				*string_buf_ptr = '\0';
27579873Sgibbs				return T_PATH;
27679873Sgibbs			}
27795376Sgibbs<INCLUDE>.		{ stop("Invalid include line", EX_DATAERR); }
27895376Sgibbs#define{SPACE}		{
27995376Sgibbs				BEGIN MACRODEF;
28095376Sgibbs				return T_DEFINE;
28195376Sgibbs			}
28295376Sgibbs<MACRODEF>{WORD}{SPACE}	{
28395376Sgibbs				char *yptr;
28479873Sgibbs
28595376Sgibbs				/* Strip space and return as a normal symbol */
28695376Sgibbs				yptr = yytext;
28795376Sgibbs				while (*yptr != ' ' && *yptr != '\t')
28895376Sgibbs					yptr++;
28995376Sgibbs				*yptr = '\0';
29095376Sgibbs				yylval.sym = symtable_get(yytext);
29195376Sgibbs				string_buf_ptr = string_buf;
29295376Sgibbs				BEGIN MACROBODY;
29395376Sgibbs				return T_SYMBOL;
29495376Sgibbs			}
29595376Sgibbs<MACRODEF>{WORD}\(	{
29695376Sgibbs				/*
29795376Sgibbs				 * We store the symbol with its opening
29895376Sgibbs				 * parren so we can differentiate macros
29995376Sgibbs				 * that take args from macros with the
30095376Sgibbs				 * same name that do not take args as
30195376Sgibbs				 * is allowed in C.
30295376Sgibbs				 */
30395376Sgibbs				BEGIN MACROARGLIST;
30495376Sgibbs				yylval.sym = symtable_get(yytext);
30595376Sgibbs				unput('(');
30695376Sgibbs				return T_SYMBOL;
30795376Sgibbs			}
30895376Sgibbs<MACROARGLIST>{WORD}	{
30995376Sgibbs				yylval.str = yytext;
31095376Sgibbs				return T_ARG;
31195376Sgibbs			}
31295376Sgibbs<MACROARGLIST>{SPACE}   ;
31395376Sgibbs<MACROARGLIST>[(,]	{
31495376Sgibbs				return yytext[0];
31595376Sgibbs			}
31695376Sgibbs<MACROARGLIST>[)]	{
31795376Sgibbs				string_buf_ptr = string_buf;
31895376Sgibbs				BEGIN MACROBODY;
31995376Sgibbs				return ')';
32095376Sgibbs			}
32195376Sgibbs<MACROARGLIST>.		{
322193244Sdelphij				snprintf(msgbuf, sizeof(msgbuf), "Invalid character "
32395376Sgibbs					 "'%c' in macro argument list",
32495376Sgibbs					 yytext[0]);
325193244Sdelphij				stop(msgbuf, EX_DATAERR);
32695376Sgibbs			}
32795376Sgibbs<MACROCALLARGS>{SPACE}  ;
32895376Sgibbs<MACROCALLARGS>\(	{
32995376Sgibbs				parren_count++;
33095376Sgibbs				if (parren_count == 1)
33195376Sgibbs					return ('(');
33295376Sgibbs				*string_buf_ptr++ = '(';
33395376Sgibbs			}
33495376Sgibbs<MACROCALLARGS>\)	{
33595376Sgibbs				parren_count--;
33695376Sgibbs				if (parren_count == 0) {
33795376Sgibbs					BEGIN INITIAL;
33895376Sgibbs					return (')');
33995376Sgibbs				}
34095376Sgibbs				*string_buf_ptr++ = ')';
34195376Sgibbs			}
34295376Sgibbs<MACROCALLARGS>{MCARG}	{
34395376Sgibbs				char *yptr;
34423925Sgibbs
34595376Sgibbs				yptr = yytext;
34695376Sgibbs				while (*yptr)
34795376Sgibbs					*string_buf_ptr++ = *yptr++;
34895376Sgibbs			}
34995376Sgibbs<MACROCALLARGS>\,	{
35095376Sgibbs				if (string_buf_ptr != string_buf) {
35195376Sgibbs					/*
35295376Sgibbs					 * Return an argument and
35395376Sgibbs					 * rescan this comma so we
35495376Sgibbs					 * can return it as well.
35595376Sgibbs					 */
35695376Sgibbs					*string_buf_ptr = '\0';
35795376Sgibbs					yylval.str = string_buf;
35895376Sgibbs					string_buf_ptr = string_buf;
35995376Sgibbs					unput(',');
36095376Sgibbs					return T_ARG;
36195376Sgibbs				}
36295376Sgibbs				return ',';
36395376Sgibbs			}
36495376Sgibbs<MACROBODY>\\\n		{
36595376Sgibbs				/* Eat escaped newlines. */
36695376Sgibbs				++yylineno;
36795376Sgibbs			}
368123577Sgibbs<MACROBODY>\r		;
36995376Sgibbs<MACROBODY>\n		{
37095376Sgibbs				/* Macros end on the first unescaped newline. */
37195376Sgibbs				BEGIN INITIAL;
37295376Sgibbs				*string_buf_ptr = '\0';
37395376Sgibbs				yylval.str = string_buf;
37495376Sgibbs				++yylineno;
37595376Sgibbs				return T_MACROBODY;
37695376Sgibbs			}
37795376Sgibbs<MACROBODY>{MBODY}	{
37895376Sgibbs				char *yptr;
379123577Sgibbs				char c;
38095376Sgibbs
38195376Sgibbs				yptr = yytext;
382193244Sdelphij				while ((c = *yptr++)) {
383123577Sgibbs					/*
384123577Sgibbs					 * Strip carriage returns.
385123577Sgibbs					 */
386123577Sgibbs					if (c == '\r')
387123577Sgibbs						continue;
388123577Sgibbs					*string_buf_ptr++ = c;
389123577Sgibbs				}
39095376Sgibbs			}
39195376Sgibbs{WORD}\(		{
39295376Sgibbs				char *yptr;
39395376Sgibbs				char *ycopy;
39495376Sgibbs
39595376Sgibbs				/* May be a symbol or a macro invocation. */
39695376Sgibbs				yylval.sym = symtable_get(yytext);
39795376Sgibbs				if (yylval.sym->type == MACRO) {
39895376Sgibbs					YY_BUFFER_STATE old_state;
39995376Sgibbs					YY_BUFFER_STATE temp_state;
40095376Sgibbs
40195376Sgibbs					ycopy = strdup(yytext);
40295376Sgibbs					yptr = ycopy + yyleng;
40395376Sgibbs					while (yptr > ycopy)
40495376Sgibbs						unput(*--yptr);
40595376Sgibbs					old_state = YY_CURRENT_BUFFER;
40695376Sgibbs					temp_state =
40795376Sgibbs					    yy_create_buffer(stdin,
40895376Sgibbs							     YY_BUF_SIZE);
40995376Sgibbs					yy_switch_to_buffer(temp_state);
41095376Sgibbs					mm_switch_to_buffer(old_state);
41195376Sgibbs					mmparse();
41295376Sgibbs					mm_switch_to_buffer(temp_state);
41395376Sgibbs					yy_switch_to_buffer(old_state);
41495376Sgibbs					mm_delete_buffer(temp_state);
41595376Sgibbs					expand_macro(yylval.sym);
41695376Sgibbs				} else {
41795376Sgibbs					if (yylval.sym->type == UNINITIALIZED) {
41895376Sgibbs						/* Try without the '(' */
41995376Sgibbs						symbol_delete(yylval.sym);
42095376Sgibbs						yytext[yyleng-1] = '\0';
42195376Sgibbs						yylval.sym =
42295376Sgibbs						    symtable_get(yytext);
42395376Sgibbs					}
42495376Sgibbs					unput('(');
42595376Sgibbs					return T_SYMBOL;
42695376Sgibbs				}
42795376Sgibbs			}
42895376Sgibbs{WORD}			{
42995376Sgibbs				yylval.sym = symtable_get(yytext);
43095376Sgibbs				if (yylval.sym->type == MACRO) {
43195376Sgibbs					expand_macro(yylval.sym);
43295376Sgibbs				} else {
43395376Sgibbs					return T_SYMBOL;
43495376Sgibbs				}
43595376Sgibbs			}
43623925Sgibbs.			{
437193244Sdelphij				snprintf(msgbuf, sizeof(msgbuf), "Invalid character "
43823925Sgibbs					 "'%c'", yytext[0]);
439193244Sdelphij				stop(msgbuf, EX_DATAERR);
44023925Sgibbs			}
44123925Sgibbs%%
44223925Sgibbs
44323925Sgibbstypedef struct include {
44423925Sgibbs        YY_BUFFER_STATE  buffer;
44523925Sgibbs        int              lineno;
44623925Sgibbs        char            *filename;
44760938Sjake	SLIST_ENTRY(include) links;
44823925Sgibbs}include_t;
44923925Sgibbs
45060938SjakeSLIST_HEAD(, include) include_stack;
45123925Sgibbs
45223925Sgibbsvoid
45365943Sgibbsinclude_file(char *file_name, include_type type)
45423925Sgibbs{
45523925Sgibbs	FILE *newfile;
45623925Sgibbs	include_t *include;
45723925Sgibbs
45823925Sgibbs	newfile = NULL;
45923925Sgibbs	/* Try the current directory first */
46023925Sgibbs	if (includes_search_curdir != 0 || type == SOURCE_FILE)
46123925Sgibbs		newfile = fopen(file_name, "r");
46223925Sgibbs
46323925Sgibbs	if (newfile == NULL && type != SOURCE_FILE) {
46423925Sgibbs                path_entry_t include_dir;
46523925Sgibbs                for (include_dir = search_path.slh_first;
46623925Sgibbs                     include_dir != NULL;
46723925Sgibbs                     include_dir = include_dir->links.sle_next) {
46823925Sgibbs			char fullname[PATH_MAX];
46923925Sgibbs
47023925Sgibbs			if ((include_dir->quoted_includes_only == TRUE)
47123925Sgibbs			 && (type != QUOTED_INCLUDE))
47223925Sgibbs				continue;
47323925Sgibbs
47423925Sgibbs			snprintf(fullname, sizeof(fullname),
47523925Sgibbs				 "%s/%s", include_dir->directory, file_name);
47623925Sgibbs
47723925Sgibbs			if ((newfile = fopen(fullname, "r")) != NULL)
47823925Sgibbs				break;
47923925Sgibbs                }
48023925Sgibbs        }
48123925Sgibbs
48223925Sgibbs	if (newfile == NULL) {
48323925Sgibbs		perror(file_name);
48423925Sgibbs		stop("Unable to open input file", EX_SOFTWARE);
48523925Sgibbs		/* NOTREACHED */
48623925Sgibbs	}
48726997Sgibbs
48826997Sgibbs	if (type != SOURCE_FILE) {
48926997Sgibbs		include = (include_t *)malloc(sizeof(include_t));
49026997Sgibbs		if (include == NULL) {
49126997Sgibbs			stop("Unable to allocate include stack entry",
49226997Sgibbs			     EX_SOFTWARE);
49326997Sgibbs			/* NOTREACHED */
49426997Sgibbs		}
49526997Sgibbs		include->buffer = YY_CURRENT_BUFFER;
49626997Sgibbs		include->lineno = yylineno;
49726997Sgibbs		include->filename = yyfilename;
49826997Sgibbs		SLIST_INSERT_HEAD(&include_stack, include, links);
49923925Sgibbs	}
50023925Sgibbs	yy_switch_to_buffer(yy_create_buffer(newfile, YY_BUF_SIZE));
50123925Sgibbs	yylineno = 1;
50223925Sgibbs	yyfilename = strdup(file_name);
50323925Sgibbs}
50423925Sgibbs
50595376Sgibbsstatic void next_substitution(struct symbol *mac_symbol, const char *body_pos,
50695376Sgibbs			      const char **next_match,
50795376Sgibbs			      struct macro_arg **match_marg, regmatch_t *match);
50895376Sgibbs
50995376Sgibbsvoid
51095376Sgibbsexpand_macro(struct symbol *macro_symbol)
51195376Sgibbs{
51295376Sgibbs	struct macro_arg *marg;
51395376Sgibbs	struct macro_arg *match_marg;
51495376Sgibbs	const char *body_head;
51595376Sgibbs	const char *body_pos;
51695376Sgibbs	const char *next_match;
517193268Sdelphij	regmatch_t match = { .rm_so = 0, .rm_eo = 0 };
51895376Sgibbs
51995376Sgibbs	/*
52095376Sgibbs	 * Due to the nature of unput, we must work
52195376Sgibbs	 * backwards through the macro body performing
52295376Sgibbs	 * any expansions.
52395376Sgibbs	 */
52495376Sgibbs	body_head = macro_symbol->info.macroinfo->body;
52595376Sgibbs	body_pos = body_head + strlen(body_head);
52695376Sgibbs	while (body_pos > body_head) {
52795376Sgibbs		next_match = body_head;
52895376Sgibbs		match_marg = NULL;
52995376Sgibbs		next_substitution(macro_symbol, body_pos, &next_match,
53095376Sgibbs				  &match_marg, &match);
53195376Sgibbs
53295376Sgibbs		/* Put back everything up until the replacement. */
53395376Sgibbs		while (body_pos > next_match)
53495376Sgibbs			unput(*--body_pos);
53595376Sgibbs
53695376Sgibbs		/* Perform the replacement. */
53795376Sgibbs		if (match_marg != NULL) {
53895376Sgibbs			const char *strp;
53995376Sgibbs
54095376Sgibbs			next_match = match_marg->replacement_text;
54195376Sgibbs			strp = next_match + strlen(next_match);
54295376Sgibbs			while (strp > next_match)
54395376Sgibbs				unput(*--strp);
54495376Sgibbs
54595376Sgibbs			/* Skip past the unexpanded macro arg. */
54695376Sgibbs			body_pos -= match.rm_eo - match.rm_so;
54795376Sgibbs		}
54895376Sgibbs	}
54995376Sgibbs
55095376Sgibbs	/* Cleanup replacement text. */
55195376Sgibbs	STAILQ_FOREACH(marg, &macro_symbol->info.macroinfo->args, links) {
55295376Sgibbs		free(marg->replacement_text);
55395376Sgibbs	}
55495376Sgibbs}
55595376Sgibbs
55695376Sgibbs/*
55795376Sgibbs * Find the next substitution in the macro working backwards from
55895376Sgibbs * body_pos until the beginning of the macro buffer.  next_match
55995376Sgibbs * should be initialized to the beginning of the macro buffer prior
56095376Sgibbs * to calling this routine.
56195376Sgibbs */
56295376Sgibbsstatic void
56395376Sgibbsnext_substitution(struct symbol *mac_symbol, const char *body_pos,
56495376Sgibbs		  const char **next_match, struct macro_arg **match_marg,
56595376Sgibbs		  regmatch_t *match)
56695376Sgibbs{
56795376Sgibbs	regmatch_t	  matches[2];
56895376Sgibbs	struct macro_arg *marg;
56995376Sgibbs	const char	 *search_pos;
57095376Sgibbs	int		  retval;
57195376Sgibbs
57295376Sgibbs	do {
57395376Sgibbs		search_pos = *next_match;
57495376Sgibbs
57595376Sgibbs		STAILQ_FOREACH(marg, &mac_symbol->info.macroinfo->args, links) {
57695376Sgibbs
57795376Sgibbs			retval = regexec(&marg->arg_regex, search_pos, 2,
57895376Sgibbs					 matches, 0);
57995376Sgibbs			if (retval == 0
58095376Sgibbs			 && (matches[1].rm_eo + search_pos) <= body_pos
58195376Sgibbs			 && (matches[1].rm_eo + search_pos) > *next_match) {
58295376Sgibbs				*match = matches[1];
58395376Sgibbs				*next_match = match->rm_eo + search_pos;
58495376Sgibbs				*match_marg = marg;
58595376Sgibbs			}
58695376Sgibbs		}
58795376Sgibbs	} while (search_pos != *next_match);
58895376Sgibbs}
58995376Sgibbs
59023925Sgibbsint
591201261Sedyywrap(void)
59223925Sgibbs{
59323925Sgibbs	include_t *include;
59423925Sgibbs
59523925Sgibbs	yy_delete_buffer(YY_CURRENT_BUFFER);
59623925Sgibbs	(void)fclose(yyin);
59723925Sgibbs	if (yyfilename != NULL)
59823925Sgibbs		free(yyfilename);
59926997Sgibbs	yyfilename = NULL;
60023925Sgibbs	include = include_stack.slh_first;
60123925Sgibbs	if (include != NULL) {
60223925Sgibbs		yy_switch_to_buffer(include->buffer);
60323925Sgibbs		yylineno = include->lineno;
60423925Sgibbs		yyfilename = include->filename;
60523925Sgibbs		SLIST_REMOVE_HEAD(&include_stack, links);
60623925Sgibbs		free(include);
60723925Sgibbs		return (0);
60823925Sgibbs	}
60923925Sgibbs	return (1);
61023925Sgibbs}
611