📄 read.c
字号:
/* read.c - read a source file - Copyright 1986, 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.This file is part of GAS, the GNU Assembler.GAS is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, or (at your option)any later version.GAS is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GAS; see the file COPYING. If not, write to the FreeSoftware Foundation, 59 Temple Place - Suite 330, Boston, MA02111-1307, USA. */#if 0/* If your chars aren't 8 bits, you will change this a bit. But then, GNU isn't spozed to run on your machine anyway. (RMS is so shortsighted sometimes.) */#define MASK_CHAR (0xFF)#else#define MASK_CHAR ((int)(unsigned char) -1)#endif/* This is the largest known floating point format (for now). It will grow when we do 4361 style flonums. */#define MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT (16)/* Routines that read assembler source text to build spagetti in memory. Another group of these functions is in the expr.c module. *//* For isdigit (). */#include <ctype.h>#include "as.h"#include "subsegs.h"#include "sb.h"#include "macro.h"#include "obstack.h"#include "listing.h"#include "ecoff.h"#ifndef TC_START_LABEL#define TC_START_LABEL(x,y) (x==':')#endif/* Set by the object-format or the target. */#ifndef TC_IMPLICIT_LCOMM_ALIGNMENT#define TC_IMPLICIT_LCOMM_ALIGNMENT(SIZE, P2VAR) \ do \ { \ if ((SIZE) >= 8) \ (P2VAR) = 3; \ else if ((SIZE) >= 4) \ (P2VAR) = 2; \ else if ((SIZE) >= 2) \ (P2VAR) = 1; \ else \ (P2VAR) = 0; \ } \ while (0)#endifchar *input_line_pointer; /*->next char of source file to parse. */#if BITS_PER_CHAR != 8/* The following table is indexed by[(char)] and will break if a char does not have exactly 256 states (hopefully 0:255!)! */die horribly;#endif#ifndef LEX_AT/* The m88k unfortunately uses @ as a label beginner. */#define LEX_AT 0#endif#ifndef LEX_BR/* The RS/6000 assembler uses {,},[,] as parts of symbol names. */#define LEX_BR 0#endif#ifndef LEX_PCT/* The Delta 68k assembler permits % inside label names. */#define LEX_PCT 0#endif#ifndef LEX_QM/* The PowerPC Windows NT assemblers permits ? inside label names. */#define LEX_QM 0#endif#ifndef LEX_HASH/* The IA-64 assembler uses # as a suffix designating a symbol. We include it in the symbol and strip it out in tc_canonicalize_symbol_name. */#define LEX_HASH 0#endif#ifndef LEX_DOLLAR/* The a29k assembler does not permits labels to start with $. */#define LEX_DOLLAR 3#endif#ifndef LEX_TILDE/* The Delta 68k assembler permits ~ at start of label names. */#define LEX_TILDE 0#endif/* Used by is_... macros. our ctype[]. */char lex_type[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* @ABCDEFGHIJKLMNO */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* PQRSTUVWXYZ[\]^_ */ 0, 0, 0, LEX_HASH, LEX_DOLLAR, LEX_PCT, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, /* _!"#$%&'()*+,-./ */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, LEX_QM, /* 0123456789:;<=>? */ LEX_AT, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* @ABCDEFGHIJKLMNO */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, LEX_BR, 0, LEX_BR, 0, 3, /* PQRSTUVWXYZ[\]^_ */ 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* `abcdefghijklmno */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, LEX_BR, 0, LEX_BR, LEX_TILDE, 0, /* pqrstuvwxyz{|}~. */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3};/* In: a character. Out: 1 if this character ends a line. */char is_end_of_line[256] = {#ifdef CR_EOL 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, /* @abcdefghijklmno */#else 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* @abcdefghijklmno */#endif 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* _!"#$%&'()*+,-./ */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0123456789:;<=>? */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* */};#ifdef IGNORE_OPCODE_CASEchar original_case_string[128];#endif/* Functions private to this file. */static char *buffer; /* 1st char of each buffer of lines is here. */static char *buffer_limit; /*->1 + last char in buffer. *//* TARGET_BYTES_BIG_ENDIAN is required to be defined to either 0 or 1 in the tc-<CPU>.h file. See the "Porting GAS" section of the internals manual. */int target_big_endian = TARGET_BYTES_BIG_ENDIAN;static char *old_buffer; /* JF a hack. */static char *old_input;static char *old_limit;/* Variables for handling include file directory table. *//* Table of pointers to directories to search for .include's. */char **include_dirs;/* How many are in the table. */int include_dir_count;/* Length of longest in table. */int include_dir_maxlen = 1;#ifndef WORKING_DOT_WORDstruct broken_word *broken_words;int new_broken_words;#endif/* The current offset into the absolute section. We don't try to build frags in the absolute section, since no data can be stored there. We just keep track of the current offset. */addressT abs_section_offset;/* If this line had an MRI style label, it is stored in this variable. This is used by some of the MRI pseudo-ops. */symbolS *line_label;/* This global variable is used to support MRI common sections. We translate such sections into a common symbol. This variable is non-NULL when we are in an MRI common section. */symbolS *mri_common_symbol;/* In MRI mode, after a dc.b pseudo-op with an odd number of bytes, we need to align to an even byte boundary unless the next pseudo-op is dc.b, ds.b, or dcb.b. This variable is set to 1 if an alignment may be needed. */static int mri_pending_align;#ifndef NO_LISTING#ifdef OBJ_ELF/* This variable is set to be non-zero if the next string we see might be the name of the source file in DWARF debugging information. See the comment in emit_expr for the format we look for. */static int dwarf_file_string;#endif#endifstatic void cons_worker PARAMS ((int, int));static int scrub_from_string PARAMS ((char *, int));static void do_align PARAMS ((int, char *, int, int));static void s_align PARAMS ((int, int));static void s_lcomm_internal PARAMS ((int, int));static int hex_float PARAMS ((int, char *));static inline int sizeof_sleb128 PARAMS ((offsetT));static inline int sizeof_uleb128 PARAMS ((valueT));static inline int output_sleb128 PARAMS ((char *, offsetT));static inline int output_uleb128 PARAMS ((char *, valueT));static inline int output_big_sleb128 PARAMS ((char *, LITTLENUM_TYPE *, int));static inline int output_big_uleb128 PARAMS ((char *, LITTLENUM_TYPE *, int));static int output_big_leb128 PARAMS ((char *, LITTLENUM_TYPE *, int, int));static void do_org PARAMS ((segT, expressionS *, int));char *demand_copy_string PARAMS ((int *lenP));static segT get_segmented_expression PARAMS ((expressionS *expP));static segT get_known_segmented_expression PARAMS ((expressionS * expP));static void pobegin PARAMS ((void));static int get_line_sb PARAMS ((sb *));static void generate_file_debug PARAMS ((void));voidread_begin (){ const char *p; pobegin (); obj_read_begin_hook (); /* Something close -- but not too close -- to a multiple of 1024. The debugging malloc I'm using has 24 bytes of overhead. */ obstack_begin (¬es, chunksize); obstack_begin (&cond_obstack, chunksize); /* Use machine dependent syntax. */ for (p = line_separator_chars; *p; p++) is_end_of_line[(unsigned char) *p] = 1; /* Use more. FIXME-SOMEDAY. */ if (flag_mri) lex_type['?'] = 3;}/* Set up pseudo-op tables. */static struct hash_control *po_hash;static const pseudo_typeS potable[] = { {"abort", s_abort, 0}, {"align", s_align_ptwo, 0}, {"ascii", stringer, 0}, {"asciz", stringer, 1}, {"balign", s_align_bytes, 0}, {"balignw", s_align_bytes, -2}, {"balignl", s_align_bytes, -4},/* block */ {"byte", cons, 1}, {"comm", s_comm, 0}, {"common", s_mri_common, 0}, {"common.s", s_mri_common, 1}, {"data", s_data, 0}, {"dc", cons, 2}, {"dc.b", cons, 1}, {"dc.d", float_cons, 'd'}, {"dc.l", cons, 4}, {"dc.s", float_cons, 'f'}, {"dc.w", cons, 2}, {"dc.x", float_cons, 'x'}, {"dcb", s_space, 2}, {"dcb.b", s_space, 1}, {"dcb.d", s_float_space, 'd'}, {"dcb.l", s_space, 4}, {"dcb.s", s_float_space, 'f'}, {"dcb.w", s_space, 2}, {"dcb.x", s_float_space, 'x'}, {"ds", s_space, 2}, {"ds.b", s_space, 1}, {"ds.d", s_space, 8}, {"ds.l", s_space, 4}, {"ds.p", s_space, 12}, {"ds.s", s_space, 4}, {"ds.w", s_space, 2}, {"ds.x", s_space, 12}, {"debug", s_ignore, 0},#ifdef S_SET_DESC {"desc", s_desc, 0},#endif/* dim */ {"double", float_cons, 'd'},/* dsect */ {"eject", listing_eject, 0}, /* Formfeed listing. */ {"else", s_else, 0}, {"elsec", s_else, 0}, {"elseif", s_elseif, (int) O_ne}, {"end", s_end, 0}, {"endc", s_endif, 0}, {"endfunc", s_func, 1}, {"endif", s_endif, 0},/* endef */ {"equ", s_set, 0}, {"equiv", s_set, 1}, {"err", s_err, 0}, {"exitm", s_mexit, 0},/* extend */ {"extern", s_ignore, 0}, /* We treat all undef as ext. */ {"appfile", s_app_file, 1}, {"appline", s_app_line, 0}, {"fail", s_fail, 0}, {"file", s_app_file, 0}, {"fill", s_fill, 0}, {"float", float_cons, 'f'}, {"format", s_ignore, 0}, {"func", s_func, 0}, {"global", s_globl, 0}, {"globl", s_globl, 0}, {"hword", cons, 2}, {"if", s_if, (int) O_ne}, {"ifc", s_ifc, 0}, {"ifdef", s_ifdef, 0}, {"ifeq", s_if, (int) O_eq}, {"ifeqs", s_ifeqs, 0}, {"ifge", s_if, (int) O_ge}, {"ifgt", s_if, (int) O_gt}, {"ifle", s_if, (int) O_le}, {"iflt", s_if, (int) O_lt}, {"ifnc", s_ifc, 1}, {"ifndef", s_ifdef, 1}, {"ifne", s_if, (int) O_ne}, {"ifnes", s_ifeqs, 1}, {"ifnotdef", s_ifdef, 1}, {"include", s_include, 0}, {"int", cons, 4}, {"irp", s_irp, 0}, {"irep", s_irp, 0}, {"irpc", s_irp, 1}, {"irepc", s_irp, 1}, {"lcomm", s_lcomm, 0}, {"lflags", listing_flags, 0}, /* Listing flags. */ {"linkonce", s_linkonce, 0}, {"list", listing_list, 1}, /* Turn listing on. */ {"llen", listing_psize, 1}, {"long", cons, 4}, {"lsym", s_lsym, 0}, {"macro", s_macro, 0}, {"mexit", s_mexit, 0}, {"mri", s_mri, 0}, {".mri", s_mri, 0}, /* Special case so .mri works in MRI mode. */ {"name", s_ignore, 0}, {"noformat", s_ignore, 0}, {"nolist", listing_list, 0}, /* Turn listing off. */ {"nopage", listing_nopage, 0}, {"octa", cons, 16}, {"offset", s_struct, 0}, {"org", s_org, 0}, {"p2align", s_align_ptwo, 0}, {"p2alignw", s_align_ptwo, -2}, {"p2alignl", s_align_ptwo, -4}, {"page", listing_eject, 0}, {"plen", listing_psize, 0}, {"print", s_print, 0}, {"psize", listing_psize, 0}, /* Set paper size. */ {"purgem", s_purgem, 0}, {"quad", cons, 8}, {"rep", s_rept, 0}, {"rept", s_rept, 0}, {"rva", s_rva, 4}, {"sbttl", listing_title, 1}, /* Subtitle of listing. *//* scl *//* sect */ {"set", s_set, 0}, {"short", cons, 2}, {"single", float_cons, 'f'},/* size */ {"space", s_space, 0}, {"skip", s_space, 0}, {"sleb128", s_leb128, 1}, {"spc", s_ignore, 0}, {"stabd", s_stab, 'd'}, {"stabn", s_stab, 'n'}, {"stabs", s_stab, 's'}, {"string", stringer, 1}, {"struct", s_struct, 0},/* tag */ {"text", s_text, 0}, /* This is for gcc to use. It's only just been added (2/94), so gcc won't be able to use it for a while -- probably a year or more. But once this has been released, check with gcc maintainers before deleting it or even changing the spelling. */ {"this_GCC_requires_the_GNU_assembler", s_ignore, 0}, /* If we're folding case -- done for some targets, not necessarily all -- the above string in an input file will be converted to this one. Match it either way... */ {"this_gcc_requires_the_gnu_assembler", s_ignore, 0}, {"title", listing_title, 0}, /* Listing title. */ {"ttl", listing_title, 0},/* type */ {"uleb128", s_leb128, 0},/* use *//* val */ {"xcom", s_comm, 0}, {"xdef", s_globl, 0}, {"xref", s_ignore, 0}, {"xstabs", s_xstab, 's'}, {"word", cons, 2}, {"zero", s_space, 0}, {NULL, NULL, 0} /* End sentinel. */};static int pop_override_ok = 0;static const char *pop_table_name;voidpop_insert (table) const pseudo_typeS *table;{ const char *errtxt; const pseudo_typeS *pop; for (pop = table; pop->poc_name; pop++) { errtxt = hash_insert (po_hash, pop->poc_name, (char *) pop); if (errtxt && (!pop_override_ok || strcmp (errtxt, "exists"))) as_fatal (_("error constructing %s pseudo-op table: %s"), pop_table_name, errtxt); }}#ifndef md_pop_insert#define md_pop_insert() pop_insert(md_pseudo_table)#endif#ifndef obj_pop_insert#define obj_pop_insert() pop_insert(obj_pseudo_table)#endifstatic voidpobegin (){ po_hash = hash_new (); /* Do the target-specific pseudo ops. */ pop_table_name = "md"; md_pop_insert (); /* Now object specific. Skip any that were in the target table. */ pop_table_name = "obj"; pop_override_ok = 1; obj_pop_insert (); /* Now portable ones. Skip any that we've seen already. */ pop_table_name = "standard"; pop_insert (potable);}#define HANDLE_CONDITIONAL_ASSEMBLY() \ if (ignore_input ()) \ { \ while (!is_end_of_line[(unsigned char) *input_line_pointer++]) \ if (input_line_pointer == buffer_limit) \ break; \ continue; \ }/* This function is used when scrubbing the characters between #APP and #NO_APP. */static char *scrub_string;static char *scrub_string_end;static intscrub_from_string (buf, buflen) char *buf; int buflen;{ int copy; copy = scrub_string_end - scrub_string; if (copy > buflen) copy = buflen; memcpy (buf, scrub_string, copy); scrub_string += copy; return copy;}/* We read the file, putting things into a web that represents what we have been reading. */voidread_a_source_file (name) char *name;{ register char c; register char *s; /* String of symbol, '\0' appended. */ register int temp; pseudo_typeS *pop;#ifdef WARN_COMMENTS found_comment = 0;#endif buffer = input_scrub_new_file (name); listing_file (name); listing_newline (NULL); register_dependency (name); /* Generate debugging information before we've read anything in to denote
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -