gasp.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 3,135 行 · 第 1/5 页
C
3,135 行
/* gasp.c - Gnu assembler preprocessor main program. Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. Written by Steve and Judy Chamberlain of Cygnus Support, sac@cygnus.com This file is part of GASP, the GNU Assembler Preprocessor. GASP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GASP is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GASP; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *//*This program translates the input macros and stuff into a formsuitable for gas to consume. gasp [-sdhau] [-c char] [-o <outfile>] <infile>* -s copy source to output -c <char> comments are started with <char> instead of ! -u allow unreasonable stuff -p print line numbers -d print debugging stats -s semi colons start comments -a use alternate syntax Pseudo ops can start with or without a . Labels have to be in first column. -I specify include dir Macro arg parameters subsituted by name, don't need the &. String can start with ' too. Strings can be surrounded by <..> A %<exp> in a string evaluates the expression Literal char in a string with !*/#include "config.h"#include "bin-bugs.h"#include <stdio.h>#include <string.h>#include <getopt.h>#include <ctype.h>#ifdef HAVE_STDLIB_H#include <stdlib.h>#endif#ifdef NEED_MALLOC_DECLARATIONextern char *malloc ();#endif#include "ansidecl.h"#include "libiberty.h"#include "sb.h"#include "macro.h"#include "asintl.h"char *program_version = "1.2";/* This is normally declared in as.h, but we don't include that. We need the function because other files linked with gasp.c might call it. */extern void as_abort PARAMS ((const char *, int, const char *));/* The default obstack chunk size. If we set this to zero, the obstack code will use whatever will fit in a 4096 byte block. This is used by the hash table code used by macro.c. */int chunksize = 0;#define MAX_INCLUDES 30 /* Maximum include depth. */#define MAX_REASONABLE 1000 /* Maximum number of expansions. */int unreasonable; /* -u on command line. */int stats; /* -d on command line. */int print_line_number; /* -p flag on command line. */int copysource; /* -c flag on command line. */int warnings; /* Number of WARNINGs generated so far. */int errors; /* Number of ERRORs generated so far. */int fatals; /* Number of fatal ERRORs generated so far (either 0 or 1). */int alternate = 0; /* -a on command line. */int mri = 0; /* -M on command line. */char comment_char = '!';int radix = 10; /* Default radix. */int had_end; /* Seen .END. *//* The output stream. */FILE *outfile;/* The attributes of each character are stored as a bit pattern chartype, which gives us quick tests. */#define FIRSTBIT 1#define NEXTBIT 2#define SEPBIT 4#define WHITEBIT 8#define COMMENTBIT 16#define BASEBIT 32#define ISCOMMENTCHAR(x) (chartype[(unsigned char)(x)] & COMMENTBIT)#define ISFIRSTCHAR(x) (chartype[(unsigned char)(x)] & FIRSTBIT)#define ISNEXTCHAR(x) (chartype[(unsigned char)(x)] & NEXTBIT)#define ISSEP(x) (chartype[(unsigned char)(x)] & SEPBIT)#define ISWHITE(x) (chartype[(unsigned char)(x)] & WHITEBIT)#define ISBASE(x) (chartype[(unsigned char)(x)] & BASEBIT)static char chartype[256];/* Conditional assembly uses the `ifstack'. Each aif pushes another entry onto the stack, and sets the on flag if it should. The aelse sets hadelse, and toggles on. An aend pops a level. We limit to 100 levels of nesting, not because we're facists pigs with read only minds, but because more than 100 levels of nesting is probably a bug in the user's macro structure. */#define IFNESTING 100struct { int on; /* Is the level being output. */ int hadelse; /* Has an aelse been seen. */} ifstack[IFNESTING];int ifi;/* The final and intermediate results of expression evaluation are kept in exp_t's. Note that a symbol is not an sb, but a pointer into the input line. It must be coped somewhere safe before the next line is read in. */typedef struct { char *name; int len;} symbol;typedef struct { int value; /* Constant part. */ symbol add_symbol; /* Name part. */ symbol sub_symbol; /* Name part. */} exp_t;/* Hashing is done in a pretty standard way. A hash_table has a pointer to a vector of pointers to hash_entrys, and the size of the vector. A hash_entry contains a union of all the info we like to store in hash table. If there is a hash collision, hash_entries with the same hash are kept in a chain. *//* What the data in a hash_entry means. */typedef enum { hash_integer, /* Name->integer mapping. */ hash_string, /* Name->string mapping. */ hash_macro, /* Name is a macro. */ hash_formal /* Name is a formal argument. */} hash_type;typedef struct hs { sb key; /* Symbol name. */ hash_type type; /* Symbol meaning. */ union { sb s; int i; struct macro_struct *m; struct formal_struct *f; } value; struct hs *next; /* Next hash_entry with same hash key. */} hash_entry;typedef struct { hash_entry **table; int size;} hash_table;/* How we nest files and expand macros etc. We keep a stack of of include_stack structs. Each include file pushes a new level onto the stack. We keep an sb with a pushback too. unget chars are pushed onto the pushback sb, getchars first checks the pushback sb before reading from the input stream. Small things are expanded by adding the text of the item onto the pushback sb. Larger items are grown by pushing a new level and allocating the entire pushback buf for the item. Each time something like a macro is expanded, the stack index is changed. We can then perform an exitm by popping all entries off the stack with the same stack index. If we're being reasonable, we can detect recusive expansion by checking the index is reasonably small. */typedef enum { include_file, include_repeat, include_while, include_macro} include_type;struct include_stack { sb pushback; /* Current pushback stream. */ int pushback_index; /* Next char to read from stream. */ FILE *handle; /* Open file. */ sb name; /* Name of file. */ int linecount; /* Number of lines read so far. */ include_type type; int index; /* Index of this layer. */} include_stack[MAX_INCLUDES];struct include_stack *sp;#define isp (sp - include_stack)/* Include file list. */typedef struct include_path { struct include_path *next; sb path;} include_path;include_path *paths_head;include_path *paths_tail;static void quit PARAMS ((void));static void hash_new_table PARAMS ((int, hash_table *));static int hash PARAMS ((sb *));static hash_entry *hash_create PARAMS ((hash_table *, sb *));static void hash_add_to_string_table PARAMS ((hash_table *, sb *, sb *, int));static void hash_add_to_int_table PARAMS ((hash_table *, sb *, int));static hash_entry *hash_lookup PARAMS ((hash_table *, sb *));static void checkconst PARAMS ((int, exp_t *));static int sb_strtol PARAMS ((int, sb *, int, int *));static int level_0 PARAMS ((int, sb *, exp_t *));static int level_1 PARAMS ((int, sb *, exp_t *));static int level_2 PARAMS ((int, sb *, exp_t *));static int level_3 PARAMS ((int, sb *, exp_t *));static int level_4 PARAMS ((int, sb *, exp_t *));static int level_5 PARAMS ((int, sb *, exp_t *));static int exp_parse PARAMS ((int, sb *, exp_t *));static void exp_string PARAMS ((exp_t *, sb *));static int exp_get_abs PARAMS ((const char *, int, sb *, int *));#if 0static void strip_comments PARAMS ((sb *));#endifstatic void unget PARAMS ((int));static void include_buf PARAMS ((sb *, sb *, include_type, int));static void include_print_where_line PARAMS ((FILE *));static void include_print_line PARAMS ((FILE *));static int get_line PARAMS ((sb *));static int grab_label PARAMS ((sb *, sb *));static void change_base PARAMS ((int, sb *, sb *));static void do_end PARAMS ((sb *));static void do_assign PARAMS ((int, int, sb *));static void do_radix PARAMS ((sb *));static int get_opsize PARAMS ((int, sb *, int *));static int eol PARAMS ((int, sb *));static void do_data PARAMS ((int, sb *, int));static void do_datab PARAMS ((int, sb *));static void do_align PARAMS ((int, sb *));static void do_res PARAMS ((int, sb *, int));static void do_export PARAMS ((sb *));static void do_print PARAMS ((int, sb *));static void do_heading PARAMS ((int, sb *));static void do_page PARAMS ((void));static void do_form PARAMS ((int, sb *));static int get_any_string PARAMS ((int, sb *, sb *, int, int));static int skip_openp PARAMS ((int, sb *));static int skip_closep PARAMS ((int, sb *));static int dolen PARAMS ((int, sb *, sb *));static int doinstr PARAMS ((int, sb *, sb *));static int dosubstr PARAMS ((int, sb *, sb *));static void process_assigns PARAMS ((int, sb *, sb *));static int get_and_process PARAMS ((int, sb *, sb *));static void process_file PARAMS ((void));static void free_old_entry PARAMS ((hash_entry *));static void do_assigna PARAMS ((int, sb *));static void do_assignc PARAMS ((int, sb *));static void do_reg PARAMS ((int, sb *));static int condass_lookup_name PARAMS ((sb *, int, sb *, int));static int whatcond PARAMS ((int, sb *, int *));static int istrue PARAMS ((int, sb *));static void do_aif PARAMS ((int, sb *));static void do_aelse PARAMS ((void));static void do_aendi PARAMS ((void));static int condass_on PARAMS ((void));static void do_if PARAMS ((int, sb *, int));static int get_mri_string PARAMS ((int, sb *, sb *, int));static void do_ifc PARAMS ((int, sb *, int));static void do_aendr PARAMS ((void));static void do_awhile PARAMS ((int, sb *));static void do_aendw PARAMS ((void));static void do_exitm PARAMS ((void));static void do_arepeat PARAMS ((int, sb *));static void do_endm PARAMS ((void));static void do_irp PARAMS ((int, sb *, int));static void do_local PARAMS ((int, sb *));static void do_macro PARAMS ((int, sb *));static int macro_op PARAMS ((int, sb *));static int getstring PARAMS ((int, sb *, sb *));static void do_sdata PARAMS ((int, sb *, int));static void do_sdatab PARAMS ((int, sb *));static int new_file PARAMS ((const char *));static void do_include PARAMS ((int, sb *));static void include_pop PARAMS ((void));static int get PARAMS ((void));static int linecount PARAMS ((void));static int include_next_index PARAMS ((void));static void chartype_init PARAMS ((void));static int process_pseudo_op PARAMS ((int, sb *, sb *));static void add_keyword PARAMS ((const char *, int));static void process_init PARAMS ((void));static void do_define PARAMS ((const char *));static void show_usage PARAMS ((FILE *, int));static void show_help PARAMS ((void));#define FATAL(x) \ do \ { \ include_print_where_line (stderr); \ fprintf x; \ fatals++; \ quit (); \ } \ while (0)#define ERROR(x) \ do \ { \ include_print_where_line (stderr); \ fprintf x; \ errors++; \ } \ while (0)#define WARNING(x) \ do \ { \ include_print_where_line (stderr); \ fprintf x; \ warnings++; \ } \ while (0)/* Exit the program and return the right ERROR code. */static voidquit (){ int exitcode; if (fatals + errors) exitcode = 1; else exitcode = 0; if (stats) { int i; for (i = 0; i < sb_max_power_two; i++) { fprintf (stderr, "strings size %8d : %d\n", 1 << i, string_count[i]); } } exit (exitcode);}/* Hash table maintenance. *//* Build a new hash table with size buckets and fill in the info at ptr. */static voidhash_new_table (size, ptr) int size; hash_table *ptr;{ int i; ptr->size = size; ptr->table = (hash_entry **) xmalloc (size * (sizeof (hash_entry *))); /* Fill with null-pointer, not zero-bit-pattern. */ for (i = 0; i < size; i++) ptr->table[i] = 0;}/* Calculate and return the hash value of the sb at key. */static inthash (key) sb *key;{ int k = 0x1234; int i; char *p = key->ptr; for (i = 0; i < key->len; i++) { k ^= (k << 2) ^ *p; p++; } return k & 0xf0fff;}/* Look up key in hash_table tab. If present, then return it, otherwise build a new one and fill it with hash_integer. */static hash_entry *hash_create (tab, key) hash_table *tab; sb *key;{ int k = hash (key) % tab->size; hash_entry *p; hash_entry **table = tab->table; p = table[k]; while (1) { if (!p) { hash_entry *n = (hash_entry *) xmalloc (sizeof (hash_entry)); n->next = table[k]; sb_new (&n->key); sb_add_sb (&n->key, key); table[k] = n; n->type = hash_integer; return n; } if (strncmp (table[k]->key.ptr, key->ptr, key->len) == 0) { return p; } p = p->next; }}/* Add sb name with key into hash_table tab. If replacing old value and again, then ERROR. */static voidhash_add_to_string_table (tab, key, name, again) hash_table *tab; sb *key; sb *name; int again;{ hash_entry *ptr = hash_create (tab, key); if (ptr->type == hash_integer) { sb_new (&ptr->value.s); } if (ptr->value.s.len) { if (!again) ERROR ((stderr, _("redefinition not allowed\n"))); } ptr->type = hash_string; sb_reset (&ptr->value.s); sb_add_sb (&ptr->value.s, name);}/* Add integer name to hash_table tab with sb key. */static voidhash_add_to_int_table (tab, key, name) hash_table *tab; sb *key; int name;{ hash_entry *ptr = hash_create (tab, key); ptr->value.i = name;}/* Look up sb key in hash_table tab. If found, return hash_entry result, else 0. */static hash_entry *hash_lookup (tab, key) hash_table *tab; sb *key;{ int k = hash (key) % tab->size; hash_entry **table = tab->table; hash_entry *p = table[k]; while (p) { if (p->key.len == key->len && strncmp (p->key.ptr, key->ptr, key->len) == 0) return p; p = p->next; } return 0;}/* expressions are handled in a really simple recursive decent way. each bit of the machine takes an index into an sb and a pointer to an exp_t, modifies the *exp_t and returns the index of the first character past the part of the expression parsed. expression precedence: ( ) unary + - ~ * / + - & | ~*//* Make sure that the exp_t at term is constant. If not the give the op ERROR. */static voidcheckconst (op, term) int op; exp_t *term;{ if (term->add_symbol.len || term->sub_symbol.len) { ERROR ((stderr, _("the %c operator cannot take non-absolute arguments.\n"), op)); }}/* Turn the number in string at idx into a number of base, fill in ptr, and return the index of the first character not in the number. */static intsb_strtol (idx, string, base, ptr) int idx; sb *string; int base; int *ptr;{ int value = 0; idx = sb_skip_white (idx, string); while (idx < string->len) { int ch = string->ptr[idx]; int dig = 0; if (isdigit (ch)) dig = ch - '0'; else if (ch >= 'a' && ch <= 'f') dig = ch - 'a' + 10; else if (ch >= 'A' && ch <= 'F') dig = ch - 'A' + 10; else break; if (dig >= base) break; value = value * base + dig; idx++; } *ptr = value; return idx;}static intlevel_0 (idx, string, lhs) int idx; sb *string; exp_t *lhs;{ lhs->add_symbol.len = 0; lhs->add_symbol.name = 0; lhs->sub_symbol.len = 0; lhs->sub_symbol.name = 0; idx = sb_skip_white (idx, string); lhs->value = 0; if (isdigit ((unsigned char) string->ptr[idx])) { idx = sb_strtol (idx, string, 10, &lhs->value); } else if (ISFIRSTCHAR (string->ptr[idx])) { int len = 0; lhs->add_symbol.name = string->ptr + idx; while (idx < string->len && ISNEXTCHAR (string->ptr[idx])) { idx++; len++; } lhs->add_symbol.len = len; } else if (string->ptr[idx] == '"') { sb acc; sb_new (&acc); ERROR ((stderr, _("string where expression expected.\n"))); idx = getstring (idx, string, &acc); sb_kill (&acc); } else { ERROR ((stderr, _("can't find primary in expression.\n"))); idx++; } return sb_skip_white (idx, string);}static intlevel_1 (idx, string, lhs) int idx; sb *string; exp_t *lhs;{ idx = sb_skip_white (idx, string); switch (string->ptr[idx]) { case '+': idx = level_1 (idx + 1, string, lhs); break; case '~': idx = level_1 (idx + 1, string, lhs); checkconst ('~', lhs); lhs->value = ~lhs->value; break; case '-': {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?