📄 read.c
字号:
} input_line_pointer ++; *end_name = 0; if(name[0]=='.' && name[1]=='\0') { /* Turn '. = mumble' into a .org mumble */ register segT segment; expressionS exp; register char *ptr; segment = get_known_segmented_expression(& exp); if ( ! need_pass_2 ) { if (segment != now_seg && segment != SEG_ABSOLUTE) as_warn("Illegal segment \"%s\". Segment \"%s\" assumed.", seg_name [(int) segment], seg_name [(int) now_seg]); ptr = frag_var (rs_org, 1, 1, (relax_substateT)0, exp.X_add_symbol, exp.X_add_number, (char *)0); *ptr= 0; } /* if (ok to make frag) */ *end_name = delim; return; } symbolP = symbol_find_or_make (name); *end_name = delim; pseudo_set (symbolP); demand_empty_rest_of_line ();}voids_space(){ long int temp_repeat; register long int temp_fill; register char *p; /* Just like .fill, but temp_size = 1 */ if ( get_absolute_expression_and_terminator( & temp_repeat) == ',' ) { temp_fill = get_absolute_expression (); } else { input_line_pointer --; /* Backup over what was not a ','. */ temp_fill = 0; } if ( temp_repeat <= 0 ) { as_warn("Repeat < 0, .space ignored"); ignore_rest_of_line(); return; } if ( ! need_pass_2 ) { p = frag_var (rs_fill, 1, 1, (relax_substateT)0, (symbolS *)0, temp_repeat, (char *)0); * p = temp_fill; } demand_empty_rest_of_line();}voids_text(){ register int temp; temp = get_absolute_expression (); subseg_new (SEG_TEXT, (subsegT)temp); demand_empty_rest_of_line();}/*( JF was static, but can't be if machine dependent pseudo-ops are to use it */voiddemand_empty_rest_of_line(){ SKIP_WHITESPACE(); if ( is_end_of_line [* input_line_pointer] ) { input_line_pointer ++; } else { ignore_rest_of_line(); } /* Return having already swallowed end-of-line. */} /* Return pointing just after end-of-line. */voidignore_rest_of_line() /* For suspect lines: gives warning. */{ if ( ! is_end_of_line [* input_line_pointer]) { as_warn("Rest of line ignored. 1st junk character valued %d (%c)." , * input_line_pointer, *input_line_pointer); while ( input_line_pointer < buffer_limit && ! is_end_of_line [* input_line_pointer] ) { input_line_pointer ++; } } input_line_pointer ++; /* Return pointing just after end-of-line. */ know( is_end_of_line [input_line_pointer [-1]] );}/* * stab() * * Handle .stabX directives, which used to be open-coded. * So much creeping featurism overloaded the semantics that we decided * to put all .stabX thinking in one place. Here. * * We try to make any .stabX directive legal. Other people's AS will often * do assembly-time consistency checks: eg assigning meaning to n_type bits * and "protecting" you from setting them to certain values. (They also zero * certain bits before emitting symbols. Tut tut.) * * If an expression is not absolute we either gripe or use the relocation * information. Other people's assemblers silently forget information they * don't need and invent information they need that you didn't supply. * * .stabX directives always make a symbol table entry. It may be junk if * the rest of your .stabX directive is malformed. */static voidstab (what)int what;{ register symbolS * symbolP; register char * string; int saved_type; int length; int goof; /* TRUE if we have aborted. */ long int longint;/* * Enter with input_line_pointer pointing past .stabX and any following * whitespace. */ goof = FALSE; /* JF who forgot this?? */ if (what == 's') { string = demand_copy_C_string (& length); SKIP_WHITESPACE(); if (* input_line_pointer == ',') input_line_pointer ++; else { as_warn( "I need a comma after symbol's name" ); goof = TRUE; } } else string = "";/* * Input_line_pointer->after ','. String -> symbol name. */ if (! goof) { symbolP = symbol_new (string, 0,0,0,0,(struct frag *)0); switch (what) { case 'd': symbolP->sy_name = NULL; /* .stabd feature. */ symbolP->sy_value = obstack_next_free(& frags) - frag_now->fr_literal; symbolP->sy_frag = frag_now; break; case 'n': symbolP->sy_frag = &zero_address_frag; break; case 's': symbolP->sy_frag = & zero_address_frag; break; default: BAD_CASE( what ); break; } if (get_absolute_expression_and_terminator (& longint) == ',') symbolP->sy_type = saved_type = longint; else { as_warn( "I want a comma after the n_type expression" ); goof = TRUE; input_line_pointer --; /* Backup over a non-',' char. */ } } if (! goof) { if (get_absolute_expression_and_terminator (& longint) == ',') symbolP->sy_other = longint; else { as_warn( "I want a comma after the n_other expression" ); goof = TRUE; input_line_pointer --; /* Backup over a non-',' char. */ } } if (! goof) { symbolP->sy_desc = get_absolute_expression (); if (what == 's' || what == 'n') { if (* input_line_pointer != ',') { as_warn( "I want a comma after the n_desc expression" ); goof = TRUE; } else { input_line_pointer ++; } } } if ((! goof) && (what=='s' || what=='n')) { pseudo_set (symbolP); symbolP->sy_type = saved_type; } if (goof) ignore_rest_of_line (); else demand_empty_rest_of_line ();}/* * pseudo_set() * * In: Pointer to a symbol. * Input_line_pointer -> expression. * * Out: Input_line_pointer -> just after any whitespace after expression. * Tried to set symbol to value of expression. * Will change sy_type, sy_value, sy_frag; * May set need_pass_2 == TRUE. */static voidpseudo_set (symbolP) symbolS * symbolP;{ expressionS exp; register segT segment; int ext; know( symbolP ); /* NULL pointer is logic error. */ ext=(symbolP->sy_type&N_EXT); if ((segment = expression( & exp )) == SEG_NONE) { as_warn( "Missing expression: absolute 0 assumed" ); exp . X_seg = SEG_ABSOLUTE; exp . X_add_number = 0; } switch (segment) { case SEG_BIG: as_warn( "%s number illegal. Absolute 0 assumed.", exp . X_add_number > 0 ? "Bignum" : "Floating-Point" ); symbolP -> sy_type = N_ABS | ext; symbolP -> sy_value = 0; symbolP -> sy_frag = & zero_address_frag; break; case SEG_NONE: as_warn("No expression: Using absolute 0"); symbolP -> sy_type = N_ABS | ext; symbolP -> sy_value = 0; symbolP -> sy_frag = & zero_address_frag; break; case SEG_DIFFERENCE: if (exp.X_add_symbol && exp.X_subtract_symbol && (exp.X_add_symbol->sy_type & N_TYPE) == (exp.X_subtract_symbol->sy_type & N_TYPE)) { if(exp.X_add_symbol->sy_frag != exp.X_subtract_symbol->sy_frag) { as_bad("Unknown expression: symbols %s and %s are in different frags.",exp.X_add_symbol->sy_name, exp.X_subtract_symbol->sy_name); need_pass_2++; } exp.X_add_number+=exp.X_add_symbol->sy_value - exp.X_subtract_symbol->sy_value; } else as_warn( "Complex expression. Absolute segment assumed." ); case SEG_ABSOLUTE: symbolP -> sy_type = N_ABS | ext; symbolP -> sy_value = exp . X_add_number; symbolP -> sy_frag = & zero_address_frag; break; case SEG_DATA: case SEG_TEXT: case SEG_BSS: symbolP -> sy_type = seg_N_TYPE [(int) segment] | ext; symbolP -> sy_value= exp . X_add_number + exp . X_add_symbol -> sy_value; symbolP -> sy_frag = exp . X_add_symbol -> sy_frag; break; case SEG_PASS1: /* Not an error. Just try another pass. */ symbolP->sy_forward=exp.X_add_symbol; as_warn("Unknown expression"); know( need_pass_2 == TRUE ); break; case SEG_UNKNOWN: symbolP->sy_forward=exp.X_add_symbol; /* as_warn("unknown symbol"); */ /* need_pass_2 = TRUE; */ break; default: BAD_CASE( segment ); break; }}/* * stabs(file), stabf(func) and stabd(line) -- for the purpose of * source file debugging of assembly files, generate file, * function and line number stabs, respectively. * These functions have corresponding functions named * filestab(), funcstab() and linestab() in input-scrub.c, * where logical files and logical line numbers are handled. */#include <stab.h>stabs(file) char *file;{ /* .stabs "file",100,0,0,. */ (void) symbol_new(file, N_SO, 0, 0, obstack_next_free(& frags) - frag_now->fr_literal, frag_now);}stabf(func) char *func;{ symbolS *symbolP; static int void_undefined = 1; /* crudely filter uninteresting labels: require an initial '_' */ if (*func++ != '_') return; /* assembly functions are assumed to have void type */ if (void_undefined) { /* .stabs "void:t15=15",128,0,0,0 */ (void) symbol_new("void:t1=1", N_LSYM, 0, 0, 0, &zero_address_frag); void_undefined = 0; } /* .stabs "func:F1",36,0,0,. */ symbolP = symbol_new((char *) 0, N_FUN, 0, 0, obstack_next_free(& frags) - frag_now->fr_literal, frag_now); obstack_grow(¬es, func, strlen(func)); obstack_1grow(¬es, ':'); obstack_1grow(¬es, 'F'); obstack_1grow(¬es, '1'); obstack_1grow(¬es, '\0'); symbolP->sy_name = obstack_finish(¬es);}stabd(line) unsigned line;{ /* .stabd 68,0,line */ (void) symbol_new((char *)0, N_SLINE, 0, line, obstack_next_free(& frags) - frag_now->fr_literal, frag_now);}/* * cons() * * CONStruct more frag of .bytes, or .words etc. * Should need_pass_2 be TRUE then emit no frag(s). * This understands EXPRESSIONS, as opposed to big_cons(). * * Bug (?) * * This has a split personality. We use expression() to read the * value. We can detect if the value won't fit in a byte or word. * But we can't detect if expression() discarded significant digits * in the case of a long. Not worth the crocks required to fix it. */voidcons(nbytes) /* worker to do .byte etc statements */ /* clobbers input_line_pointer, checks */ /* end-of-line. */ register int nbytes; /* 1=.byte, 2=.word, 4=.long */{ register char c; register long int mask; /* High-order bits we will left-truncate, */ /* but includes sign bit also. */ register long int get; /* what we get */ register long int use; /* get after truncation. */ register long int unmask; /* what bits we will store */ register char * p; register segT segment; expressionS exp;#ifdef NS32K void fix_new_ns32k();#else void fix_new();#endif /* * Input_line_pointer -> 1st char after pseudo-op-code and could legally * be a end-of-line. (Or, less legally an eof - which we cope with.) */ /* JF << of >= number of bits in the object is undefined. In particular SPARC (Sun 4) has problems */ if(nbytes>=sizeof(long int)) mask = 0; else mask = ~0 << (BITS_PER_CHAR * nbytes); /* Don't store these bits. */ unmask = ~ mask; /* Do store these bits. */#ifdef NEVER "Do this mod if you want every overflow check to assume SIGNED 2's complement data."; mask = ~ (unmask >> 1); /* Includes sign bit now. */#endif /* * The following awkward logic is to parse ZERO or more expressions, * comma seperated. Recall an expression includes its leading & * trailing blanks. We fake a leading ',' if there is (supposed to * be) a 1st expression, and keep demanding 1 expression for each ','. */ if (is_it_end_of_statement()) { c = 0; /* Skip loop. */ input_line_pointer ++; /* Matches end-of-loop 'correction'. */ } else c = ','; /* Do loop. */ while ( c == ',' ) { segment = expression( &exp ); /* At least scan over the expression. */ if ( ! need_pass_2 ) { /* Still worthwhile making frags. */ /* Don't call this if we are going to junk this pass anyway! */ know( segment != SEG_PASS1 ); if ( segment == SEG_DIFFERENCE && exp . X_add_symbol == NULL ) { as_warn( "Subtracting symbol \"%s\"(segment\"%s\") is too hard. Absolute segment assumed.", exp . X_subtract_symbol -> sy_name, seg_name [(int) N_TYPE_seg [exp . X_subtract_symbol -> sy_type & N_TYPE]]); segment = SEG_ABSOLUTE; /* Leave exp . X_add_number alone. */ } p = frag_more (nbytes); switch (segment) { case SEG_BIG: as_warn( "%s number illegal. Absolute 0 assumed.", exp . X_add_number > 0 ? "Bignum" : "Floating-Point"); md_number_to_chars (p, (long)0, nbytes); break; case SEG_NONE: as_warn( "0 assumed for missing expression" ); exp . X_add_number = 0; know( exp . X_add_symbol == NULL ); /* fall into SEG_ABSOLUTE */ case SEG_ABSOLUTE: get = exp . X_add_number; use = get & unmask; if ( (get & mask) && (get & mask) != mask ) { /* Leading bits contain both 0s & 1s. */ as_warn("Value x%x truncated to x%x.", get, use); } md_number_to_chars (p, use, nbytes); /* put bytes in right order. */ break; case SEG_DIFFERENCE:#ifndef WORKING_DOT_WORD if(nbytes==2) { struct broken_word *x; x=(struct broken_word *)xmalloc(sizeof(struct broken_word)); x->next_broken_word=broken_words; broken_words=x; x->frag=frag_now; x->word_goes_here=p; x->dispfrag=0; x->add=exp.X_add_symbol; x->sub=exp.X_subtract_symbol; x->addnum=exp.X_add_number; x->added=0; new_broken_words++; break; } /* Else Fall through into. . . */#endif case SEG_BSS: case SEG_UNKNOWN: case SEG_TEXT: case SEG_DATA:#if defined(SPARC) || defined(I860) fix_new (frag_now, p - frag_now -> fr_literal, nbytes, exp . X_add_symbol, exp . X_subtract_symbol, exp . X_add_number, 0, RELOC_32);#endif#ifdef NS32K fix_new_ns32k (frag_now, p - frag_now -> fr_literal, nbytes, exp . X_add_symbol, exp . X_subtract_symbol, exp . X_add_number, 0, 0, 2, 0, 0);#endif#if !defined(SPARC) && !defined(NS32K) && !defined(I860) fix_new (frag_now, p - frag_now -> fr_literal, nbytes, exp . X_add_symbol, exp . X_subtract_symbol, exp . X_add_number, 0);#endif break; default: BAD_CASE( segment ); break; } /* switch(segment) */ } /* if(!need_pass_2) */ c = * input_line_pointer ++; } /* while(c==',') */ input_line_pointer --; /* Put terminator back into stream. */ demand_empty_rest_of_line();} /* cons() *//* * big_cons() * * CONStruct more frag(s) of .quads, or .octa etc. * Makes 0 or more new frags. * If need_pass_2 == TRUE, generate no frag. * This understands only bignums, not expressions. Cons() understands * expressions. * * Constants recognised are '0...'(octal) '0x...'(hex) '...'(decimal). * * This creates objects with struct obstack_control objs, destroying * any context objs held about a partially completed object. Beware! * * * I think it sucks to have 2 different types of integers, with 2 * routines to read them, store them etc. * It would be nicer to permit bignums in expressions and only * complain if the result overflowed. However, due to "efficiency"... */voidbig_cons(nbytes) /* worker to do .quad etc statements */ /* clobbers input_line_pointer, checks */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -