1 %{
2 /*
3  * Lexical Analyzer for the Aic7xxx SCSI Host adapter sequencer assembler.
4  *
5  * Copyright (c) 1997-1998 Justin T. Gibbs.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions, and the following disclaimer,
13  *    without modification.
14  * 2. The name of the author may not be used to endorse or promote products
15  *    derived from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
21  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * $FreeBSD: src/sys/dev/aic7xxx/aicasm_scan.l,v 1.8 1999/12/06 18:23:30 gibbs Exp $
30  */
31 
32 #include <sys/types.h>
33 
34 #include <limits.h>
35 #include <stdio.h>
36 #include <string.h>
37 #include <sysexits.h>
38 #include <sys/queue.h>
39 
40 #include "aicasm.h"
41 #include "aicasm_symbol.h"
42 #include "y.tab.h"
43 
44 #define MAX_STR_CONST 256
45 char string_buf[MAX_STR_CONST];
46 char *string_buf_ptr;
47 int  parren_count;
48 %}
49 
50 PATH		[-/A-Za-z0-9_.]*[./][-/A-Za-z0-9_.]*
51 WORD		[A-Za-z_][-A-Za-z_0-9]*
52 SPACE		[ \t]+
53 
54 %x COMMENT
55 %x CEXPR
56 %x INCLUDE
57 
58 %%
59 \n			{ ++yylineno; }
60 "/*"			{ BEGIN COMMENT;  /* Enter comment eating state */ }
61 <COMMENT>"/*"		{ fprintf(stderr, "Warning! Comment within comment."); }
62 <COMMENT>\n		{ ++yylineno; }
63 <COMMENT>[^*/\n]*	;
64 <COMMENT>"*"+[^*/\n]*	;
65 <COMMENT>"/"+[^*/\n]*	;
66 <COMMENT>"*"+"/"	{ BEGIN INITIAL; }
67 if[ \t]*\(		{
68 				string_buf_ptr = string_buf;
69 				parren_count = 1;
70 				BEGIN CEXPR;
71 				return T_IF;
72 			}
73 <CEXPR>\(		{	*string_buf_ptr++ = '('; parren_count++; }
74 <CEXPR>\)		{
75 				parren_count--;
76 				if (parren_count == 0) {
77 					/* All done */
78 					BEGIN INITIAL;
79 					*string_buf_ptr = '\0';
80 					yylval.sym = symtable_get(string_buf);
81 					return T_CEXPR;
82 				} else {
83 					*string_buf_ptr++ = ')';
84 				}
85 			}
86 <CEXPR>\n		{ ++yylineno; }
87 <CEXPR>[^()\n]+		{
88 				char *yptr = yytext;
89 
90 				while (*yptr != '\0')
91 					*string_buf_ptr++ = *yptr++;
92 			}
93 
94 {SPACE}			;
95 
96 	/* Register/SCB/SRAM definition keywords */
97 register		{ return T_REGISTER; }
98 const			{ yylval.value = FALSE; return T_CONST; }
99 download		{ return T_DOWNLOAD; }
100 address			{ return T_ADDRESS; }
101 access_mode		{ return T_ACCESS_MODE; }
102 RW|RO|WO		{
103 				 if (strcmp(yytext, "RW") == 0)
104 					yylval.value = RW;
105 				 else if (strcmp(yytext, "RO") == 0)
106 					yylval.value = RO;
107 				 else
108 					yylval.value = WO;
109 				 return T_MODE;
110 			}
111 bit			{ return T_BIT; }
112 mask			{ return T_MASK; }
113 alias			{ return T_ALIAS; }
114 size			{ return T_SIZE; }
115 scb			{ return T_SCB; }
116 scratch_ram		{ return T_SRAM; }
117 accumulator		{ return T_ACCUM; }
118 allones			{ return T_ALLONES; }
119 allzeros		{ return T_ALLZEROS; }
120 none			{ return T_NONE; }
121 sindex			{ return T_SINDEX; }
122 A			{ return T_A; }
123 
124 	/* Opcodes */
125 shl			{ return T_SHL; }
126 shr			{ return T_SHR; }
127 ror			{ return T_ROR; }
128 rol			{ return T_ROL; }
129 mvi			{ return T_MVI; }
130 mov			{ return T_MOV; }
131 clr			{ return T_CLR; }
132 jmp			{ return T_JMP; }
133 jc			{ return T_JC;	}
134 jnc			{ return T_JNC;	}
135 je			{ return T_JE;	}
136 jne			{ return T_JNE;	}
137 jz			{ return T_JZ;	}
138 jnz			{ return T_JNZ;	}
139 call			{ return T_CALL; }
140 add			{ return T_ADD; }
141 adc			{ return T_ADC; }
142 bmov			{ return T_BMOV; }
143 inc			{ return T_INC; }
144 dec			{ return T_DEC; }
145 stc			{ return T_STC;	}
146 clc			{ return T_CLC; }
147 cmp			{ return T_CMP;	}
148 xor			{ return T_XOR;	}
149 test			{ return T_TEST;}
150 and			{ return T_AND;	}
151 or			{ return T_OR;	}
152 ret			{ return T_RET; }
153 nop			{ return T_NOP; }
154 else			{ return T_ELSE; }
155 
156 	/* Allowed Symbols */
157 [-+,:()~|&."{};<>[\]!]	{ return yytext[0]; }
158 
159 	/* Number processing */
160 0[0-7]*			{
161 				yylval.value = strtol(yytext, NULL, 8);
162 				return T_NUMBER;
163 			}
164 
165 0[xX][0-9a-fA-F]+	{
166 				yylval.value = strtoul(yytext + 2, NULL, 16);
167 				return T_NUMBER;
168 			}
169 
170 [1-9][0-9]*		{
171 				yylval.value = strtol(yytext, NULL, 10);
172 				return T_NUMBER;
173 			}
174 
175 	/* Include Files */
176 #include		{ return T_INCLUDE; BEGIN INCLUDE;}
177 <INCLUDE>[<>\"]		{ return yytext[0]; }
178 <INCLUDE>{PATH}		{ yylval.str = strdup(yytext); return T_PATH; }
179 <INCLUDE>;		{ BEGIN INITIAL; return yytext[0]; }
180 <INCLUDE>.		{ stop("Invalid include line", EX_DATAERR); }
181 
182 	/* For parsing C include files with #define foo */
183 #define			{ yylval.value = TRUE; return T_CONST; }
184 	/* Throw away macros */
185 #define[^\n]*[()]+[^\n]* ;
186 {PATH}			{ yylval.str = strdup(yytext); return T_PATH; }
187 
188 {WORD}			{ yylval.sym = symtable_get(yytext);  return T_SYMBOL; }
189 
190 .			{
191 				char buf[255];
192 
193 				snprintf(buf, sizeof(buf), "Invalid character "
194 					 "'%c'", yytext[0]);
195 				stop(buf, EX_DATAERR);
196 			}
197 %%
198 
199 typedef struct include {
200         YY_BUFFER_STATE  buffer;
201         int              lineno;
202         char            *filename;
203 	SLIST_ENTRY(include) links;
204 }include_t;
205 
206 SLIST_HEAD(, include) include_stack;
207 
208 void
209 include_file(file_name, type)
210 	char	*file_name;
211 	include_type type;
212 {
213 	FILE *newfile;
214 	include_t *include;
215 
216 	newfile = NULL;
217 	/* Try the current directory first */
218 	if (includes_search_curdir != 0 || type == SOURCE_FILE)
219 		newfile = fopen(file_name, "r");
220 
221 	if (newfile == NULL && type != SOURCE_FILE) {
222                 path_entry_t include_dir;
223                 for (include_dir = search_path.slh_first;
224                      include_dir != NULL;
225                      include_dir = include_dir->links.sle_next) {
226 			char fullname[PATH_MAX];
227 
228 			if ((include_dir->quoted_includes_only == TRUE)
229 			 && (type != QUOTED_INCLUDE))
230 				continue;
231 
232 			snprintf(fullname, sizeof(fullname),
233 				 "%s/%s", include_dir->directory, file_name);
234 
235 			if ((newfile = fopen(fullname, "r")) != NULL)
236 				break;
237                 }
238         }
239 
240 	if (newfile == NULL) {
241 		perror(file_name);
242 		stop("Unable to open input file", EX_SOFTWARE);
243 		/* NOTREACHED */
244 	}
245 
246 	if (type != SOURCE_FILE) {
247 		include = (include_t *)malloc(sizeof(include_t));
248 		if (include == NULL) {
249 			stop("Unable to allocate include stack entry",
250 			     EX_SOFTWARE);
251 			/* NOTREACHED */
252 		}
253 		include->buffer = YY_CURRENT_BUFFER;
254 		include->lineno = yylineno;
255 		include->filename = yyfilename;
256 		SLIST_INSERT_HEAD(&include_stack, include, links);
257 	}
258 	yy_switch_to_buffer(yy_create_buffer(newfile, YY_BUF_SIZE));
259 	yylineno = 1;
260 	yyfilename = strdup(file_name);
261 }
262 
263 int
264 yywrap()
265 {
266 	include_t *include;
267 
268 	yy_delete_buffer(YY_CURRENT_BUFFER);
269 	(void)fclose(yyin);
270 	if (yyfilename != NULL)
271 		free(yyfilename);
272 	yyfilename = NULL;
273 	include = include_stack.slh_first;
274 	if (include != NULL) {
275 		yy_switch_to_buffer(include->buffer);
276 		yylineno = include->lineno;
277 		yyfilename = include->filename;
278 		SLIST_REMOVE_HEAD(&include_stack, links);
279 		free(include);
280 		return (0);
281 	}
282 	return (1);
283 }
284