Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/drivers/scsi/aic7xxx/aicasm/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 15 kB image not shown  

Quelle  aicasm_scan.l   Sprache: unbekannt

 
%{
/*
 * Lexical Analyzer for the Aic7xxx SCSI Host adapter sequencer assembler.
 *
 * Copyright (c) 1997, 1998, 2000 Justin T. Gibbs.
 * Copyright (c) 2001, 2002 Adaptec Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions, and the following disclaimer,
 *    without modification.
 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
 *    substantially similar to the "NO WARRANTY" disclaimer below
 *    ("Disclaimer") and any redistribution must be conditioned upon
 *    including a substantially similar Disclaimer requirement for further
 *    binary redistribution.
 * 3. Neither the names of the above-listed copyright holders nor the names
 *    of any contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * Alternatively, this software may be distributed under the terms of the
 * GNU General Public License ("GPL") version 2 as published by the Free
 * Software Foundation.
 *
 * NO WARRANTY
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * 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#20 $
 *
 * $FreeBSD$
 */

#include <sys/types.h>

#include <inttypes.h>
#include <limits.h>
#include <regex.h>
#include <stdio.h>
#include <string.h>
#include <sysexits.h>
#include "../queue.h"

#include "aicasm.h"
#include "aicasm_symbol.h"
#include "aicasm_gram.h"

/* 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];
void mm_switch_to_buffer(YY_BUFFER_STATE);
void mmparse();
void mm_delete_buffer(YY_BUFFER_STATE);
%}

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; }
\r   ;
"/*"   { BEGIN COMMENT;  /* Enter comment eating state */ }
<COMMENT>"/*"  { fprintf(stderr, "Warning! Comment within comment."); }
<COMMENT>\n  { ++yylineno; }
<COMMENT>[^*/\n]* ;
<COMMENT>"*"+[^*/\n]* ;
<COMMENT>"/"+[^*/\n]* ;
<COMMENT>"*"+"/" { BEGIN INITIAL; }
if[ \t]*\(  {
    string_buf_ptr = string_buf;
    parren_count = 1;
    BEGIN CEXPR;
    return T_IF;
   }
<CEXPR>\(  { *string_buf_ptr++ = '('; parren_count++; }
<CEXPR>\)  {
    parren_count--;
    if (parren_count == 0) {
     /* All done */
     BEGIN INITIAL;
     *string_buf_ptr = '\0';
     yylval.sym = symtable_get(string_buf);
     return T_CEXPR;
    } else {
     *string_buf_ptr++ = ')';
    }
   }
<CEXPR>\n  { ++yylineno; }
<CEXPR>\r  ;
<CEXPR>[^()\n]+ {
    char *yptr;

    yptr = yytext;
    while (*yptr != '\0') {
     /* Remove duplicate spaces */
     if (*yptr == '\t')
      *yptr = ' ';
     if (*yptr == ' '
      && string_buf_ptr != string_buf
      && string_buf_ptr[-1] == ' ')
      yptr++;
     else 
      *string_buf_ptr++ = *yptr++;
    }
   }
else   { return T_ELSE; }
VERSION   { return T_VERSION; }
PREFIX   { return T_PREFIX; }
PATCH_ARG_LIST  { return T_PATCH_ARG_LIST; }
\"   {
    string_buf_ptr = string_buf;
    BEGIN STRING;
   }
<STRING>[^"]+  {
    char *yptr;

    yptr = yytext;
    while (*yptr)
     *string_buf_ptr++ = *yptr++;
   }
<STRING>\"  {
    /* All done */
    BEGIN INITIAL;
    *string_buf_ptr = '\0';
    yylval.str = string_buf;
    return T_STRING;
   }
{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; }
count   { return T_COUNT; }
access_mode  { return T_ACCESS_MODE; }
dont_generate_debug_code { return T_DONT_GENERATE_DEBUG_CODE; }
modes   { return T_MODES; }
RW|RO|WO  {
     if (strcmp(yytext, "RW") == 0)
     yylval.value = RW;
     else if (strcmp(yytext, "RO") == 0)
     yylval.value = RO;
     else
     yylval.value = WO;
     return T_MODE;
   }
field   { return T_FIELD; }
enum   { return T_ENUM; }
mask   { return T_MASK; }
alias   { return T_ALIAS; }
size   { return T_SIZE; }
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; }
sindex   { return T_SINDEX; }
A   { return T_A; }

 /* Instruction Formatting */
PAD_PAGE  { return T_PAD_PAGE; }
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; }

 /* Opcodes */
shl   { return T_SHL; }
shr   { return T_SHR; }
ror   { return T_ROR; }
rol   { return T_ROL; }
mvi   { return T_MVI; }
mov   { return T_MOV; }
clr   { return T_CLR; }
jmp   { return T_JMP; }
jc   { return T_JC; }
jnc   { return T_JNC; }
je   { return T_JE; }
jne   { return T_JNE; }
jz   { return T_JZ; }
jnz   { return T_JNZ; }
call   { return T_CALL; }
add   { return T_ADD; }
adc   { return T_ADC; }
bmov   { return T_BMOV; }
inc   { return T_INC; }
dec   { return T_DEC; }
stc   { return T_STC; }
clc   { return T_CLC; }
cmp   { return T_CMP; }
not   { return T_NOT; }
xor   { return T_XOR; }
test   { return T_TEST;}
and   { return T_AND; }
or   { return T_OR; }
ret   { return T_RET; }
nop   { return T_NOP; }

 /* ARP2 16bit extensions */
 /* or16   { return T_OR16; } */
 /* and16   { return T_AND16; }*/
 /* xor16   { return T_XOR16; }*/
 /* add16   { return T_ADD16; }*/
 /* adc16   { return T_ADC16; }*/
 /* mvi16   { return T_MVI16; }*/
 /* test16   { return T_TEST16; }*/
 /* cmp16   { return T_CMP16; }*/
 /* cmpxchg   { return T_CMPXCHG; }*/

 /* Allowed Symbols */
\<\<   { return T_EXPR_LSHIFT; }
\>\>   { return T_EXPR_RSHIFT; }
[-+,:()~|&."{};<>[\]/*!=] { return yytext[0]; }

 /* Number processing */
0[0-7]*   {
    yylval.value = strtol(yytext, NULL, 8);
    return T_NUMBER;
   }

0[xX][0-9a-fA-F]+ {
    yylval.value = strtoul(yytext + 2, NULL, 16);
    return T_NUMBER;
   }

[1-9][0-9]*  {
    yylval.value = strtol(yytext, NULL, 10);
    return T_NUMBER;
   }
 /* Include Files */
#include{SPACE}  {
    BEGIN INCLUDE;
    quote_count = 0;
    return T_INCLUDE;
   }
<INCLUDE>[<]  { return yytext[0]; }
<INCLUDE>[>]  { BEGIN INITIAL; return yytext[0]; }
<INCLUDE>[\"]  {
    if (quote_count != 0)
     BEGIN INITIAL;
    quote_count++;
    return yytext[0];
   }
<INCLUDE>{PATH}  {
    char *yptr;

    yptr = yytext;
    string_buf_ptr = string_buf;
    while (*yptr)
     *string_buf_ptr++ = *yptr++;
    yylval.str = string_buf;
    *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;

    /* 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;

    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>\r  ;
<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;
    char c;

    yptr = yytext;
    while (c = *yptr++) {
     /*
      * Strip carriage returns.
      */
     if (c == '\r')
      continue;
     *string_buf_ptr++ = c;
    }
   }
{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);
   }
%%

typedef struct include {
        YY_BUFFER_STATE  buffer;
        int              lineno;
        char            *filename;
 SLIST_ENTRY(include) links;
}include_t;

SLIST_HEAD(, include) include_stack;

void
include_file(char *file_name, include_type type)
{
 FILE *newfile;
 include_t *include;

 newfile = NULL;
 /* Try the current directory first */
 if (includes_search_curdir != 0 || type == SOURCE_FILE)
  newfile = fopen(file_name, "r");

 if (newfile == NULL && type != SOURCE_FILE) {
                path_entry_t include_dir;
                for (include_dir = search_path.slh_first;
                     include_dir != NULL;                
                     include_dir = include_dir->links.sle_next) {
   char fullname[PATH_MAX];

   if ((include_dir->quoted_includes_only == TRUE)
    && (type != QUOTED_INCLUDE))
    continue;

   snprintf(fullname, sizeof(fullname),
     "%s/%s", include_dir->directory, file_name);

   if ((newfile = fopen(fullname, "r")) != NULL)
    break;
                }
        }

 if (newfile == NULL) {
  perror(file_name);
  stop("Unable to open input file", EX_SOFTWARE);
  /* NOTREACHED */
 }

 if (type != SOURCE_FILE) {
  include = (include_t *)malloc(sizeof(include_t));
  if (include == NULL) {
   stop("Unable to allocate include stack entry",
        EX_SOFTWARE);
   /* NOTREACHED */
  }
  include->buffer = YY_CURRENT_BUFFER;
  include->lineno = yylineno;
  include->filename = yyfilename;
  SLIST_INSERT_HEAD(&include_stack, include, links);
 }
 yy_switch_to_buffer(yy_create_buffer(newfile, YY_BUF_SIZE));
 yylineno = 1;
 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, ¯o_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()
{
 include_t *include;

 yy_delete_buffer(YY_CURRENT_BUFFER);
 (void)fclose(yyin);
 if (yyfilename != NULL)
  free(yyfilename);
 yyfilename = NULL;
 include = include_stack.slh_first;
 if (include != NULL) {
  yy_switch_to_buffer(include->buffer);
  yylineno = include->lineno;
  yyfilename = include->filename;
  SLIST_REMOVE_HEAD(&include_stack, links);
  free(include);
  return (0);
 }
 return (1);
}

[ Dauer der Verarbeitung: 0.4 Sekunden  (vorverarbeitet)  ]