📄 read.c
字号:
/* end-of-line. */ register int nbytes; /* 8=.quad 16=.octa ... */{ register char c; /* input_line_pointer -> c. */ register int radix; register long int length; /* Number of chars in an object. */ register int digit; /* Value of 1 digit. */ register int carry; /* For multi-precision arithmetic. */ register int work; /* For multi-precision arithmetic. */ register char * p; /* For multi-precision arithmetic. */ extern char hex_value[]; /* In hex_value.c. */ /* * The following awkward logic is to parse ZERO or more strings, * 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. */ } else { c = ','; /* Do loop. */ -- input_line_pointer; } while (c == ',') { ++ input_line_pointer; SKIP_WHITESPACE(); c = * input_line_pointer; /* C contains 1st non-blank character of what we hope is a number. */ if (c == '0') { c = * ++ input_line_pointer; if (c == 'x' || c=='X') { c = * ++ input_line_pointer; radix = 16; } else { radix = 8; } } else { radix = 10; } /* * This feature (?) is here to stop people worrying about * mysterious zero constants: which is what they get when * they completely omit digits. */ if (hex_value[c] >= radix) { as_warn( "Missing digits. 0 assumed." ); } bignum_high = bignum_low - 1; /* Start constant with 0 chars. */ for( ; (digit = hex_value [c]) < radix; c = * ++ input_line_pointer) { /* Multiply existing number by radix, then add digit. */ carry = digit; for (p=bignum_low; p <= bignum_high; p++) { work = (*p & MASK_CHAR) * radix + carry; *p = work & MASK_CHAR; carry = work >> BITS_PER_CHAR; } if (carry) { grow_bignum(); * bignum_high = carry & MASK_CHAR; know( (carry & ~ MASK_CHAR) == 0); } } length = bignum_high - bignum_low + 1; if (length > nbytes) { as_warn( "Most significant bits truncated in integer constant." ); } else { register long int leading_zeroes; for(leading_zeroes = nbytes - length; leading_zeroes; leading_zeroes --) { grow_bignum(); * bignum_high = 0; } } if (! need_pass_2) { p = frag_more (nbytes); bcopy (bignum_low, p, (int)nbytes); } /* C contains character after number. */ SKIP_WHITESPACE(); c = * input_line_pointer; /* C contains 1st non-blank character after number. */ } demand_empty_rest_of_line();} /* big_cons() */static voidgrow_bignum() /* Extend bignum by 1 char. */{ register long int length; bignum_high ++; if (bignum_high >= bignum_limit) { length = bignum_limit - bignum_low; bignum_low = xrealloc (bignum_low, length + length); bignum_high = bignum_low + length; bignum_limit = bignum_low + length + length; }} /* grow_bignum(); *//* * float_cons() * * CONStruct some more frag chars of .floats .ffloats etc. * Makes 0 or more new frags. * If need_pass_2 == TRUE, no frags are emitted. * This understands only floating literals, not expressions. Sorry. * * A floating constant is defined by atof_generic(), except it is preceded * by 0d 0f 0g or 0h. After observing the STRANGE way my BSD AS does its * reading, I decided to be incompatible. This always tries to give you * rounded bits to the precision of the pseudo-op. Former AS did premature * truncatation, restored noisy bits instead of trailing 0s AND gave you * a choice of 2 flavours of noise according to which of 2 floating-point * scanners you directed AS to use. * * In: input_line_pointer -> whitespace before, or '0' of flonum. * */void /* JF was static, but can't be if VAX.C is goning to use it */float_cons(float_type) /* Worker to do .float etc statements. */ /* Clobbers input_line-pointer, checks end-of-line. */ register float_type; /* 'f':.ffloat ... 'F':.float ... */{ register char * p; register char c; int length; /* Number of chars in an object. */ register char * err; /* Error from scanning floating literal. */ char temp [MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT]; /* * The following awkward logic is to parse ZERO or more strings, * 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; /* -> past termintor. */ } else { c = ','; /* Do loop. */ } while (c == ',') { /* input_line_pointer -> 1st char of a flonum (we hope!). */ SKIP_WHITESPACE(); /* Skip any 0{letter} that may be present. Don't even check if the * letter is legal. Someone may invent a "z" format and this routine * has no use for such information. Lusers beware: you get * diagnostics if your input is ill-conditioned. */ if(input_line_pointer[0]=='0' && isalpha(input_line_pointer[1])) input_line_pointer+=2; err = md_atof (float_type, temp, &length); know( length <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT); know( length > 0 ); if (* err) { as_warn( "Bad floating literal: %s", err); ignore_rest_of_line(); /* Input_line_pointer -> just after end-of-line. */ c = 0; /* Break out of loop. */ } else { if ( ! need_pass_2) { p = frag_more (length); bcopy (temp, p, length); } SKIP_WHITESPACE(); c = * input_line_pointer ++; /* C contains 1st non-white character after number. */ /* input_line_pointer -> just after terminator (c). */ } } -- input_line_pointer; /* -> terminator (is not ','). */ demand_empty_rest_of_line();} /* float_cons() *//* * stringer() * * We read 0 or more ',' seperated, double-quoted strings. * * Caller should have checked need_pass_2 is FALSE because we don't check it. */static voidstringer(append_zero) /* Worker to do .ascii etc statements. */ /* Checks end-of-line. */ register int append_zero; /* 0: don't append '\0', else 1 */{ /* register char * p; JF unused */ /* register int length; JF unused */ /* Length of string we read, excluding */ /* trailing '\0' implied by closing quote. */ /* register char * where; JF unused */ /* register fragS * fragP; JF unused */ register int c; /* * The following awkward logic is to parse ZERO or more strings, * comma seperated. Recall a string expression includes spaces * before the opening '\"' and spaces after the closing '\"'. * We fake a leading ',' if there is (supposed to be) * a 1st, expression. We keep demanding expressions for each * ','. */ if (is_it_end_of_statement()) { c = 0; /* Skip loop. */ ++ input_line_pointer; /* Compensate for end of loop. */ } else { c = ','; /* Do loop. */ } for ( ; c == ','; c = *input_line_pointer ++) { SKIP_WHITESPACE(); if (* input_line_pointer == '\"') { ++ input_line_pointer; /* -> 1st char of string. */ while ( (c = next_char_of_string()) >= 0) { FRAG_APPEND_1_CHAR( c ); } if (append_zero) { FRAG_APPEND_1_CHAR( 0 ); } know( input_line_pointer [-1] == '\"' ); } else { as_warn( "Expected \"-ed string" ); } SKIP_WHITESPACE(); } -- input_line_pointer; demand_empty_rest_of_line();} /* stringer() */static intnext_char_of_string (){ register int c; c = * input_line_pointer ++; switch (c) { case '\"': c = -1; break; case '\\': switch (c = * input_line_pointer ++) { case 'b': c = '\b'; break; case 'f': c = '\f'; break; case 'n': c = '\n'; break; case 'r': c = '\r'; break; case 't': c = '\t'; break; case '\\': case '"': break; /* As itself. */ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { long int number; for (number = 0; isdigit(c); c = * input_line_pointer ++) { number = number * 8 + c - '0'; } c = number; } -- input_line_pointer; break; case '\n':/* as_fatal( "Unterminated string - use app!" ); *//* To be compatible with BSD 4.2 as: give the luser a linefeed!! */ c = '\n'; break; default: as_warn( "Bad escaped character in string, '?' assumed" ); c = '?'; break; } break; default: break; } return (c);}static segTget_segmented_expression ( expP ) register expressionS * expP;{ register segT retval; if ( (retval = expression( expP )) == SEG_PASS1 || retval == SEG_NONE || retval == SEG_BIG ) { as_warn("Expected address expression: absolute 0 assumed"); retval = expP -> X_seg = SEG_ABSOLUTE; expP -> X_add_number = 0; expP -> X_add_symbol = expP -> X_subtract_symbol = 0; } return (retval); /* SEG_ ABSOLUTE,UNKNOWN,DATA,TEXT,BSS */}static segTget_known_segmented_expression ( expP ) register expressionS * expP;{ register segT retval; register char * name1; register char * name2; if ( (retval = get_segmented_expression (expP)) == SEG_UNKNOWN ) { name1 = expP -> X_add_symbol ? expP -> X_add_symbol -> sy_name : ""; name2 = expP -> X_subtract_symbol ? expP -> X_subtract_symbol -> sy_name : ""; if ( name1 && name2 ) { as_warn("Symbols \"%s\" \"%s\" are undefined: absolute 0 assumed.", name1, name2); } else { as_warn("Symbol \"%s\" undefined: absolute 0 assumed.", name1 ? name1 : name2); } retval = expP -> X_seg = SEG_ABSOLUTE; expP -> X_add_number = 0; expP -> X_add_symbol = expP -> X_subtract_symbol = NULL; } know( retval == SEG_ABSOLUTE || retval == SEG_DATA || retval == SEG_TEXT || retval == SEG_BSS || retval == SEG_DIFFERENCE ); return (retval);} /* get_known_segmented_expression() *//* static */ long int /* JF was static, but can't be if the MD pseudos are to use it */get_absolute_expression (){ expressionS exp; register segT s; if ( (s = expression(& exp)) != SEG_ABSOLUTE ) { if ( s != SEG_NONE ) { as_warn( "Bad Absolute Expression, absolute 0 assumed."); } exp . X_add_number = 0; } return (exp . X_add_number);}static char /* return terminator */get_absolute_expression_and_terminator( val_pointer) long int * val_pointer; /* return value of expression */{ * val_pointer = get_absolute_expression (); return ( * input_line_pointer ++ );}/* * demand_copy_C_string() * * Like demand_copy_string, but return NULL if the string contains any '\0's. * Give a warning if that happens. */static char *demand_copy_C_string (len_pointer) int * len_pointer;{ register char * s; if (s = demand_copy_string (len_pointer)) { register int len; for (len = * len_pointer; len > 0; len--) { if (* s == 0) { s = 0; len = 1; * len_pointer = 0; as_warn( "This string may not contain \'\\0\'" ); } } } return (s);}/* * demand_copy_string() * * Demand string, but return a safe (=private) copy of the string. * Return NULL if we can't read a string here. */static char *demand_copy_string (lenP) int * lenP;{ register int c; register int len; char * retval; len = 0; SKIP_WHITESPACE(); if (* input_line_pointer == '\"') { input_line_pointer ++; /* Skip opening quote. */ while ( (c = next_char_of_string()) >= 0 ) { obstack_1grow ( ¬es, c ); len ++; } /* JF this next line is so demand_copy_C_string will return a null termanated string. */ obstack_1grow(¬es,'\0'); retval=obstack_finish( ¬es); } else { as_warn( "Missing string" ); retval = NULL; ignore_rest_of_line (); } * lenP = len; return (retval);}/* * is_it_end_of_statement() * * In: Input_line_pointer -> next character. * * Do: Skip input_line_pointer over all whitespace. * * Out: TRUE if input_line_pointer -> end-of-line. */static intis_it_end_of_statement(){ SKIP_WHITESPACE(); return (is_end_of_line [* input_line_pointer]);}voidequals(sym_name)char *sym_name;{ register struct symbol * symbolP; /* symbol we are working with */ input_line_pointer++; if(*input_line_pointer=='=') input_line_pointer++; while(*input_line_pointer==' ' || *input_line_pointer=='\t') input_line_pointer++; if(sym_name[0]=='.' && sym_name[1]=='\0') { /* Turn '. = mumble' into a .org mumble */ register segT segment; expressionS exp; register char *p; 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]); p = frag_var (rs_org, 1, 1, (relax_substateT)0, exp.X_add_symbol, exp.X_add_number, (char *)0); * p = 0; } /* if (ok to make frag) */ } else { symbolP=symbol_find_or_make(sym_name); pseudo_set(symbolP); }}/* end: read.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -