Back to home page

OSCL-LXR

 
 

    


0001 %{
0002 /*
0003  * Lexical Analyzer for the Aic7xxx SCSI Host adapter sequencer assembler.
0004  *
0005  * Copyright (c) 1997, 1998, 2000 Justin T. Gibbs.
0006  * Copyright (c) 2001, 2002 Adaptec Inc.
0007  * All rights reserved.
0008  *
0009  * Redistribution and use in source and binary forms, with or without
0010  * modification, are permitted provided that the following conditions
0011  * are met:
0012  * 1. Redistributions of source code must retain the above copyright
0013  *    notice, this list of conditions, and the following disclaimer,
0014  *    without modification.
0015  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
0016  *    substantially similar to the "NO WARRANTY" disclaimer below
0017  *    ("Disclaimer") and any redistribution must be conditioned upon
0018  *    including a substantially similar Disclaimer requirement for further
0019  *    binary redistribution.
0020  * 3. Neither the names of the above-listed copyright holders nor the names
0021  *    of any contributors may be used to endorse or promote products derived
0022  *    from this software without specific prior written permission.
0023  *
0024  * Alternatively, this software may be distributed under the terms of the
0025  * GNU General Public License ("GPL") version 2 as published by the Free
0026  * Software Foundation.
0027  *
0028  * NO WARRANTY
0029  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
0030  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
0031  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
0032  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
0033  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
0034  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
0035  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
0036  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
0037  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
0038  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0039  * POSSIBILITY OF SUCH DAMAGES.
0040  *
0041  * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_scan.l#20 $
0042  *
0043  * $FreeBSD$
0044  */
0045 
0046 #include <sys/types.h>
0047 
0048 #include <inttypes.h>
0049 #include <limits.h>
0050 #include <regex.h>
0051 #include <stdio.h>
0052 #include <string.h>
0053 #include <sysexits.h>
0054 #include "../queue.h"
0055 
0056 #include "aicasm.h"
0057 #include "aicasm_symbol.h"
0058 #include "aicasm_gram.h"
0059 
0060 /* This is used for macro body capture too, so err on the large size. */
0061 #define MAX_STR_CONST 4096
0062 static char string_buf[MAX_STR_CONST];
0063 static char *string_buf_ptr;
0064 static int  parren_count;
0065 static int  quote_count;
0066 static char buf[255];
0067 %}
0068 
0069 PATH            ([/]*[-A-Za-z0-9_.])+
0070 WORD            [A-Za-z_][-A-Za-z_0-9]*
0071 SPACE           [ \t]+
0072 MCARG           [^(), \t]+
0073 MBODY           ((\\[^\n])*[^\n\\]*)+
0074 
0075 %x COMMENT
0076 %x CEXPR
0077 %x INCLUDE
0078 %x STRING
0079 %x MACRODEF
0080 %x MACROARGLIST
0081 %x MACROCALLARGS
0082 %x MACROBODY
0083 
0084 %%
0085 \n                      { ++yylineno; }
0086 \r                      ;
0087 "/*"                    { BEGIN COMMENT;  /* Enter comment eating state */ }
0088 <COMMENT>"/*"           { fprintf(stderr, "Warning! Comment within comment."); }
0089 <COMMENT>\n             { ++yylineno; }
0090 <COMMENT>[^*/\n]*       ;
0091 <COMMENT>"*"+[^*/\n]*   ;
0092 <COMMENT>"/"+[^*/\n]*   ;
0093 <COMMENT>"*"+"/"        { BEGIN INITIAL; }
0094 if[ \t]*\(              {
0095                                 string_buf_ptr = string_buf;
0096                                 parren_count = 1;
0097                                 BEGIN CEXPR;
0098                                 return T_IF;
0099                         }
0100 <CEXPR>\(               {       *string_buf_ptr++ = '('; parren_count++; }
0101 <CEXPR>\)               {
0102                                 parren_count--;
0103                                 if (parren_count == 0) {
0104                                         /* All done */
0105                                         BEGIN INITIAL;
0106                                         *string_buf_ptr = '\0';
0107                                         yylval.sym = symtable_get(string_buf);
0108                                         return T_CEXPR;
0109                                 } else {
0110                                         *string_buf_ptr++ = ')';
0111                                 }
0112                         }
0113 <CEXPR>\n               { ++yylineno; }
0114 <CEXPR>\r               ;
0115 <CEXPR>[^()\n]+ {
0116                                 char *yptr;
0117 
0118                                 yptr = yytext;
0119                                 while (*yptr != '\0') {
0120                                         /* Remove duplicate spaces */
0121                                         if (*yptr == '\t')
0122                                                 *yptr = ' ';
0123                                         if (*yptr == ' '
0124                                          && string_buf_ptr != string_buf
0125                                          && string_buf_ptr[-1] == ' ')
0126                                                 yptr++;
0127                                         else 
0128                                                 *string_buf_ptr++ = *yptr++;
0129                                 }
0130                         }
0131 else                    { return T_ELSE; }
0132 VERSION                 { return T_VERSION; }
0133 PREFIX                  { return T_PREFIX; }
0134 PATCH_ARG_LIST          { return T_PATCH_ARG_LIST; }
0135 \"                      {
0136                                 string_buf_ptr = string_buf;
0137                                 BEGIN STRING;
0138                         }
0139 <STRING>[^"]+           {
0140                                 char *yptr;
0141 
0142                                 yptr = yytext;
0143                                 while (*yptr)
0144                                         *string_buf_ptr++ = *yptr++;
0145                         }
0146 <STRING>\"              {
0147                                 /* All done */
0148                                 BEGIN INITIAL;
0149                                 *string_buf_ptr = '\0';
0150                                 yylval.str = string_buf;
0151                                 return T_STRING;
0152                         }
0153 {SPACE}                  ;
0154 
0155         /* Register/SCB/SRAM definition keywords */
0156 export                  { return T_EXPORT; }
0157 register                { return T_REGISTER; }
0158 const                   { yylval.value = FALSE; return T_CONST; }
0159 download                { return T_DOWNLOAD; }
0160 address                 { return T_ADDRESS; }
0161 count                   { return T_COUNT; }
0162 access_mode             { return T_ACCESS_MODE; }
0163 dont_generate_debug_code { return T_DONT_GENERATE_DEBUG_CODE; }
0164 modes                   { return T_MODES; }
0165 RW|RO|WO                {
0166                                  if (strcmp(yytext, "RW") == 0)
0167                                         yylval.value = RW;
0168                                  else if (strcmp(yytext, "RO") == 0)
0169                                         yylval.value = RO;
0170                                  else
0171                                         yylval.value = WO;
0172                                  return T_MODE;
0173                         }
0174 field                   { return T_FIELD; }
0175 enum                    { return T_ENUM; }
0176 mask                    { return T_MASK; }
0177 alias                   { return T_ALIAS; }
0178 size                    { return T_SIZE; }
0179 scb                     { return T_SCB; }
0180 scratch_ram             { return T_SRAM; }
0181 accumulator             { return T_ACCUM; }
0182 mode_pointer            { return T_MODE_PTR; }
0183 allones                 { return T_ALLONES; }
0184 allzeros                { return T_ALLZEROS; }
0185 none                    { return T_NONE; }
0186 sindex                  { return T_SINDEX; }
0187 A                       { return T_A; }
0188 
0189         /* Instruction Formatting */
0190 PAD_PAGE                { return T_PAD_PAGE; }
0191 BEGIN_CRITICAL          { return T_BEGIN_CS; }
0192 END_CRITICAL            { return T_END_CS; }
0193 SET_SRC_MODE            { return T_SET_SRC_MODE; }
0194 SET_DST_MODE            { return T_SET_DST_MODE; }
0195 
0196         /* Opcodes */
0197 shl                     { return T_SHL; }
0198 shr                     { return T_SHR; }
0199 ror                     { return T_ROR; }
0200 rol                     { return T_ROL; }
0201 mvi                     { return T_MVI; }
0202 mov                     { return T_MOV; }
0203 clr                     { return T_CLR; }
0204 jmp                     { return T_JMP; }
0205 jc                      { return T_JC;  }
0206 jnc                     { return T_JNC; }
0207 je                      { return T_JE;  }
0208 jne                     { return T_JNE; }
0209 jz                      { return T_JZ;  }
0210 jnz                     { return T_JNZ; }
0211 call                    { return T_CALL; }
0212 add                     { return T_ADD; }
0213 adc                     { return T_ADC; }
0214 bmov                    { return T_BMOV; }
0215 inc                     { return T_INC; }
0216 dec                     { return T_DEC; }
0217 stc                     { return T_STC; }
0218 clc                     { return T_CLC; }
0219 cmp                     { return T_CMP; }
0220 not                     { return T_NOT; }
0221 xor                     { return T_XOR; }
0222 test                    { return T_TEST;}
0223 and                     { return T_AND; }
0224 or                      { return T_OR;  }
0225 ret                     { return T_RET; }
0226 nop                     { return T_NOP; }
0227 
0228         /* ARP2 16bit extensions */
0229         /* or16                 { return T_OR16; } */
0230         /* and16                        { return T_AND16; }*/
0231         /* xor16                        { return T_XOR16; }*/
0232         /* add16                        { return T_ADD16; }*/
0233         /* adc16                        { return T_ADC16; }*/
0234         /* mvi16                        { return T_MVI16; }*/
0235         /* test16                       { return T_TEST16; }*/
0236         /* cmp16                        { return T_CMP16; }*/
0237         /* cmpxchg                      { return T_CMPXCHG; }*/
0238 
0239         /* Allowed Symbols */
0240 \<\<                    { return T_EXPR_LSHIFT; }
0241 \>\>                    { return T_EXPR_RSHIFT; }
0242 [-+,:()~|&."{};<>[\]/*!=] { return yytext[0]; }
0243 
0244         /* Number processing */
0245 0[0-7]*                 {
0246                                 yylval.value = strtol(yytext, NULL, 8);
0247                                 return T_NUMBER;
0248                         }
0249 
0250 0[xX][0-9a-fA-F]+       {
0251                                 yylval.value = strtoul(yytext + 2, NULL, 16);
0252                                 return T_NUMBER;
0253                         }
0254 
0255 [1-9][0-9]*             {
0256                                 yylval.value = strtol(yytext, NULL, 10);
0257                                 return T_NUMBER;
0258                         }
0259         /* Include Files */
0260 #include{SPACE}         {
0261                                 BEGIN INCLUDE;
0262                                 quote_count = 0;
0263                                 return T_INCLUDE;
0264                         }
0265 <INCLUDE>[<]            { return yytext[0]; }
0266 <INCLUDE>[>]            { BEGIN INITIAL; return yytext[0]; }
0267 <INCLUDE>[\"]           {
0268                                 if (quote_count != 0)
0269                                         BEGIN INITIAL;
0270                                 quote_count++;
0271                                 return yytext[0];
0272                         }
0273 <INCLUDE>{PATH}         {
0274                                 char *yptr;
0275 
0276                                 yptr = yytext;
0277                                 string_buf_ptr = string_buf;
0278                                 while (*yptr)
0279                                         *string_buf_ptr++ = *yptr++;
0280                                 yylval.str = string_buf;
0281                                 *string_buf_ptr = '\0';
0282                                 return T_PATH;
0283                         }
0284 <INCLUDE>.              { stop("Invalid include line", EX_DATAERR); }
0285 #define{SPACE}          {
0286                                 BEGIN MACRODEF;
0287                                 return T_DEFINE;
0288                         }
0289 <MACRODEF>{WORD}{SPACE} { 
0290                                 char *yptr;
0291 
0292                                 /* Strip space and return as a normal symbol */
0293                                 yptr = yytext;
0294                                 while (*yptr != ' ' && *yptr != '\t')
0295                                         yptr++;
0296                                 *yptr = '\0';
0297                                 yylval.sym = symtable_get(yytext);
0298                                 string_buf_ptr = string_buf;
0299                                 BEGIN MACROBODY;
0300                                 return T_SYMBOL;
0301                         }
0302 <MACRODEF>{WORD}\(      {
0303                                 /*
0304                                  * We store the symbol with its opening
0305                                  * parren so we can differentiate macros
0306                                  * that take args from macros with the
0307                                  * same name that do not take args as
0308                                  * is allowed in C.
0309                                  */
0310                                 BEGIN MACROARGLIST;
0311                                 yylval.sym = symtable_get(yytext);
0312                                 unput('(');
0313                                 return T_SYMBOL;
0314                         }
0315 <MACROARGLIST>{WORD}    {
0316                                 yylval.str = yytext;
0317                                 return T_ARG;
0318                         }
0319 <MACROARGLIST>{SPACE}   ;
0320 <MACROARGLIST>[(,]      {
0321                                 return yytext[0];
0322                         }
0323 <MACROARGLIST>[)]       {
0324                                 string_buf_ptr = string_buf;
0325                                 BEGIN MACROBODY;
0326                                 return ')';
0327                         }
0328 <MACROARGLIST>.         {
0329                                 snprintf(buf, sizeof(buf), "Invalid character "
0330                                          "'%c' in macro argument list",
0331                                          yytext[0]);
0332                                 stop(buf, EX_DATAERR);
0333                         }
0334 <MACROCALLARGS>{SPACE}  ;
0335 <MACROCALLARGS>\(       {
0336                                 parren_count++;
0337                                 if (parren_count == 1)
0338                                         return ('(');
0339                                 *string_buf_ptr++ = '(';
0340                         }
0341 <MACROCALLARGS>\)       {
0342                                 parren_count--;
0343                                 if (parren_count == 0) {
0344                                         BEGIN INITIAL;
0345                                         return (')');
0346                                 }
0347                                 *string_buf_ptr++ = ')';
0348                         }
0349 <MACROCALLARGS>{MCARG}  {
0350                                 char *yptr;
0351 
0352                                 yptr = yytext;
0353                                 while (*yptr)
0354                                         *string_buf_ptr++ = *yptr++;
0355                         }
0356 <MACROCALLARGS>\,       {
0357                                 if (string_buf_ptr != string_buf) {
0358                                         /*
0359                                          * Return an argument and
0360                                          * rescan this comma so we
0361                                          * can return it as well.
0362                                          */
0363                                         *string_buf_ptr = '\0';
0364                                         yylval.str = string_buf;
0365                                         string_buf_ptr = string_buf;
0366                                         unput(',');
0367                                         return T_ARG;
0368                                 }
0369                                 return ',';
0370                         }
0371 <MACROBODY>\\\n         {
0372                                 /* Eat escaped newlines. */
0373                                 ++yylineno;
0374                         }
0375 <MACROBODY>\r           ;
0376 <MACROBODY>\n           {
0377                                 /* Macros end on the first unescaped newline. */
0378                                 BEGIN INITIAL;
0379                                 *string_buf_ptr = '\0';
0380                                 yylval.str = string_buf;
0381                                 ++yylineno;
0382                                 return T_MACROBODY;
0383                         }
0384 <MACROBODY>{MBODY}      {
0385                                 char *yptr;
0386                                 char c;
0387 
0388                                 yptr = yytext;
0389                                 while (c = *yptr++) {
0390                                         /*
0391                                          * Strip carriage returns.
0392                                          */
0393                                         if (c == '\r')
0394                                                 continue;
0395                                         *string_buf_ptr++ = c;
0396                                 }
0397                         }
0398 {WORD}\(                {
0399                                 char *yptr;
0400                                 char *ycopy;
0401 
0402                                 /* May be a symbol or a macro invocation. */
0403                                 yylval.sym = symtable_get(yytext);
0404                                 if (yylval.sym->type == MACRO) {
0405                                         YY_BUFFER_STATE old_state;
0406                                         YY_BUFFER_STATE temp_state;
0407 
0408                                         ycopy = strdup(yytext);
0409                                         yptr = ycopy + yyleng;
0410                                         while (yptr > ycopy)
0411                                                 unput(*--yptr);
0412                                         old_state = YY_CURRENT_BUFFER;
0413                                         temp_state =
0414                                             yy_create_buffer(stdin,
0415                                                              YY_BUF_SIZE);
0416                                         yy_switch_to_buffer(temp_state);
0417                                         mm_switch_to_buffer(old_state);
0418                                         mmparse();
0419                                         mm_switch_to_buffer(temp_state);
0420                                         yy_switch_to_buffer(old_state);
0421                                         mm_delete_buffer(temp_state);
0422                                         expand_macro(yylval.sym);
0423                                 } else {
0424                                         if (yylval.sym->type == UNINITIALIZED) {
0425                                                 /* Try without the '(' */
0426                                                 symbol_delete(yylval.sym);
0427                                                 yytext[yyleng-1] = '\0';
0428                                                 yylval.sym =
0429                                                     symtable_get(yytext);
0430                                         }
0431                                         unput('(');
0432                                         return T_SYMBOL;
0433                                 }
0434                         }
0435 {WORD}                  {
0436                                 yylval.sym = symtable_get(yytext);
0437                                 if (yylval.sym->type == MACRO) {
0438                                         expand_macro(yylval.sym);
0439                                 } else {
0440                                         return T_SYMBOL;
0441                                 }
0442                         }
0443 .                       { 
0444                                 snprintf(buf, sizeof(buf), "Invalid character "
0445                                          "'%c'", yytext[0]);
0446                                 stop(buf, EX_DATAERR);
0447                         }
0448 %%
0449 
0450 typedef struct include {
0451         YY_BUFFER_STATE  buffer;
0452         int              lineno;
0453         char            *filename;
0454         SLIST_ENTRY(include) links;
0455 }include_t;
0456 
0457 SLIST_HEAD(, include) include_stack;
0458 
0459 void
0460 include_file(char *file_name, include_type type)
0461 {
0462         FILE *newfile;
0463         include_t *include;
0464 
0465         newfile = NULL;
0466         /* Try the current directory first */
0467         if (includes_search_curdir != 0 || type == SOURCE_FILE)
0468                 newfile = fopen(file_name, "r");
0469 
0470         if (newfile == NULL && type != SOURCE_FILE) {
0471                 path_entry_t include_dir;
0472                 for (include_dir = search_path.slh_first;
0473                      include_dir != NULL;                
0474                      include_dir = include_dir->links.sle_next) {
0475                         char fullname[PATH_MAX];
0476 
0477                         if ((include_dir->quoted_includes_only == TRUE)
0478                          && (type != QUOTED_INCLUDE))
0479                                 continue;
0480 
0481                         snprintf(fullname, sizeof(fullname),
0482                                  "%s/%s", include_dir->directory, file_name);
0483 
0484                         if ((newfile = fopen(fullname, "r")) != NULL)
0485                                 break;
0486                 }
0487         }
0488 
0489         if (newfile == NULL) {
0490                 perror(file_name);
0491                 stop("Unable to open input file", EX_SOFTWARE);
0492                 /* NOTREACHED */
0493         }
0494 
0495         if (type != SOURCE_FILE) {
0496                 include = (include_t *)malloc(sizeof(include_t));
0497                 if (include == NULL) {
0498                         stop("Unable to allocate include stack entry",
0499                              EX_SOFTWARE);
0500                         /* NOTREACHED */
0501                 }
0502                 include->buffer = YY_CURRENT_BUFFER;
0503                 include->lineno = yylineno;
0504                 include->filename = yyfilename;
0505                 SLIST_INSERT_HEAD(&include_stack, include, links);
0506         }
0507         yy_switch_to_buffer(yy_create_buffer(newfile, YY_BUF_SIZE));
0508         yylineno = 1;
0509         yyfilename = strdup(file_name);
0510 }
0511 
0512 static void next_substitution(struct symbol *mac_symbol, const char *body_pos,
0513                               const char **next_match,
0514                               struct macro_arg **match_marg, regmatch_t *match);
0515 
0516 void
0517 expand_macro(struct symbol *macro_symbol)
0518 {
0519         struct macro_arg *marg;
0520         struct macro_arg *match_marg;
0521         const char *body_head;
0522         const char *body_pos;
0523         const char *next_match;
0524 
0525         /*
0526          * Due to the nature of unput, we must work
0527          * backwards through the macro body performing
0528          * any expansions.
0529          */
0530         body_head = macro_symbol->info.macroinfo->body;
0531         body_pos = body_head + strlen(body_head);
0532         while (body_pos > body_head) {
0533                 regmatch_t match;
0534 
0535                 next_match = body_head;
0536                 match_marg = NULL;
0537                 next_substitution(macro_symbol, body_pos, &next_match,
0538                                   &match_marg, &match);
0539 
0540                 /* Put back everything up until the replacement. */
0541                 while (body_pos > next_match)
0542                         unput(*--body_pos);
0543 
0544                 /* Perform the replacement. */
0545                 if (match_marg != NULL) {
0546                         const char *strp;
0547 
0548                         next_match = match_marg->replacement_text;
0549                         strp = next_match + strlen(next_match);
0550                         while (strp > next_match)
0551                                 unput(*--strp);
0552 
0553                         /* Skip past the unexpanded macro arg. */
0554                         body_pos -= match.rm_eo - match.rm_so;
0555                 }
0556         }
0557 
0558         /* Cleanup replacement text. */
0559         STAILQ_FOREACH(marg, &macro_symbol->info.macroinfo->args, links) {
0560                 free(marg->replacement_text);
0561         }
0562 }
0563 
0564 /*
0565  * Find the next substitution in the macro working backwards from
0566  * body_pos until the beginning of the macro buffer.  next_match
0567  * should be initialized to the beginning of the macro buffer prior
0568  * to calling this routine.
0569  */
0570 static void
0571 next_substitution(struct symbol *mac_symbol, const char *body_pos,
0572                   const char **next_match, struct macro_arg **match_marg,
0573                   regmatch_t *match)
0574 {
0575         regmatch_t        matches[2];
0576         struct macro_arg *marg;
0577         const char       *search_pos;
0578         int               retval;
0579 
0580         do {
0581                 search_pos = *next_match;
0582 
0583                 STAILQ_FOREACH(marg, &mac_symbol->info.macroinfo->args, links) {
0584 
0585                         retval = regexec(&marg->arg_regex, search_pos, 2,
0586                                          matches, 0);
0587                         if (retval == 0
0588                          && (matches[1].rm_eo + search_pos) <= body_pos
0589                          && (matches[1].rm_eo + search_pos) > *next_match) {
0590                                 *match = matches[1];
0591                                 *next_match = match->rm_eo + search_pos;
0592                                 *match_marg = marg;
0593                         }
0594                 }
0595         } while (search_pos != *next_match);
0596 }
0597 
0598 int
0599 yywrap()
0600 {
0601         include_t *include;
0602 
0603         yy_delete_buffer(YY_CURRENT_BUFFER);
0604         (void)fclose(yyin);
0605         if (yyfilename != NULL)
0606                 free(yyfilename);
0607         yyfilename = NULL;
0608         include = include_stack.slh_first;
0609         if (include != NULL) {
0610                 yy_switch_to_buffer(include->buffer);
0611                 yylineno = include->lineno;
0612                 yyfilename = include->filename;
0613                 SLIST_REMOVE_HEAD(&include_stack, links);
0614                 free(include);
0615                 return (0);
0616         }
0617         return (1);
0618 }