Now that the base issue is fixed, enable -Wsign-compare again in scanners.
[dragonfly.git] / sys / dev / disk / aic7xxx / aicasm / aicasm_scan.l
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#19 $
42  *
43  * $FreeBSD: src/sys/dev/aic7xxx/aicasm/aicasm_scan.l,v 1.22 2003/12/16 23:54:07 gibbs Exp $
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 #ifdef __linux__
55 #include "../queue.h"
56 #else
57 #include <sys/queue.h>
58 #endif
59
60 #include "aicasm.h"
61 #include "aicasm_symbol.h"
62 #include "aicasm_gram.h"
63
64 /* This is used for macro body capture too, so err on the large size. */
65 #define MAX_STR_CONST 4096
66 #define YY_NO_INPUT
67 static char string_buf[MAX_STR_CONST];
68 static char *string_buf_ptr;
69 static int  parren_count;
70 static int  quote_count;
71 static char msgbuf[255];
72
73 extern int mmparse(void);
74 extern void mm_switch_to_buffer(YY_BUFFER_STATE);
75 extern void mm_delete_buffer(YY_BUFFER_STATE);
76 %}
77
78 PATH            ([/]*[-A-Za-z0-9_.])+
79 WORD            [A-Za-z_][-A-Za-z_0-9]*
80 SPACE           [ \t]+
81 MCARG           [^(), \t]+
82 MBODY           ((\\[^\n])*[^\n\\]*)+
83
84 %x COMMENT
85 %x CEXPR
86 %x INCLUDE
87 %x STRING
88 %x MACRODEF
89 %x MACROARGLIST
90 %x MACROCALLARGS
91 %x MACROBODY
92
93 %%
94 \n                      { ++yylineno; }
95 \r                      ;
96 "/*"                    { BEGIN COMMENT;  /* Enter comment eating state */ }
97 <COMMENT>"/*"           { fprintf(stderr, "Warning! Comment within comment."); }
98 <COMMENT>\n             { ++yylineno; }
99 <COMMENT>[^*/\n]*       ;
100 <COMMENT>"*"+[^*/\n]*   ;
101 <COMMENT>"/"+[^*/\n]*   ;
102 <COMMENT>"*"+"/"        { BEGIN INITIAL; }
103 if[ \t]*\(              {
104                                 string_buf_ptr = string_buf;
105                                 parren_count = 1;
106                                 BEGIN CEXPR;
107                                 return T_IF;
108                         }
109 <CEXPR>\(               {       *string_buf_ptr++ = '('; parren_count++; }
110 <CEXPR>\)               {
111                                 parren_count--;
112                                 if (parren_count == 0) {
113                                         /* All done */
114                                         BEGIN INITIAL;
115                                         *string_buf_ptr = '\0';
116                                         yylval.sym = symtable_get(string_buf);
117                                         return T_CEXPR;
118                                 } else {
119                                         *string_buf_ptr++ = ')';
120                                 }
121                         }
122 <CEXPR>\n               { ++yylineno; }
123 <CEXPR>\r               ;
124 <CEXPR>[^()\n]+ {
125                                 char *yptr;
126
127                                 yptr = yytext;
128                                 while (*yptr != '\0') {
129                                         /* Remove duplicate spaces */
130                                         if (*yptr == '\t')
131                                                 *yptr = ' ';
132                                         if (*yptr == ' '
133                                          && string_buf_ptr != string_buf
134                                          && string_buf_ptr[-1] == ' ')
135                                                 yptr++;
136                                         else 
137                                                 *string_buf_ptr++ = *yptr++;
138                                 }
139                         }
140
141 VERSION                 { return T_VERSION; }
142 PREFIX                  { return T_PREFIX; }
143 PATCH_ARG_LIST          { return T_PATCH_ARG_LIST; }
144 \"                      {
145                                 string_buf_ptr = string_buf;
146                                 BEGIN STRING;
147                         }
148 <STRING>[^"]+           {
149                                 char *yptr;
150
151                                 yptr = yytext;
152                                 while (*yptr)
153                                         *string_buf_ptr++ = *yptr++;
154                         }
155 <STRING>\"              {
156                                 /* All done */
157                                 BEGIN INITIAL;
158                                 *string_buf_ptr = '\0';
159                                 yylval.str = string_buf;
160                                 return T_STRING;
161                         }
162 {SPACE}                  ;
163
164         /* Register/SCB/SRAM definition keywords */
165 export                  { return T_EXPORT; }
166 register                { return T_REGISTER; }
167 const                   { yylval.value = FALSE; return T_CONST; }
168 download                { return T_DOWNLOAD; }
169 address                 { return T_ADDRESS; }
170 access_mode             { return T_ACCESS_MODE; }
171 modes                   { return T_MODES; }
172 RW|RO|WO                {
173                                  if (strcmp(yytext, "RW") == 0)
174                                         yylval.value = RW;
175                                  else if (strcmp(yytext, "RO") == 0)
176                                         yylval.value = RO;
177                                  else
178                                         yylval.value = WO;
179                                  return T_MODE;
180                         }
181 BEGIN_CRITICAL          { return T_BEGIN_CS; }
182 END_CRITICAL            { return T_END_CS; }
183 SET_SRC_MODE            { return T_SET_SRC_MODE; }
184 SET_DST_MODE            { return T_SET_DST_MODE; }
185 field                   { return T_FIELD; }
186 enum                    { return T_ENUM; }
187 mask                    { return T_MASK; }
188 alias                   { return T_ALIAS; }
189 size                    { return T_SIZE; }
190 scb                     { return T_SCB; }
191 scratch_ram             { return T_SRAM; }
192 accumulator             { return T_ACCUM; }
193 mode_pointer            { return T_MODE_PTR; }
194 allones                 { return T_ALLONES; }
195 allzeros                { return T_ALLZEROS; }
196 none                    { return T_NONE; }
197 sindex                  { return T_SINDEX; }
198 A                       { return T_A; }
199
200         /* Opcodes */
201 shl                     { return T_SHL; }
202 shr                     { return T_SHR; }
203 ror                     { return T_ROR; }
204 rol                     { return T_ROL; }
205 mvi                     { return T_MVI; }
206 mov                     { return T_MOV; }
207 clr                     { return T_CLR; }
208 jmp                     { return T_JMP; }
209 jc                      { return T_JC;  }
210 jnc                     { return T_JNC; }
211 je                      { return T_JE;  }
212 jne                     { return T_JNE; }
213 jz                      { return T_JZ;  }
214 jnz                     { return T_JNZ; }
215 call                    { return T_CALL; }
216 add                     { return T_ADD; }
217 adc                     { return T_ADC; }
218 bmov                    { return T_BMOV; }
219 inc                     { return T_INC; }
220 dec                     { return T_DEC; }
221 stc                     { return T_STC; }
222 clc                     { return T_CLC; }
223 cmp                     { return T_CMP; }
224 not                     { return T_NOT; }
225 xor                     { return T_XOR; }
226 test                    { return T_TEST;}
227 and                     { return T_AND; }
228 or                      { return T_OR;  }
229 ret                     { return T_RET; }
230 nop                     { return T_NOP; }
231 else                    { return T_ELSE; }
232
233         /* Allowed Symbols */
234 \<\<                    { return T_EXPR_LSHIFT; }
235 \>\>                    { return T_EXPR_RSHIFT; }
236 [-+,:()~|&."{};<>[\]/*!=] { return yytext[0]; }
237
238         /* Number processing */
239 0[0-7]*                 {
240                                 yylval.value = strtol(yytext, NULL, 8);
241                                 return T_NUMBER;
242                         }
243
244 0[xX][0-9a-fA-F]+       {
245                                 yylval.value = strtoul(yytext + 2, NULL, 16);
246                                 return T_NUMBER;
247                         }
248
249 [1-9][0-9]*             {
250                                 yylval.value = strtol(yytext, NULL, 10);
251                                 return T_NUMBER;
252                         }
253         /* Include Files */
254 #include{SPACE}         {
255                                 BEGIN INCLUDE;
256                                 quote_count = 0;
257                                 return T_INCLUDE;
258                         }
259 <INCLUDE>[<]            { return yytext[0]; }
260 <INCLUDE>[>]            { BEGIN INITIAL; return yytext[0]; }
261 <INCLUDE>[\"]           {
262                                 if (quote_count != 0)
263                                         BEGIN INITIAL;
264                                 quote_count++;
265                                 return yytext[0];
266                         }
267 <INCLUDE>{PATH}         {
268                                 char *yptr;
269
270                                 yptr = yytext;
271                                 string_buf_ptr = string_buf;
272                                 while (*yptr)
273                                         *string_buf_ptr++ = *yptr++;
274                                 yylval.str = string_buf;
275                                 *string_buf_ptr = '\0';
276                                 return T_PATH;
277                         }
278 <INCLUDE>.              { stop("Invalid include line", EX_DATAERR); }
279 #define{SPACE}          {
280                                 BEGIN MACRODEF;
281                                 return T_DEFINE;
282                         }
283 <MACRODEF>{WORD}{SPACE} { 
284                                 char *yptr;
285
286                                 /* Strip space and return as a normal symbol */
287                                 yptr = yytext;
288                                 while (*yptr != ' ' && *yptr != '\t')
289                                         yptr++;
290                                 *yptr = '\0';
291                                 yylval.sym = symtable_get(yytext);
292                                 string_buf_ptr = string_buf;
293                                 BEGIN MACROBODY;
294                                 return T_SYMBOL;
295                         }
296 <MACRODEF>{WORD}\(      {
297                                 /*
298                                  * We store the symbol with its opening
299                                  * parren so we can differentiate macros
300                                  * that take args from macros with the
301                                  * same name that do not take args as
302                                  * is allowed in C.
303                                  */
304                                 BEGIN MACROARGLIST;
305                                 yylval.sym = symtable_get(yytext);
306                                 unput('(');
307                                 return T_SYMBOL;
308                         }
309 <MACROARGLIST>{WORD}    {
310                                 yylval.str = yytext;
311                                 return T_ARG;
312                         }
313 <MACROARGLIST>{SPACE}   ;
314 <MACROARGLIST>[(,]      {
315                                 return yytext[0];
316                         }
317 <MACROARGLIST>[)]       {
318                                 string_buf_ptr = string_buf;
319                                 BEGIN MACROBODY;
320                                 return ')';
321                         }
322 <MACROARGLIST>.         {
323                                 snprintf(msgbuf, sizeof(msgbuf), "Invalid character "
324                                          "'%c' in macro argument list",
325                                          yytext[0]);
326                                 stop(msgbuf, EX_DATAERR);
327                         }
328 <MACROCALLARGS>{SPACE}  ;
329 <MACROCALLARGS>\(       {
330                                 parren_count++;
331                                 if (parren_count == 1)
332                                         return ('(');
333                                 *string_buf_ptr++ = '(';
334                         }
335 <MACROCALLARGS>\)       {
336                                 parren_count--;
337                                 if (parren_count == 0) {
338                                         BEGIN INITIAL;
339                                         return (')');
340                                 }
341                                 *string_buf_ptr++ = ')';
342                         }
343 <MACROCALLARGS>{MCARG}  {
344                                 char *yptr;
345
346                                 yptr = yytext;
347                                 while (*yptr)
348                                         *string_buf_ptr++ = *yptr++;
349                         }
350 <MACROCALLARGS>\,       {
351                                 if (string_buf_ptr != string_buf) {
352                                         /*
353                                          * Return an argument and
354                                          * rescan this comma so we
355                                          * can return it as well.
356                                          */
357                                         *string_buf_ptr = '\0';
358                                         yylval.str = string_buf;
359                                         string_buf_ptr = string_buf;
360                                         unput(',');
361                                         return T_ARG;
362                                 }
363                                 return ',';
364                         }
365 <MACROBODY>\\\n         {
366                                 /* Eat escaped newlines. */
367                                 ++yylineno;
368                         }
369 <MACROBODY>\r           ;
370 <MACROBODY>\n           {
371                                 /* Macros end on the first unescaped newline. */
372                                 BEGIN INITIAL;
373                                 *string_buf_ptr = '\0';
374                                 yylval.str = string_buf;
375                                 ++yylineno;
376                                 return T_MACROBODY;
377                         }
378 <MACROBODY>{MBODY}      {
379                                 char *yptr;
380                                 char c;
381
382                                 yptr = yytext;
383                                 while ((c = *yptr++)) {
384                                         /*
385                                          * Strip carriage returns.
386                                          */
387                                         if (c == '\r')
388                                                 continue;
389                                         *string_buf_ptr++ = c;
390                                 }
391                         }
392 {WORD}\(                {
393                                 char *yptr;
394                                 char *ycopy;
395
396                                 /* May be a symbol or a macro invocation. */
397                                 yylval.sym = symtable_get(yytext);
398                                 if (yylval.sym->type == MACRO) {
399                                         YY_BUFFER_STATE old_state;
400                                         YY_BUFFER_STATE temp_state;
401
402                                         ycopy = strdup(yytext);
403                                         yptr = ycopy + yyleng;
404                                         while (yptr > ycopy)
405                                                 unput(*--yptr);
406                                         old_state = YY_CURRENT_BUFFER;
407                                         temp_state =
408                                             yy_create_buffer(stdin,
409                                                              YY_BUF_SIZE);
410                                         yy_switch_to_buffer(temp_state);
411                                         mm_switch_to_buffer(old_state);
412                                         mmparse();
413                                         mm_switch_to_buffer(temp_state);
414                                         yy_switch_to_buffer(old_state);
415                                         mm_delete_buffer(temp_state);
416                                         expand_macro(yylval.sym);
417                                 } else {
418                                         if (yylval.sym->type == UNINITIALIZED) {
419                                                 /* Try without the '(' */
420                                                 symbol_delete(yylval.sym);
421                                                 yytext[yyleng-1] = '\0';
422                                                 yylval.sym =
423                                                     symtable_get(yytext);
424                                         }
425                                         unput('(');
426                                         return T_SYMBOL;
427                                 }
428                         }
429 {WORD}                  {
430                                 yylval.sym = symtable_get(yytext);
431                                 if (yylval.sym->type == MACRO) {
432                                         expand_macro(yylval.sym);
433                                 } else {
434                                         return T_SYMBOL;
435                                 }
436                         }
437 .                       { 
438                                 snprintf(msgbuf, sizeof(msgbuf), "Invalid character "
439                                          "'%c'", yytext[0]);
440                                 stop(msgbuf, EX_DATAERR);
441                         }
442 %%
443
444 typedef struct include {
445         YY_BUFFER_STATE  buffer;
446         int              lineno;
447         char            *filename;
448         SLIST_ENTRY(include) links;
449 }include_t;
450
451 SLIST_HEAD(, include) include_stack;
452
453 void
454 include_file(char *file_name, include_type type)
455 {
456         FILE *newfile;
457         include_t *include;
458
459         newfile = NULL;
460         /* Try the current directory first */
461         if (includes_search_curdir != 0 || type == SOURCE_FILE)
462                 newfile = fopen(file_name, "r");
463
464         if (newfile == NULL && type != SOURCE_FILE) {
465                 path_entry_t include_dir;
466                 for (include_dir = search_path.slh_first;
467                      include_dir != NULL;                
468                      include_dir = include_dir->links.sle_next) {
469                         char fullname[PATH_MAX];
470
471                         if ((include_dir->quoted_includes_only == TRUE)
472                          && (type != QUOTED_INCLUDE))
473                                 continue;
474
475                         snprintf(fullname, sizeof(fullname),
476                                  "%s/%s", include_dir->directory, file_name);
477
478                         if ((newfile = fopen(fullname, "r")) != NULL)
479                                 break;
480                 }
481         }
482
483         if (newfile == NULL) {
484                 perror(file_name);
485                 stop("Unable to open input file", EX_SOFTWARE);
486                 /* NOTREACHED */
487         }
488
489         if (type != SOURCE_FILE) {
490                 include = (include_t *)malloc(sizeof(include_t));
491                 if (include == NULL) {
492                         stop("Unable to allocate include stack entry",
493                              EX_SOFTWARE);
494                         /* NOTREACHED */
495                 }
496                 include->buffer = YY_CURRENT_BUFFER;
497                 include->lineno = yylineno;
498                 include->filename = yyfilename;
499                 SLIST_INSERT_HEAD(&include_stack, include, links);
500         }
501         yy_switch_to_buffer(yy_create_buffer(newfile, YY_BUF_SIZE));
502         yylineno = 1;
503         yyfilename = strdup(file_name);
504 }
505
506 static void next_substitution(struct symbol *mac_symbol, const char *body_pos,
507                               const char **next_match,
508                               struct macro_arg **match_marg, regmatch_t *match);
509
510 void
511 expand_macro(struct symbol *macro_symbol)
512 {
513         struct macro_arg *marg;
514         struct macro_arg *match_marg;
515         const char *body_head;
516         const char *body_pos;
517         const char *next_match;
518         regmatch_t match = { .rm_so = 0, .rm_eo = 0 };
519
520         /*
521          * Due to the nature of unput, we must work
522          * backwards through the macro body performing
523          * any expansions.
524          */
525         body_head = macro_symbol->info.macroinfo->body;
526         body_pos = body_head + strlen(body_head);
527         while (body_pos > body_head) {
528                 next_match = body_head;
529                 match_marg = NULL;
530                 next_substitution(macro_symbol, body_pos, &next_match,
531                                   &match_marg, &match);
532
533                 /* Put back everything up until the replacement. */
534                 while (body_pos > next_match)
535                         unput(*--body_pos);
536
537                 /* Perform the replacement. */
538                 if (match_marg != NULL) {
539                         const char *strp;
540
541                         next_match = match_marg->replacement_text;
542                         strp = next_match + strlen(next_match);
543                         while (strp > next_match)
544                                 unput(*--strp);
545
546                         /* Skip past the unexpanded macro arg. */
547                         body_pos -= match.rm_eo - match.rm_so;
548                 }
549         }
550
551         /* Cleanup replacement text. */
552         STAILQ_FOREACH(marg, &macro_symbol->info.macroinfo->args, links) {
553                 free(marg->replacement_text);
554         }
555 }
556
557 /*
558  * Find the next substitution in the macro working backwards from
559  * body_pos until the beginning of the macro buffer.  next_match
560  * should be initialized to the beginning of the macro buffer prior
561  * to calling this routine.
562  */
563 static void
564 next_substitution(struct symbol *mac_symbol, const char *body_pos,
565                   const char **next_match, struct macro_arg **match_marg,
566                   regmatch_t *match)
567 {
568         regmatch_t        matches[2];
569         struct macro_arg *marg;
570         const char       *search_pos;
571         int               retval;
572
573         do {
574                 search_pos = *next_match;
575
576                 STAILQ_FOREACH(marg, &mac_symbol->info.macroinfo->args, links) {
577
578                         retval = regexec(&marg->arg_regex, search_pos, 2,
579                                          matches, 0);
580                         if (retval == 0
581                          && (matches[1].rm_eo + search_pos) <= body_pos
582                          && (matches[1].rm_eo + search_pos) > *next_match) {
583                                 *match = matches[1];
584                                 *next_match = match->rm_eo + search_pos;
585                                 *match_marg = marg;
586                         }
587                 }
588         } while (search_pos != *next_match);
589 }
590
591 int
592 yywrap(void)
593 {
594         include_t *include;
595
596         yy_delete_buffer(YY_CURRENT_BUFFER);
597         (void)fclose(yyin);
598         if (yyfilename != NULL)
599                 free(yyfilename);
600         yyfilename = NULL;
601         include = include_stack.slh_first;
602         if (include != NULL) {
603                 yy_switch_to_buffer(include->buffer);
604                 yylineno = include->lineno;
605                 yyfilename = include->filename;
606                 SLIST_REMOVE_HEAD(&include_stack, links);
607                 free(include);
608                 return (0);
609         }
610         return (1);
611 }