patch-2.4.19 linux-2.4.19/drivers/scsi/aic7xxx/aicasm/aicasm_scan.l

Next file: linux-2.4.19/drivers/scsi/aic7xxx/aicasm/aicasm_symbol.c
Previous file: linux-2.4.19/drivers/scsi/aic7xxx/aicasm/aicasm_macro_scan.l
Back to the patch index
Back to the overall index

diff -urN linux-2.4.18/drivers/scsi/aic7xxx/aicasm/aicasm_scan.l linux-2.4.19/drivers/scsi/aic7xxx/aicasm/aicasm_scan.l
@@ -38,14 +38,15 @@
  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGES.
  *
- * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_scan.l#7 $
+ * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_scan.l#10 $
  *
- * $FreeBSD: src/sys/dev/aic7xxx/aicasm/aicasm_scan.l,v 1.13 2000/09/22 22:19:54 gibbs Exp $
+ * $FreeBSD: src/sys/dev/aic7xxx/aicasm/aicasm_scan.l,v 1.13.2.3 2001/07/28 18:46:44 gibbs Exp $
  */
 
 #include <sys/types.h>
 
 #include <limits.h>
+#include <regex.h>
 #include <stdio.h>
 #include <string.h>
 #include <sysexits.h>
@@ -57,23 +58,31 @@
 
 #include "aicasm.h"
 #include "aicasm_symbol.h"
-#include "y.tab.h"
+#include "aicasm_gram.h"
 
-#define MAX_STR_CONST 256
-char string_buf[MAX_STR_CONST];
-char *string_buf_ptr;
-int  parren_count;
-int  quote_count;
+/* This is used for macro body capture too, so err on the large size. */
+#define MAX_STR_CONST 4096
+static char string_buf[MAX_STR_CONST];
+static char *string_buf_ptr;
+static int  parren_count;
+static int  quote_count;
+static char buf[255];
 %}
 
-PATH		[-/A-Za-z0-9_.]*[./][-/A-Za-z0-9_.]*
+PATH		([/]*[-A-Za-z0-9_.])+
 WORD		[A-Za-z_][-A-Za-z_0-9]*
 SPACE		[ \t]+
+MCARG		[^(), \t]+
+MBODY		((\\[^\n])*[^\n\\]*)+
 
 %x COMMENT
 %x CEXPR
 %x INCLUDE
 %x STRING
+%x MACRODEF
+%x MACROARGLIST
+%x MACROCALLARGS
+%x MACROBODY
 
 %%
 \n			{ ++yylineno; }
@@ -122,6 +131,7 @@
 			}
 
 VERSION			{ return T_VERSION; }
+PATCH_ARG_LIST		{ return T_PATCH_ARG_LIST; }
 \"			{
 				string_buf_ptr = string_buf;
 				BEGIN STRING;
@@ -140,14 +150,16 @@
 				yylval.str = string_buf;
 				return T_STRING;
 			}
-{SPACE}			;
+{SPACE}			 ;
 
 	/* Register/SCB/SRAM definition keywords */
+export			{ return T_EXPORT; }
 register		{ return T_REGISTER; }
 const			{ yylval.value = FALSE; return T_CONST; }
 download		{ return T_DOWNLOAD; }
 address			{ return T_ADDRESS; }
 access_mode		{ return T_ACCESS_MODE; }
+modes			{ return T_MODES; }
 RW|RO|WO		{
 				 if (strcmp(yytext, "RW") == 0)
 					yylval.value = RW;
@@ -159,6 +171,8 @@
 			}
 BEGIN_CRITICAL		{ return T_BEGIN_CS; }
 END_CRITICAL		{ return T_END_CS; }
+SET_SRC_MODE		{ return T_SET_SRC_MODE; }
+SET_DST_MODE		{ return T_SET_DST_MODE; }
 bit			{ return T_BIT; }
 mask			{ return T_MASK; }
 alias			{ return T_ALIAS; }
@@ -166,6 +180,7 @@
 scb			{ return T_SCB; }
 scratch_ram		{ return T_SRAM; }
 accumulator		{ return T_ACCUM; }
+mode_pointer		{ return T_MODE_PTR; }
 allones			{ return T_ALLONES; }
 allzeros		{ return T_ALLZEROS; }
 none			{ return T_NONE; }
@@ -206,7 +221,9 @@
 else			{ return T_ELSE; }
 
 	/* Allowed Symbols */
-[-+,:()~|&."{};<>[\]!=]	{ return yytext[0]; }
+\<\<			{ return T_EXPR_LSHIFT; }
+\>\>			{ return T_EXPR_RSHIFT; }
+[-+,:()~|&."{};<>[\]/*!=] { return yytext[0]; }
 
 	/* Number processing */
 0[0-7]*			{
@@ -223,7 +240,6 @@
 				yylval.value = strtol(yytext, NULL, 10);
 				return T_NUMBER;
 			}
-
 	/* Include Files */
 #include{SPACE}		{
 				BEGIN INCLUDE;
@@ -238,13 +254,7 @@
 				quote_count++;
 				return yytext[0];
 			}
-<INCLUDE>.		{ stop("Invalid include line", EX_DATAERR); }
-
-	/* For parsing C include files with #define foo */
-#define			{ yylval.value = TRUE; return T_CONST; }
-	/* Throw away macros */
-#define[^\n]*[()]+[^\n]* ;
-<INITIAL,INCLUDE>{PATH}	{
+<INCLUDE>{PATH}		{
 				char *yptr;
 
 				yptr = yytext;
@@ -255,12 +265,158 @@
 				*string_buf_ptr = '\0';
 				return T_PATH;
 			}
+<INCLUDE>.		{ stop("Invalid include line", EX_DATAERR); }
+#define{SPACE}		{
+				BEGIN MACRODEF;
+				return T_DEFINE;
+			}
+<MACRODEF>{WORD}{SPACE}	{ 
+				char *yptr;
 
-{WORD}			{ yylval.sym = symtable_get(yytext);  return T_SYMBOL; }
+				/* Strip space and return as a normal symbol */
+				yptr = yytext;
+				while (*yptr != ' ' && *yptr != '\t')
+					yptr++;
+				*yptr = '\0';
+				yylval.sym = symtable_get(yytext);
+				string_buf_ptr = string_buf;
+				BEGIN MACROBODY;
+				return T_SYMBOL;
+			}
+<MACRODEF>{WORD}\(	{
+				/*
+				 * We store the symbol with its opening
+				 * parren so we can differentiate macros
+				 * that take args from macros with the
+				 * same name that do not take args as
+				 * is allowed in C.
+				 */
+				BEGIN MACROARGLIST;
+				yylval.sym = symtable_get(yytext);
+				unput('(');
+				return T_SYMBOL;
+			}
+<MACROARGLIST>{WORD}	{
+				yylval.str = yytext;
+				return T_ARG;
+			}
+<MACROARGLIST>{SPACE}   ;
+<MACROARGLIST>[(,]	{
+				return yytext[0];
+			}
+<MACROARGLIST>[)]	{
+				string_buf_ptr = string_buf;
+				BEGIN MACROBODY;
+				return ')';
+			}
+<MACROARGLIST>.		{
+				snprintf(buf, sizeof(buf), "Invalid character "
+					 "'%c' in macro argument list",
+					 yytext[0]);
+				stop(buf, EX_DATAERR);
+			}
+<MACROCALLARGS>{SPACE}  ;
+<MACROCALLARGS>\(	{
+				parren_count++;
+				if (parren_count == 1)
+					return ('(');
+				*string_buf_ptr++ = '(';
+			}
+<MACROCALLARGS>\)	{
+				parren_count--;
+				if (parren_count == 0) {
+					BEGIN INITIAL;
+					return (')');
+				}
+				*string_buf_ptr++ = ')';
+			}
+<MACROCALLARGS>{MCARG}	{
+				char *yptr;
 
-.			{ 
-				char buf[255];
+				yptr = yytext;
+				while (*yptr)
+					*string_buf_ptr++ = *yptr++;
+			}
+<MACROCALLARGS>\,	{
+				if (string_buf_ptr != string_buf) {
+					/*
+					 * Return an argument and
+					 * rescan this comma so we
+					 * can return it as well.
+					 */
+					*string_buf_ptr = '\0';
+					yylval.str = string_buf;
+					string_buf_ptr = string_buf;
+					unput(',');
+					return T_ARG;
+				}
+				return ',';
+			}
+<MACROBODY>\\\n		{
+				/* Eat escaped newlines. */
+				++yylineno;
+			}
+<MACROBODY>\n		{
+				/* Macros end on the first unescaped newline. */
+				BEGIN INITIAL;
+				*string_buf_ptr = '\0';
+				yylval.str = string_buf;
+				++yylineno;
+				return T_MACROBODY;
+			}
+<MACROBODY>{MBODY}	{
+				char *yptr;
 
+				yptr = yytext;
+				while (*yptr)
+					*string_buf_ptr++ = *yptr++;
+			}
+{WORD}\(		{
+				char *yptr;
+				char *ycopy;
+
+				/* May be a symbol or a macro invocation. */
+				yylval.sym = symtable_get(yytext);
+				if (yylval.sym->type == MACRO) {
+					YY_BUFFER_STATE old_state;
+					YY_BUFFER_STATE temp_state;
+
+					ycopy = strdup(yytext);
+					yptr = ycopy + yyleng;
+					while (yptr > ycopy)
+						unput(*--yptr);
+					old_state = YY_CURRENT_BUFFER;
+					temp_state =
+					    yy_create_buffer(stdin,
+							     YY_BUF_SIZE);
+					yy_switch_to_buffer(temp_state);
+					mm_switch_to_buffer(old_state);
+					mmparse();
+					mm_switch_to_buffer(temp_state);
+					yy_switch_to_buffer(old_state);
+					mm_delete_buffer(temp_state);
+					expand_macro(yylval.sym);
+				} else {
+					if (yylval.sym->type == UNINITIALIZED) {
+						/* Try without the '(' */
+						symbol_delete(yylval.sym);
+						yytext[yyleng-1] = '\0';
+						yylval.sym =
+						    symtable_get(yytext);
+					}
+					unput('(');
+					return T_SYMBOL;
+				}
+			}
+{WORD}			{
+				yylval.sym = symtable_get(yytext);
+				if (yylval.sym->type == MACRO) {
+					expand_macro(yylval.sym);
+				} else {
+					return T_SYMBOL;
+				}
+			}
+.			{ 
 				snprintf(buf, sizeof(buf), "Invalid character "
 					 "'%c'", yytext[0]);
 				stop(buf, EX_DATAERR);
@@ -329,6 +485,92 @@
 	yyfilename = strdup(file_name);
 }
 
+static void next_substitution(struct symbol *mac_symbol, const char *body_pos,
+			      const char **next_match,
+			      struct macro_arg **match_marg, regmatch_t *match);
+
+void
+expand_macro(struct symbol *macro_symbol)
+{
+	struct macro_arg *marg;
+	struct macro_arg *match_marg;
+	const char *body_head;
+	const char *body_pos;
+	const char *next_match;
+
+	/*
+	 * Due to the nature of unput, we must work
+	 * backwards through the macro body performing
+	 * any expansions.
+	 */
+	body_head = macro_symbol->info.macroinfo->body;
+	body_pos = body_head + strlen(body_head);
+	while (body_pos > body_head) {
+		regmatch_t match;
+
+		next_match = body_head;
+		match_marg = NULL;
+		next_substitution(macro_symbol, body_pos, &next_match,
+				  &match_marg, &match);
+
+		/* Put back everything up until the replacement. */
+		while (body_pos > next_match)
+			unput(*--body_pos);
+
+		/* Perform the replacement. */
+		if (match_marg != NULL) {
+			const char *strp;
+
+			next_match = match_marg->replacement_text;
+			strp = next_match + strlen(next_match);
+			while (strp > next_match)
+				unput(*--strp);
+
+			/* Skip past the unexpanded macro arg. */
+			body_pos -= match.rm_eo - match.rm_so;
+		}
+	}
+
+	/* Cleanup replacement text. */
+	STAILQ_FOREACH(marg, &macro_symbol->info.macroinfo->args, links) {
+		free(marg->replacement_text);
+	}
+}
+
+/*
+ * Find the next substitution in the macro working backwards from
+ * body_pos until the beginning of the macro buffer.  next_match
+ * should be initialized to the beginning of the macro buffer prior
+ * to calling this routine.
+ */
+static void
+next_substitution(struct symbol *mac_symbol, const char *body_pos,
+		  const char **next_match, struct macro_arg **match_marg,
+		  regmatch_t *match)
+{
+	regmatch_t	  matches[2];
+	struct macro_arg *marg;
+	const char	 *search_pos;
+	int		  retval;
+
+	do {
+		search_pos = *next_match;
+
+		STAILQ_FOREACH(marg, &mac_symbol->info.macroinfo->args, links) {
+
+			retval = regexec(&marg->arg_regex, search_pos, 2,
+					 matches, 0);
+			if (retval == 0
+			 && (matches[1].rm_eo + search_pos) <= body_pos
+			 && (matches[1].rm_eo + search_pos) > *next_match) {
+				*match = matches[1];
+				*next_match = match->rm_eo + search_pos;
+				*match_marg = marg;
+			}
+		}
+	} while (search_pos != *next_match);
+}
+
 int
 yywrap()
 {

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)