File Index
Files and directories
Sign in
FILE

aicasm_scan.l

File preview with syntax highlighting.

linux-6.19.14/drivers/scsi/aic7xxx/aicasm/aicasm_scan.l PLAIN TEXT
  1%{
  2/*
  3 * Lexical Analyzer for the Aic7xxx SCSI Host adapter sequencer assembler.
  4 *
  5 * Copyright (c) 1997, 1998, 2000 Justin T. Gibbs.
  6 * Copyright (c) 2001, 2002 Adaptec Inc.
  7 * All rights reserved.
  8 *
  9 * Redistribution and use in source and binary forms, with or without
 10 * modification, are permitted provided that the following conditions
 11 * are met:
 12 * 1. Redistributions of source code must retain the above copyright
 13 *    notice, this list of conditions, and the following disclaimer,
 14 *    without modification.
 15 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
 16 *    substantially similar to the "NO WARRANTY" disclaimer below
 17 *    ("Disclaimer") and any redistribution must be conditioned upon
 18 *    including a substantially similar Disclaimer requirement for further
 19 *    binary redistribution.
 20 * 3. Neither the names of the above-listed copyright holders nor the names
 21 *    of any contributors may be used to endorse or promote products derived
 22 *    from this software without specific prior written permission.
 23 *
 24 * Alternatively, this software may be distributed under the terms of the
 25 * GNU General Public License ("GPL") version 2 as published by the Free
 26 * Software Foundation.
 27 *
 28 * NO WARRANTY
 29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
 32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 33 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 37 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 38 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 39 * POSSIBILITY OF SUCH DAMAGES.
 40 *
 41 * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_scan.l#20 $
 42 *
 43 * $FreeBSD$
 44 */
 45
 46#include <sys/types.h>
 47
 48#include <inttypes.h>
 49#include <limits.h>
 50#include <regex.h>
 51#include <stdio.h>
 52#include <string.h>
 53#include <sysexits.h>
 54#include "../queue.h"
 55
 56#include "aicasm.h"
 57#include "aicasm_symbol.h"
 58#include "aicasm_gram.h"
 59
 60/* This is used for macro body capture too, so err on the large size. */
 61#define MAX_STR_CONST 4096
 62static char string_buf[MAX_STR_CONST];
 63static char *string_buf_ptr;
 64static int  parren_count;
 65static int  quote_count;
 66static char buf[255];
 67void mm_switch_to_buffer(YY_BUFFER_STATE);
 68void mmparse();
 69void mm_delete_buffer(YY_BUFFER_STATE);
 70%}
 71
 72PATH		([/]*[-A-Za-z0-9_.])+
 73WORD		[A-Za-z_][-A-Za-z_0-9]*
 74SPACE		[ \t]+
 75MCARG		[^(), \t]+
 76MBODY		((\\[^\n])*[^\n\\]*)+
 77
 78%x COMMENT
 79%x CEXPR
 80%x INCLUDE
 81%x STRING
 82%x MACRODEF
 83%x MACROARGLIST
 84%x MACROCALLARGS
 85%x MACROBODY
 86
 87%%
 88\n			{ ++yylineno; }
 89\r			;
 90"/*"			{ BEGIN COMMENT;  /* Enter comment eating state */ }
 91<COMMENT>"/*"		{ fprintf(stderr, "Warning! Comment within comment."); }
 92<COMMENT>\n		{ ++yylineno; }
 93<COMMENT>[^*/\n]*	;
 94<COMMENT>"*"+[^*/\n]*	;
 95<COMMENT>"/"+[^*/\n]*	;
 96<COMMENT>"*"+"/"	{ BEGIN INITIAL; }
 97if[ \t]*\(		{
 98				string_buf_ptr = string_buf;
 99				parren_count = 1;
100				BEGIN CEXPR;
101				return T_IF;
102			}
103<CEXPR>\(		{	*string_buf_ptr++ = '('; parren_count++; }
104<CEXPR>\)		{
105				parren_count--;
106				if (parren_count == 0) {
107					/* All done */
108					BEGIN INITIAL;
109					*string_buf_ptr = '\0';
110					yylval.sym = symtable_get(string_buf);
111					return T_CEXPR;
112				} else {
113					*string_buf_ptr++ = ')';
114				}
115			}
116<CEXPR>\n		{ ++yylineno; }
117<CEXPR>\r		;
118<CEXPR>[^()\n]+	{
119				char *yptr;
120
121				yptr = yytext;
122				while (*yptr != '\0') {
123					/* Remove duplicate spaces */
124					if (*yptr == '\t')
125						*yptr = ' ';
126					if (*yptr == ' '
127					 && string_buf_ptr != string_buf
128					 && string_buf_ptr[-1] == ' ')
129						yptr++;
130					else 
131						*string_buf_ptr++ = *yptr++;
132				}
133			}
134else			{ return T_ELSE; }
135VERSION			{ return T_VERSION; }
136PREFIX			{ return T_PREFIX; }
137PATCH_ARG_LIST		{ return T_PATCH_ARG_LIST; }
138\"			{
139				string_buf_ptr = string_buf;
140				BEGIN STRING;
141			}
142<STRING>[^"]+		{
143				char *yptr;
144
145				yptr = yytext;
146				while (*yptr)
147					*string_buf_ptr++ = *yptr++;
148			}
149<STRING>\"		{
150				/* All done */
151				BEGIN INITIAL;
152				*string_buf_ptr = '\0';
153				yylval.str = string_buf;
154				return T_STRING;
155			}
156{SPACE}			 ;
157
158	/* Register/SCB/SRAM definition keywords */
159export			{ return T_EXPORT; }
160register		{ return T_REGISTER; }
161const			{ yylval.value = FALSE; return T_CONST; }
162download		{ return T_DOWNLOAD; }
163address			{ return T_ADDRESS; }
164count			{ return T_COUNT; }
165access_mode		{ return T_ACCESS_MODE; }
166dont_generate_debug_code { return T_DONT_GENERATE_DEBUG_CODE; }
167modes			{ return T_MODES; }
168RW|RO|WO		{
169				 if (strcmp(yytext, "RW") == 0)
170					yylval.value = RW;
171				 else if (strcmp(yytext, "RO") == 0)
172					yylval.value = RO;
173				 else
174					yylval.value = WO;
175				 return T_MODE;
176			}
177field			{ return T_FIELD; }
178enum			{ return T_ENUM; }
179mask			{ return T_MASK; }
180alias			{ return T_ALIAS; }
181size			{ return T_SIZE; }
182scb			{ return T_SCB; }
183scratch_ram		{ return T_SRAM; }
184accumulator		{ return T_ACCUM; }
185mode_pointer		{ return T_MODE_PTR; }
186allones			{ return T_ALLONES; }
187allzeros		{ return T_ALLZEROS; }
188none			{ return T_NONE; }
189sindex			{ return T_SINDEX; }
190A			{ return T_A; }
191
192	/* Instruction Formatting */
193PAD_PAGE		{ return T_PAD_PAGE; }
194BEGIN_CRITICAL		{ return T_BEGIN_CS; }
195END_CRITICAL		{ return T_END_CS; }
196SET_SRC_MODE		{ return T_SET_SRC_MODE; }
197SET_DST_MODE		{ return T_SET_DST_MODE; }
198
199	/* Opcodes */
200shl			{ return T_SHL; }
201shr			{ return T_SHR; }
202ror			{ return T_ROR; }
203rol			{ return T_ROL; }
204mvi			{ return T_MVI; }
205mov			{ return T_MOV; }
206clr			{ return T_CLR; }
207jmp			{ return T_JMP; }
208jc			{ return T_JC;	}
209jnc			{ return T_JNC;	}
210je			{ return T_JE;	}
211jne			{ return T_JNE;	}
212jz			{ return T_JZ;	}
213jnz			{ return T_JNZ;	}
214call			{ return T_CALL; }
215add			{ return T_ADD; }
216adc			{ return T_ADC; }
217bmov			{ return T_BMOV; }
218inc			{ return T_INC; }
219dec			{ return T_DEC; }
220stc			{ return T_STC;	}
221clc			{ return T_CLC; }
222cmp			{ return T_CMP;	}
223not			{ return T_NOT;	}
224xor			{ return T_XOR;	}
225test			{ return T_TEST;}
226and			{ return T_AND;	}
227or			{ return T_OR;	}
228ret			{ return T_RET; }
229nop			{ return T_NOP; }
230
231	/* ARP2 16bit extensions */
232	/* or16			{ return T_OR16; } */
233	/* and16			{ return T_AND16; }*/
234	/* xor16			{ return T_XOR16; }*/
235	/* add16			{ return T_ADD16; }*/
236	/* adc16			{ return T_ADC16; }*/
237	/* mvi16			{ return T_MVI16; }*/
238	/* test16			{ return T_TEST16; }*/
239	/* cmp16			{ return T_CMP16; }*/
240	/* cmpxchg			{ return T_CMPXCHG; }*/
241
242	/* Allowed Symbols */
243\<\<			{ return T_EXPR_LSHIFT; }
244\>\>			{ return T_EXPR_RSHIFT; }
245[-+,:()~|&."{};<>[\]/*!=] { return yytext[0]; }
246
247	/* Number processing */
2480[0-7]*			{
249				yylval.value = strtol(yytext, NULL, 8);
250				return T_NUMBER;
251			}
252
2530[xX][0-9a-fA-F]+	{
254				yylval.value = strtoul(yytext + 2, NULL, 16);
255				return T_NUMBER;
256			}
257
258[1-9][0-9]*		{
259				yylval.value = strtol(yytext, NULL, 10);
260				return T_NUMBER;
261			}
262	/* Include Files */
263#include{SPACE}		{
264				BEGIN INCLUDE;
265				quote_count = 0;
266				return T_INCLUDE;
267			}
268<INCLUDE>[<]		{ return yytext[0]; }
269<INCLUDE>[>]		{ BEGIN INITIAL; return yytext[0]; }
270<INCLUDE>[\"]		{
271				if (quote_count != 0)
272					BEGIN INITIAL;
273				quote_count++;
274				return yytext[0];
275			}
276<INCLUDE>{PATH}		{
277				char *yptr;
278
279				yptr = yytext;
280				string_buf_ptr = string_buf;
281				while (*yptr)
282					*string_buf_ptr++ = *yptr++;
283				yylval.str = string_buf;
284				*string_buf_ptr = '\0';
285				return T_PATH;
286			}
287<INCLUDE>.		{ stop("Invalid include line", EX_DATAERR); }
288#define{SPACE}		{
289				BEGIN MACRODEF;
290				return T_DEFINE;
291			}
292<MACRODEF>{WORD}{SPACE}	{ 
293				char *yptr;
294
295				/* Strip space and return as a normal symbol */
296				yptr = yytext;
297				while (*yptr != ' ' && *yptr != '\t')
298					yptr++;
299				*yptr = '\0';
300				yylval.sym = symtable_get(yytext);
301				string_buf_ptr = string_buf;
302				BEGIN MACROBODY;
303				return T_SYMBOL;
304			}
305<MACRODEF>{WORD}\(	{
306				/*
307				 * We store the symbol with its opening
308				 * parren so we can differentiate macros
309				 * that take args from macros with the
310				 * same name that do not take args as
311				 * is allowed in C.
312				 */
313				BEGIN MACROARGLIST;
314				yylval.sym = symtable_get(yytext);
315				unput('(');
316				return T_SYMBOL;
317			}
318<MACROARGLIST>{WORD}	{
319				yylval.str = yytext;
320				return T_ARG;
321			}
322<MACROARGLIST>{SPACE}   ;
323<MACROARGLIST>[(,]	{
324				return yytext[0];
325			}
326<MACROARGLIST>[)]	{
327				string_buf_ptr = string_buf;
328				BEGIN MACROBODY;
329				return ')';
330			}
331<MACROARGLIST>.		{
332				snprintf(buf, sizeof(buf), "Invalid character "
333					 "'%c' in macro argument list",
334					 yytext[0]);
335				stop(buf, EX_DATAERR);
336			}
337<MACROCALLARGS>{SPACE}  ;
338<MACROCALLARGS>\(	{
339				parren_count++;
340				if (parren_count == 1)
341					return ('(');
342				*string_buf_ptr++ = '(';
343			}
344<MACROCALLARGS>\)	{
345				parren_count--;
346				if (parren_count == 0) {
347					BEGIN INITIAL;
348					return (')');
349				}
350				*string_buf_ptr++ = ')';
351			}
352<MACROCALLARGS>{MCARG}	{
353				char *yptr;
354
355				yptr = yytext;
356				while (*yptr)
357					*string_buf_ptr++ = *yptr++;
358			}
359<MACROCALLARGS>\,	{
360				if (string_buf_ptr != string_buf) {
361					/*
362					 * Return an argument and
363					 * rescan this comma so we
364					 * can return it as well.
365					 */
366					*string_buf_ptr = '\0';
367					yylval.str = string_buf;
368					string_buf_ptr = string_buf;
369					unput(',');
370					return T_ARG;
371				}
372				return ',';
373			}
374<MACROBODY>\\\n		{
375				/* Eat escaped newlines. */
376				++yylineno;
377			}
378<MACROBODY>\r		;
379<MACROBODY>\n		{
380				/* Macros end on the first unescaped newline. */
381				BEGIN INITIAL;
382				*string_buf_ptr = '\0';
383				yylval.str = string_buf;
384				++yylineno;
385				return T_MACROBODY;
386			}
387<MACROBODY>{MBODY}	{
388				char *yptr;
389				char c;
390
391				yptr = yytext;
392				while (c = *yptr++) {
393					/*
394					 * Strip carriage returns.
395					 */
396					if (c == '\r')
397						continue;
398					*string_buf_ptr++ = c;
399				}
400			}
401{WORD}\(		{
402				char *yptr;
403				char *ycopy;
404
405				/* May be a symbol or a macro invocation. */
406				yylval.sym = symtable_get(yytext);
407				if (yylval.sym->type == MACRO) {
408					YY_BUFFER_STATE old_state;
409					YY_BUFFER_STATE temp_state;
410
411					ycopy = strdup(yytext);
412					yptr = ycopy + yyleng;
413					while (yptr > ycopy)
414						unput(*--yptr);
415					old_state = YY_CURRENT_BUFFER;
416					temp_state =
417					    yy_create_buffer(stdin,
418							     YY_BUF_SIZE);
419					yy_switch_to_buffer(temp_state);
420					mm_switch_to_buffer(old_state);
421					mmparse();
422					mm_switch_to_buffer(temp_state);
423					yy_switch_to_buffer(old_state);
424					mm_delete_buffer(temp_state);
425					expand_macro(yylval.sym);
426				} else {
427					if (yylval.sym->type == UNINITIALIZED) {
428						/* Try without the '(' */
429						symbol_delete(yylval.sym);
430						yytext[yyleng-1] = '\0';
431						yylval.sym =
432						    symtable_get(yytext);
433					}
434					unput('(');
435					return T_SYMBOL;
436				}
437			}
438{WORD}			{
439				yylval.sym = symtable_get(yytext);
440				if (yylval.sym->type == MACRO) {
441					expand_macro(yylval.sym);
442				} else {
443					return T_SYMBOL;
444				}
445			}
446.			{ 
447				snprintf(buf, sizeof(buf), "Invalid character "
448					 "'%c'", yytext[0]);
449				stop(buf, EX_DATAERR);
450			}
451%%
452
453typedef struct include {
454        YY_BUFFER_STATE  buffer;
455        int              lineno;
456        char            *filename;
457	SLIST_ENTRY(include) links;
458}include_t;
459
460SLIST_HEAD(, include) include_stack;
461
462void
463include_file(char *file_name, include_type type)
464{
465	FILE *newfile;
466	include_t *include;
467
468	newfile = NULL;
469	/* Try the current directory first */
470	if (includes_search_curdir != 0 || type == SOURCE_FILE)
471		newfile = fopen(file_name, "r");
472
473	if (newfile == NULL && type != SOURCE_FILE) {
474                path_entry_t include_dir;
475                for (include_dir = search_path.slh_first;
476                     include_dir != NULL;                
477                     include_dir = include_dir->links.sle_next) {
478			char fullname[PATH_MAX];
479
480			if ((include_dir->quoted_includes_only == TRUE)
481			 && (type != QUOTED_INCLUDE))
482				continue;
483
484			snprintf(fullname, sizeof(fullname),
485				 "%s/%s", include_dir->directory, file_name);
486
487			if ((newfile = fopen(fullname, "r")) != NULL)
488				break;
489                }
490        }
491
492	if (newfile == NULL) {
493		perror(file_name);
494		stop("Unable to open input file", EX_SOFTWARE);
495		/* NOTREACHED */
496	}
497
498	if (type != SOURCE_FILE) {
499		include = (include_t *)malloc(sizeof(include_t));
500		if (include == NULL) {
501			stop("Unable to allocate include stack entry",
502			     EX_SOFTWARE);
503			/* NOTREACHED */
504		}
505		include->buffer = YY_CURRENT_BUFFER;
506		include->lineno = yylineno;
507		include->filename = yyfilename;
508		SLIST_INSERT_HEAD(&include_stack, include, links);
509	}
510	yy_switch_to_buffer(yy_create_buffer(newfile, YY_BUF_SIZE));
511	yylineno = 1;
512	yyfilename = strdup(file_name);
513}
514
515static void next_substitution(struct symbol *mac_symbol, const char *body_pos,
516			      const char **next_match,
517			      struct macro_arg **match_marg, regmatch_t *match);
518
519void
520expand_macro(struct symbol *macro_symbol)
521{
522	struct macro_arg *marg;
523	struct macro_arg *match_marg;
524	const char *body_head;
525	const char *body_pos;
526	const char *next_match;
527
528	/*
529	 * Due to the nature of unput, we must work
530	 * backwards through the macro body performing
531	 * any expansions.
532	 */
533	body_head = macro_symbol->info.macroinfo->body;
534	body_pos = body_head + strlen(body_head);
535	while (body_pos > body_head) {
536		regmatch_t match;
537
538		next_match = body_head;
539		match_marg = NULL;
540		next_substitution(macro_symbol, body_pos, &next_match,
541				  &match_marg, &match);
542
543		/* Put back everything up until the replacement. */
544		while (body_pos > next_match)
545			unput(*--body_pos);
546
547		/* Perform the replacement. */
548		if (match_marg != NULL) {
549			const char *strp;
550
551			next_match = match_marg->replacement_text;
552			strp = next_match + strlen(next_match);
553			while (strp > next_match)
554				unput(*--strp);
555
556			/* Skip past the unexpanded macro arg. */
557			body_pos -= match.rm_eo - match.rm_so;
558		}
559	}
560
561	/* Cleanup replacement text. */
562	STAILQ_FOREACH(marg, &macro_symbol->info.macroinfo->args, links) {
563		free(marg->replacement_text);
564	}
565}
566
567/*
568 * Find the next substitution in the macro working backwards from
569 * body_pos until the beginning of the macro buffer.  next_match
570 * should be initialized to the beginning of the macro buffer prior
571 * to calling this routine.
572 */
573static void
574next_substitution(struct symbol *mac_symbol, const char *body_pos,
575		  const char **next_match, struct macro_arg **match_marg,
576		  regmatch_t *match)
577{
578	regmatch_t	  matches[2];
579	struct macro_arg *marg;
580	const char	 *search_pos;
581	int		  retval;
582
583	do {
584		search_pos = *next_match;
585
586		STAILQ_FOREACH(marg, &mac_symbol->info.macroinfo->args, links) {
587
588			retval = regexec(&marg->arg_regex, search_pos, 2,
589					 matches, 0);
590			if (retval == 0
591			 && (matches[1].rm_eo + search_pos) <= body_pos
592			 && (matches[1].rm_eo + search_pos) > *next_match) {
593				*match = matches[1];
594				*next_match = match->rm_eo + search_pos;
595				*match_marg = marg;
596			}
597		}
598	} while (search_pos != *next_match);
599}
600
601int
602yywrap()
603{
604	include_t *include;
605
606	yy_delete_buffer(YY_CURRENT_BUFFER);
607	(void)fclose(yyin);
608	if (yyfilename != NULL)
609		free(yyfilename);
610	yyfilename = NULL;
611	include = include_stack.slh_first;
612	if (include != NULL) {
613		yy_switch_to_buffer(include->buffer);
614		yylineno = include->lineno;
615		yyfilename = include->filename;
616		SLIST_REMOVE_HEAD(&include_stack, links);
617		free(include);
618		return (0);
619	}
620	return (1);
621}
~/ Read-only file preview.