📄 read.c
字号:
/*- * This code is derived from software copyrighted by the Free Software * Foundation. * * Modified 1991 by Donn Seeley at UUNET Technologies, Inc. */#ifndef lintstatic char sccsid[] = "@(#)read.c 6.4 (Berkeley) 5/8/91";#endif /* not lint *//* read.c - read a source file - Copyright (C) 1986,1987 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 1, 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 tothe Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */#define MASK_CHAR (0xFF) /* 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 MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT (16) /* This is the largest known floating point */ /* format (for now). It will grow when we */ /* do 4361 style flonums. *//* Routines that read assembler source text to build spagetti in memory. *//* Another group of these functions is in the as-expr.c module */#include <ctype.h>#include <sys/types.h>#include <sys/stat.h>#include "as.h"#include "read.h"#include "md.h"#include "hash.h"#include "obstack.h"#include "frags.h"#include "flonum.h"#include "struc-symbol.h"#include "expr.h"#include "symbols.h"#ifdef SPARC#include "sparc.h"#define OTHER_ALIGN#endif#ifdef I860#include "i860.h"#endifchar * input_line_pointer; /* -> next char of source file to parse. */#if BITS_PER_CHAR != 8The following table is indexed by [ (char) ] and will break ifa char does not have exactly 256 states (hopefully 0:255!) !#endifconst char /* used by is_... macros. our ctype[] */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, 0, 3, 0, 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, 0, /* 0123456789:;<=>? */ 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, 3, 0, 0, 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, 3, 0, 0, 0, 0, /* pqrstuvwxyz{|}~. */ 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 };/* * In: a character. * Out: TRUE if this character ends a line. */#define _ (0)const char is_end_of_line [256] = { _, _, _, _, _, _, _, _, _, _,99, _, _, _, _, _, /* @abcdefghijklmno */ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ _, _, _, _, _, _, _, _, _, _, _,99, _, _, _, _, /* 0123456789:;<=>? */ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ /* */};#undef _ /* Functions private to this file. */void equals();void big_cons();void cons();static char* demand_copy_C_string();static char* demand_copy_string();void demand_empty_rest_of_line();void float_cons();long int get_absolute_expression();static char get_absolute_expression_and_terminator();static segT get_known_segmented_expression();void ignore_rest_of_line();static int is_it_end_of_statement();static void pobegin();static void pseudo_set();static void stab();static void stringer();extern char line_comment_chars[];static char * buffer_limit; /* -> 1 + last char in buffer. */static char * bignum_low; /* Lowest char of bignum. */static char * bignum_limit; /* 1st illegal address of bignum. */static char * bignum_high; /* Highest char of bignum. */ /* May point to (bignum_start-1). */ /* Never >= bignum_limit. */static char *old_buffer = 0; /* JF a hack */static char *old_input;static char *old_limit;#ifndef WORKING_DOT_WORDstruct broken_word *broken_words;int new_broken_words = 0;#endifstatic void grow_bignum ();static int next_char_of_string ();voidread_begin(){ pobegin(); obstack_begin( ¬es, 5000 );#define BIGNUM_BEGIN_SIZE (16) bignum_low = xmalloc((long)BIGNUM_BEGIN_SIZE); bignum_limit = bignum_low + BIGNUM_BEGIN_SIZE;}/* set up pseudo-op tables */static struct hash_control *po_hash = NULL; /* use before set up: NULL-> address error */void s_abort(), s_align(), s_comm(), s_data();void s_desc(), s_even(), s_file(), s_fill();void s_globl(), s_lcomm(), s_line(), s_lsym();void s_org(), s_set(), s_space(), s_text();#ifdef VMSchar const_flag = 0;void s_const();#endif#ifdef DONTDEFvoid s_gdbline(), s_gdblinetab();void s_gdbbeg(), s_gdbblock(), s_gdbend(), s_gdbsym();#endifvoid stringer();void cons();void float_cons();void big_cons();void stab();static const pseudo_typeSpotable[] ={ { "abort", s_abort, 0 }, { "align", s_align, 0 }, { "ascii", stringer, 0 }, { "asciz", stringer, 1 }, { "byte", cons, 1 }, { "comm", s_comm, 0 },#ifdef VMS { "const", s_const, 0 },#endif { "data", s_data, 0 }, { "desc", s_desc, 0 }, { "double", float_cons, 'd' }, { "file", s_file, 0 }, { "fill", s_fill, 0 }, { "float", float_cons, 'f' },#ifdef DONTDEF { "gdbbeg", s_gdbbeg, 0 }, { "gdbblock", s_gdbblock, 0 }, { "gdbend", s_gdbend, 0 }, { "gdbsym", s_gdbsym, 0 }, { "gdbline", s_gdbline, 0 }, { "gdblinetab",s_gdblinetab, 0 },#endif { "globl", s_globl, 0 }, { "int", cons, 4 }, { "lcomm", s_lcomm, 0 }, { "line", s_line, 0 }, { "long", cons, 4 }, { "lsym", s_lsym, 0 }, { "octa", big_cons, 16 }, { "org", s_org, 0 }, { "quad", big_cons, 8 }, { "set", s_set, 0 }, { "short", cons, 2 }, { "single", float_cons, 'f' }, { "space", s_space, 0 }, { "stabd", stab, 'd' }, { "stabn", stab, 'n' }, { "stabs", stab, 's' }, { "text", s_text, 0 },#ifndef SPARC { "word", cons, 2 },#endif { NULL} /* end sentinel */};static voidpobegin(){ char * errtxt; /* error text */ const pseudo_typeS * pop; po_hash = hash_new(); errtxt = ""; /* OK so far */ for (pop=potable; pop->poc_name && !*errtxt; pop++) { errtxt = hash_insert (po_hash, pop->poc_name, (char *)pop); } for(pop=md_pseudo_table; pop->poc_name && !*errtxt; pop++) errtxt = hash_insert (po_hash, pop->poc_name, (char *)pop); if (*errtxt) { as_fatal ("error constructing pseudo-op table"); }} /* pobegin() *//* read_a_source_file() * * File has already been opened, and will be closed by our caller. * * We read the file, putting things into a web that * represents what we have been reading. */voidread_a_source_file (buffer) char * buffer; /* 1st character of each buffer of lines is here. */{ register char c; register char * s; /* string of symbol, '\0' appended */ register int temp; /* register struct frag * fragP; JF unused */ /* a frag we just made */ pseudo_typeS *pop;#ifdef DONTDEF void gdb_block_beg(); void gdb_block_position(); void gdb_block_end(); void gdb_symbols_fixup();#endif subseg_new (SEG_TEXT, 0); while ( buffer_limit = input_scrub_next_buffer (&buffer) ) { /* We have another line to parse. */ know( buffer_limit [-1] == '\n' ); /* Must have a sentinel. */ input_line_pointer = buffer; contin: /* JF this goto is my fault I admit it. Someone brave please re-write the whole input section here? Pleeze??? */ while ( input_line_pointer < buffer_limit ) { /* We have more of this buffer to parse. */ /* * We now have input_line_pointer -> 1st char of next line. * If input_line_pointer [-1] == '\n' then we just * scanned another line: so bump line counters. */ if (input_line_pointer [-1] == '\n') { bump_line_counters (); } /* * We are at the begining of a line, or similar place. * We expect a well-formed assembler statement. * A "symbol-name:" is a statement. * * Depending on what compiler is used, the order of these tests * may vary to catch most common case 1st. * Each test is independent of all other tests at the (top) level. * PLEASE make a compiler that doesn't use this assembler. * It is crufty to waste a compiler's time encoding things for this * assembler, which then wastes more time decoding it. * (And communicating via (linear) files is silly! * If you must pass stuff, please pass a tree!) */ if ( (c= * input_line_pointer ++) == '\t' || c == ' ' || c=='\f') { c = * input_line_pointer ++; } know( c != ' ' ); /* No further leading whitespace. */ /* * C is the 1st significant character. * Input_line_pointer points after that character. */ if ( is_name_beginner(c) ) { /* want user-defined label or pseudo/opcode */ s = -- input_line_pointer; c = get_symbol_end(); /* name's delimiter */ /* * C is character after symbol. * That character's place in the input line is now '\0'. * S points to the beginning of the symbol. * [In case of pseudo-op, s -> '.'.] * Input_line_pointer -> '\0' where c was. */ if ( c == ':' ) { if (flagseen['g']) /* set line number for function definition */ funcstab(s); colon(s); /* user-defined label */ * input_line_pointer ++ = ':'; /* Put ':' back for error messages' sake. */ /* Input_line_pointer -> after ':'. */ SKIP_WHITESPACE(); } else if(c=='=' || input_line_pointer[1]=='=') /* JF deal with FOO=BAR */ { equals(s); demand_empty_rest_of_line(); } else { /* expect pseudo-op or machine instruction */ if ( *s=='.' ) { /* * PSEUDO - OP. * * WARNING: c has next char, which may be end-of-line. * We lookup the pseudo-op table with s+1 because we * already know that the pseudo-op begins with a '.'. */ pop= (pseudo_typeS *) hash_find (po_hash, s+1); /* Print the error msg now, while we still can */ if(!pop) as_bad("Unknown pseudo-op: '%s'",s); /* Put it back for error messages etc. */ * input_line_pointer = c; /* The following skip of whitespace is compulsory. */ /* A well shaped space is sometimes all that seperates keyword from operands. */ if ( c == ' ' || c == '\t' ) { /* Skip seperator after keyword. */ input_line_pointer ++; } /* * Input_line is restored. * Input_line_pointer -> 1st non-blank char * after pseudo-operation. */ if(!pop) { ignore_rest_of_line(); break; } else (*pop->poc_handler)(pop->poc_val); } else { /* machine instruction */ /* If source file debugging, emit a stab. */ if (flagseen['g']) linestab(); /* WARNING: c has char, which may be end-of-line. */ /* Also: input_line_pointer -> `\0` where c was. */ * input_line_pointer = c; while ( ! is_end_of_line [* input_line_pointer] ) { input_line_pointer ++; } c = * input_line_pointer; * input_line_pointer = '\0'; md_assemble (s); /* Assemble 1 instruction. */ * input_line_pointer ++ = c; /* We resume loop AFTER the end-of-line from this instruction */ } /* if (*s=='.') */ } /* if c==':' */ continue; } /* if (is_name_beginner(c) */ if ( is_end_of_line [c] ) { /* empty statement */ continue; } if ( isdigit(c) ) { /* local label ("4:") */ temp = c - '0';#ifdef SUN_ASM_SYNTAX if( *input_line_pointer=='$') input_line_pointer++;#endif if ( * input_line_pointer ++ == ':' ) { local_colon (temp); } else { as_bad( "Spurious digit %d.", temp); input_line_pointer -- ; ignore_rest_of_line(); } continue; } if(c && index(line_comment_chars,c)) { /* Its a comment. Better say APP or NO_APP */ char *ends; char *strstr(); char *new_buf; char *new_tmp; int new_length; char *tmp_buf = 0; extern char *scrub_string,*scrub_last_string; int scrub_from_string(); void scrub_to_string(); bump_line_counters(); s=input_line_pointer; if(strncmp(s,"APP\n",4)) continue; /* We ignore it */ s+=4; ends=strstr(s,"#NO_APP\n"); if(!ends) { int tmp_len; int num; /* The end of the #APP wasn't in this buffer. We keep reading in buffers until we find the #NO_APP that goes with this #APP There is one. The specs guarentee it. . .*/ tmp_len=buffer_limit-s; tmp_buf=xmalloc(tmp_len); bcopy(s,tmp_buf,tmp_len); do { new_tmp = input_scrub_next_buffer(&buffer); if(!new_tmp) break; else buffer_limit = new_tmp; input_line_pointer = buffer; ends = strstr(buffer,"#NO_APP\n"); if(ends) num=ends-buffer; else num=buffer_limit-buffer; tmp_buf=xrealloc(tmp_buf,tmp_len+num); bcopy(buffer,tmp_buf+tmp_len,num); tmp_len+=num; } while(!ends); input_line_pointer= ends ? ends+8 : NULL; s=tmp_buf; ends=s+tmp_len; } else { input_line_pointer=ends+8; } new_buf=xmalloc(100); new_length=100; new_tmp=new_buf; scrub_string=s; scrub_last_string = ends; for(;;) { int ch; ch=do_scrub_next_char(scrub_from_string,scrub_to_string); if(ch==EOF) break; *new_tmp++=ch; if(new_tmp==new_buf+new_length) { new_buf=xrealloc(new_buf,new_length+100); new_tmp=new_buf+new_length; new_length+=100; } } if(tmp_buf) free(tmp_buf); old_buffer=buffer; old_input=input_line_pointer; old_limit=buffer_limit; buffer=new_buf; input_line_pointer=new_buf; buffer_limit=new_tmp; continue; } as_bad("Junk character %d.",c); ignore_rest_of_line(); } /* while (input_line_pointer<buffer_limit )*/ if(old_buffer) { bump_line_counters(); if(old_input == 0) return; buffer=old_buffer; input_line_pointer=old_input; buffer_limit=old_limit; old_buffer = 0; goto contin; } } /* while (more bufrers to scan) */} /* read_a_source_file() */voids_abort(){ as_fatal(".abort detected. Abandoning ship.");}#ifdef OTHER_ALIGN
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -