xref: /freebsd/sys/dev/aic7xxx/aicasm/aicasm_scan.l (revision 9207b4cff7b8d483f4dd3c62266c2b58819eb7f9)
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  * Alternatively, this software may be distributed under the terms of the
18  * GNU Public License ("GPL").
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
24  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  *
32  * $Id: //depot/src/aic7xxx/aicasm/aicasm_scan.l#5 $
33  *
34  * $FreeBSD$
35  */
36 
37 #include <sys/types.h>
38 
39 #include <limits.h>
40 #include <stdio.h>
41 #include <string.h>
42 #include <sysexits.h>
43 #ifdef __linux__
44 #include "../queue.h"
45 #else
46 #include <sys/queue.h>
47 #endif
48 
49 #include "aicasm.h"
50 #include "aicasm_symbol.h"
51 #include "y.tab.h"
52 
53 #define MAX_STR_CONST 256
54 char string_buf[MAX_STR_CONST];
55 char *string_buf_ptr;
56 int  parren_count;
57 int  quote_count;
58 %}
59 
60 %option nounput
61 
62 PATH		[-/A-Za-z0-9_.]*[./][-/A-Za-z0-9_.]*
63 WORD		[A-Za-z_][-A-Za-z_0-9]*
64 SPACE		[ \t]+
65 
66 %x COMMENT
67 %x CEXPR
68 %x INCLUDE
69 %x STRING
70 
71 %%
72 \n			{ ++yylineno; }
73 "/*"			{ BEGIN COMMENT;  /* Enter comment eating state */ }
74 <COMMENT>"/*"		{ fprintf(stderr, "Warning! Comment within comment."); }
75 <COMMENT>\n		{ ++yylineno; }
76 <COMMENT>[^*/\n]*	;
77 <COMMENT>"*"+[^*/\n]*	;
78 <COMMENT>"/"+[^*/\n]*	;
79 <COMMENT>"*"+"/"	{ BEGIN INITIAL; }
80 if[ \t]*\(		{
81 				string_buf_ptr = string_buf;
82 				parren_count = 1;
83 				BEGIN CEXPR;
84 				return T_IF;
85 			}
86 <CEXPR>\(		{	*string_buf_ptr++ = '('; parren_count++; }
87 <CEXPR>\)		{
88 				parren_count--;
89 				if (parren_count == 0) {
90 					/* All done */
91 					BEGIN INITIAL;
92 					*string_buf_ptr = '\0';
93 					yylval.sym = symtable_get(string_buf);
94 					return T_CEXPR;
95 				} else {
96 					*string_buf_ptr++ = ')';
97 				}
98 			}
99 <CEXPR>\n		{ ++yylineno; }
100 <CEXPR>[^()\n]+	{
101 				char *yptr;
102 
103 				yptr = yytext;
104 				while (*yptr != '\0') {
105 					/* Remove duplicate spaces */
106 					if (*yptr == '\t')
107 						*yptr = ' ';
108 					if (*yptr == ' '
109 					 && string_buf_ptr != string_buf
110 					 && string_buf_ptr[-1] == ' ')
111 						yptr++;
112 					else
113 						*string_buf_ptr++ = *yptr++;
114 				}
115 			}
116 
117 VERSION			{ return T_VERSION; }
118 \"			{
119 				string_buf_ptr = string_buf;
120 				BEGIN STRING;
121 			}
122 <STRING>[^"]+		{
123 				char *yptr;
124 
125 				yptr = yytext;
126 				while (*yptr)
127 					*string_buf_ptr++ = *yptr++;
128 			}
129 <STRING>\"		{
130 				/* All done */
131 				BEGIN INITIAL;
132 				*string_buf_ptr = '\0';
133 				yylval.str = string_buf;
134 				return T_STRING;
135 			}
136 {SPACE}			;
137 
138 	/* Register/SCB/SRAM definition keywords */
139 register		{ return T_REGISTER; }
140 const			{ yylval.value = FALSE; return T_CONST; }
141 download		{ return T_DOWNLOAD; }
142 address			{ return T_ADDRESS; }
143 access_mode		{ return T_ACCESS_MODE; }
144 RW|RO|WO		{
145 				 if (strcmp(yytext, "RW") == 0)
146 					yylval.value = RW;
147 				 else if (strcmp(yytext, "RO") == 0)
148 					yylval.value = RO;
149 				 else
150 					yylval.value = WO;
151 				 return T_MODE;
152 			}
153 BEGIN_CRITICAL		{ return T_BEGIN_CS; }
154 END_CRITICAL		{ return T_END_CS; }
155 bit			{ return T_BIT; }
156 mask			{ return T_MASK; }
157 alias			{ return T_ALIAS; }
158 size			{ return T_SIZE; }
159 scb			{ return T_SCB; }
160 scratch_ram		{ return T_SRAM; }
161 accumulator		{ return T_ACCUM; }
162 allones			{ return T_ALLONES; }
163 allzeros		{ return T_ALLZEROS; }
164 none			{ return T_NONE; }
165 sindex			{ return T_SINDEX; }
166 A			{ return T_A; }
167 
168 	/* Opcodes */
169 shl			{ return T_SHL; }
170 shr			{ return T_SHR; }
171 ror			{ return T_ROR; }
172 rol			{ return T_ROL; }
173 mvi			{ return T_MVI; }
174 mov			{ return T_MOV; }
175 clr			{ return T_CLR; }
176 jmp			{ return T_JMP; }
177 jc			{ return T_JC;	}
178 jnc			{ return T_JNC;	}
179 je			{ return T_JE;	}
180 jne			{ return T_JNE;	}
181 jz			{ return T_JZ;	}
182 jnz			{ return T_JNZ;	}
183 call			{ return T_CALL; }
184 add			{ return T_ADD; }
185 adc			{ return T_ADC; }
186 bmov			{ return T_BMOV; }
187 inc			{ return T_INC; }
188 dec			{ return T_DEC; }
189 stc			{ return T_STC;	}
190 clc			{ return T_CLC; }
191 cmp			{ return T_CMP;	}
192 not			{ return T_NOT;	}
193 xor			{ return T_XOR;	}
194 test			{ return T_TEST;}
195 and			{ return T_AND;	}
196 or			{ return T_OR;	}
197 ret			{ return T_RET; }
198 nop			{ return T_NOP; }
199 else			{ return T_ELSE; }
200 
201 	/* Allowed Symbols */
202 [-+,:()~|&."{};<>[\]!=]	{ return yytext[0]; }
203 
204 	/* Number processing */
205 0[0-7]*			{
206 				yylval.value = strtol(yytext, NULL, 8);
207 				return T_NUMBER;
208 			}
209 
210 0[xX][0-9a-fA-F]+	{
211 				yylval.value = strtoul(yytext + 2, NULL, 16);
212 				return T_NUMBER;
213 			}
214 
215 [1-9][0-9]*		{
216 				yylval.value = strtol(yytext, NULL, 10);
217 				return T_NUMBER;
218 			}
219 
220 	/* Include Files */
221 #include{SPACE}		{
222 				BEGIN INCLUDE;
223 				quote_count = 0;
224 				return T_INCLUDE;
225 			}
226 <INCLUDE>[<]		{ return yytext[0]; }
227 <INCLUDE>[>]		{ BEGIN INITIAL; return yytext[0]; }
228 <INCLUDE>[\"]		{
229 				if (quote_count != 0)
230 					BEGIN INITIAL;
231 				quote_count++;
232 				return yytext[0];
233 			}
234 <INCLUDE>.		{ stop("Invalid include line", EX_DATAERR); }
235 
236 	/* For parsing C include files with #define foo */
237 #define			{ yylval.value = TRUE; return T_CONST; }
238 	/* Throw away macros */
239 #define[^\n]*[()]+[^\n]* ;
240 <INITIAL,INCLUDE>{PATH}	{
241 				char *yptr;
242 
243 				yptr = yytext;
244 				string_buf_ptr = string_buf;
245 				while (*yptr)
246 					*string_buf_ptr++ = *yptr++;
247 				yylval.str = string_buf;
248 				*string_buf_ptr = '\0';
249 				return T_PATH;
250 			}
251 
252 {WORD}			{ yylval.sym = symtable_get(yytext);  return T_SYMBOL; }
253 
254 .			{
255 				char buf[255];
256 
257 				snprintf(buf, sizeof(buf), "Invalid character "
258 					 "'%c'", yytext[0]);
259 				stop(buf, EX_DATAERR);
260 			}
261 %%
262 
263 typedef struct include {
264         YY_BUFFER_STATE  buffer;
265         int              lineno;
266         char            *filename;
267 	SLIST_ENTRY(include) links;
268 }include_t;
269 
270 SLIST_HEAD(, include) include_stack;
271 
272 void
273 include_file(char *file_name, include_type type)
274 {
275 	FILE *newfile;
276 	include_t *include;
277 
278 	newfile = NULL;
279 	/* Try the current directory first */
280 	if (includes_search_curdir != 0 || type == SOURCE_FILE)
281 		newfile = fopen(file_name, "r");
282 
283 	if (newfile == NULL && type != SOURCE_FILE) {
284                 path_entry_t include_dir;
285                 for (include_dir = search_path.slh_first;
286                      include_dir != NULL;
287                      include_dir = include_dir->links.sle_next) {
288 			char fullname[PATH_MAX];
289 
290 			if ((include_dir->quoted_includes_only == TRUE)
291 			 && (type != QUOTED_INCLUDE))
292 				continue;
293 
294 			snprintf(fullname, sizeof(fullname),
295 				 "%s/%s", include_dir->directory, file_name);
296 
297 			if ((newfile = fopen(fullname, "r")) != NULL)
298 				break;
299                 }
300         }
301 
302 	if (newfile == NULL) {
303 		perror(file_name);
304 		stop("Unable to open input file", EX_SOFTWARE);
305 		/* NOTREACHED */
306 	}
307 
308 	if (type != SOURCE_FILE) {
309 		include = (include_t *)malloc(sizeof(include_t));
310 		if (include == NULL) {
311 			stop("Unable to allocate include stack entry",
312 			     EX_SOFTWARE);
313 			/* NOTREACHED */
314 		}
315 		include->buffer = YY_CURRENT_BUFFER;
316 		include->lineno = yylineno;
317 		include->filename = yyfilename;
318 		SLIST_INSERT_HEAD(&include_stack, include, links);
319 	}
320 	yy_switch_to_buffer(yy_create_buffer(newfile, YY_BUF_SIZE));
321 	yylineno = 1;
322 	yyfilename = strdup(file_name);
323 }
324 
325 int
326 yywrap()
327 {
328 	include_t *include;
329 
330 	yy_delete_buffer(YY_CURRENT_BUFFER);
331 	(void)fclose(yyin);
332 	if (yyfilename != NULL)
333 		free(yyfilename);
334 	yyfilename = NULL;
335 	include = include_stack.slh_first;
336 	if (include != NULL) {
337 		yy_switch_to_buffer(include->buffer);
338 		yylineno = include->lineno;
339 		yyfilename = include->filename;
340 		SLIST_REMOVE_HEAD(&include_stack, links);
341 		free(include);
342 		return (0);
343 	}
344 	return (1);
345 }
346