1 /*- 2 * This code is derived from software copyrighted by the Free Software 3 * Foundation. 4 * 5 * Modified 1991 by Donn Seeley at UUNET Technologies, Inc. 6 */ 7 8 #ifndef lint 9 static char sccsid[] = "@(#)read.c 6.4 (Berkeley) 05/08/91"; 10 #endif /* not lint */ 11 12 /* read.c - read a source file - 13 Copyright (C) 1986,1987 Free Software Foundation, Inc. 14 15 This file is part of GAS, the GNU Assembler. 16 17 GAS is free software; you can redistribute it and/or modify 18 it under the terms of the GNU General Public License as published by 19 the Free Software Foundation; either version 1, or (at your option) 20 any later version. 21 22 GAS is distributed in the hope that it will be useful, 23 but WITHOUT ANY WARRANTY; without even the implied warranty of 24 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 GNU General Public License for more details. 26 27 You should have received a copy of the GNU General Public License 28 along with GAS; see the file COPYING. If not, write to 29 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ 30 31 #define MASK_CHAR (0xFF) /* If your chars aren't 8 bits, you will 32 change this a bit. But then, GNU isn't 33 spozed to run on your machine anyway. 34 (RMS is so shortsighted sometimes.) 35 */ 36 37 #define MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT (16) 38 /* This is the largest known floating point */ 39 /* format (for now). It will grow when we */ 40 /* do 4361 style flonums. */ 41 42 43 /* Routines that read assembler source text to build spagetti in memory. */ 44 /* Another group of these functions is in the as-expr.c module */ 45 46 #include <ctype.h> 47 #include <sys/types.h> 48 #include <sys/stat.h> 49 #include "as.h" 50 #include "read.h" 51 #include "md.h" 52 #include "hash.h" 53 #include "obstack.h" 54 #include "frags.h" 55 #include "flonum.h" 56 #include "struc-symbol.h" 57 #include "expr.h" 58 #include "symbols.h" 59 60 #ifdef SPARC 61 #include "sparc.h" 62 #define OTHER_ALIGN 63 #endif 64 #ifdef I860 65 #include "i860.h" 66 #endif 67 68 char * input_line_pointer; /* -> next char of source file to parse. */ 69 70 71 #if BITS_PER_CHAR != 8 72 The following table is indexed by [ (char) ] and will break if 73 a char does not have exactly 256 states (hopefully 0:255!) ! 74 #endif 75 76 const char /* used by is_... macros. our ctype[] */ 77 lex_type [256] = { 78 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* @ABCDEFGHIJKLMNO */ 79 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* PQRSTUVWXYZ[\]^_ */ 80 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, /* _!"#$%&'()*+,-./ */ 81 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 0123456789:;<=>? */ 82 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* @ABCDEFGHIJKLMNO */ 83 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 3, /* PQRSTUVWXYZ[\]^_ */ 84 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* `abcdefghijklmno */ 85 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, /* pqrstuvwxyz{|}~. */ 86 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 93 }; 94 95 96 /* 97 * In: a character. 98 * Out: TRUE if this character ends a line. 99 */ 100 #define _ (0) 101 const char is_end_of_line [256] = { 102 _, _, _, _, _, _, _, _, _, _,99, _, _, _, _, _, /* @abcdefghijklmno */ 103 _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ 104 _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ 105 _, _, _, _, _, _, _, _, _, _, _,99, _, _, _, _, /* 0123456789:;<=>? */ 106 _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ 107 _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ 108 _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ 109 _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ 110 _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ 111 _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ 112 _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ 113 _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ 114 _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ /* */ 115 }; 116 #undef _ 117 118 /* Functions private to this file. */ 119 void equals(); 120 void big_cons(); 121 void cons(); 122 static char* demand_copy_C_string(); 123 static char* demand_copy_string(); 124 void demand_empty_rest_of_line(); 125 void float_cons(); 126 long int get_absolute_expression(); 127 static char get_absolute_expression_and_terminator(); 128 static segT get_known_segmented_expression(); 129 void ignore_rest_of_line(); 130 static int is_it_end_of_statement(); 131 static void pobegin(); 132 static void pseudo_set(); 133 static void stab(); 134 static void stringer(); 135 136 extern char line_comment_chars[]; 137 138 static char * buffer_limit; /* -> 1 + last char in buffer. */ 139 140 static char * bignum_low; /* Lowest char of bignum. */ 141 static char * bignum_limit; /* 1st illegal address of bignum. */ 142 static char * bignum_high; /* Highest char of bignum. */ 143 /* May point to (bignum_start-1). */ 144 /* Never >= bignum_limit. */ 145 static char *old_buffer = 0; /* JF a hack */ 146 static char *old_input; 147 static char *old_limit; 148 149 #ifndef WORKING_DOT_WORD 150 struct broken_word *broken_words; 151 int new_broken_words = 0; 152 #endif 153 154 static void grow_bignum (); 155 static int next_char_of_string (); 156 157 void 158 read_begin() 159 { 160 pobegin(); 161 obstack_begin( ¬es, 5000 ); 162 #define BIGNUM_BEGIN_SIZE (16) 163 bignum_low = xmalloc((long)BIGNUM_BEGIN_SIZE); 164 bignum_limit = bignum_low + BIGNUM_BEGIN_SIZE; 165 } 166 167 /* set up pseudo-op tables */ 168 169 static struct hash_control * 170 po_hash = NULL; /* use before set up: NULL-> address error */ 171 172 173 void s_abort(), s_align(), s_comm(), s_data(); 174 void s_desc(), s_even(), s_file(), s_fill(); 175 void s_globl(), s_lcomm(), s_line(), s_lsym(); 176 void s_org(), s_set(), s_space(), s_text(); 177 #ifdef VMS 178 char const_flag = 0; 179 void s_const(); 180 #endif 181 182 #ifdef DONTDEF 183 void s_gdbline(), s_gdblinetab(); 184 void s_gdbbeg(), s_gdbblock(), s_gdbend(), s_gdbsym(); 185 #endif 186 187 void stringer(); 188 void cons(); 189 void float_cons(); 190 void big_cons(); 191 void stab(); 192 193 static const pseudo_typeS 194 potable[] = 195 { 196 { "abort", s_abort, 0 }, 197 { "align", s_align, 0 }, 198 { "ascii", stringer, 0 }, 199 { "asciz", stringer, 1 }, 200 { "byte", cons, 1 }, 201 { "comm", s_comm, 0 }, 202 #ifdef VMS 203 { "const", s_const, 0 }, 204 #endif 205 { "data", s_data, 0 }, 206 { "desc", s_desc, 0 }, 207 { "double", float_cons, 'd' }, 208 { "file", s_file, 0 }, 209 { "fill", s_fill, 0 }, 210 { "float", float_cons, 'f' }, 211 #ifdef DONTDEF 212 { "gdbbeg", s_gdbbeg, 0 }, 213 { "gdbblock", s_gdbblock, 0 }, 214 { "gdbend", s_gdbend, 0 }, 215 { "gdbsym", s_gdbsym, 0 }, 216 { "gdbline", s_gdbline, 0 }, 217 { "gdblinetab",s_gdblinetab, 0 }, 218 #endif 219 { "globl", s_globl, 0 }, 220 { "int", cons, 4 }, 221 { "lcomm", s_lcomm, 0 }, 222 { "line", s_line, 0 }, 223 { "long", cons, 4 }, 224 { "lsym", s_lsym, 0 }, 225 { "octa", big_cons, 16 }, 226 { "org", s_org, 0 }, 227 { "quad", big_cons, 8 }, 228 { "set", s_set, 0 }, 229 { "short", cons, 2 }, 230 { "single", float_cons, 'f' }, 231 { "space", s_space, 0 }, 232 { "stabd", stab, 'd' }, 233 { "stabn", stab, 'n' }, 234 { "stabs", stab, 's' }, 235 { "text", s_text, 0 }, 236 #ifndef SPARC 237 { "word", cons, 2 }, 238 #endif 239 { NULL} /* end sentinel */ 240 }; 241 242 static void 243 pobegin() 244 { 245 char * errtxt; /* error text */ 246 const pseudo_typeS * pop; 247 248 po_hash = hash_new(); 249 errtxt = ""; /* OK so far */ 250 for (pop=potable; pop->poc_name && !*errtxt; pop++) 251 { 252 errtxt = hash_insert (po_hash, pop->poc_name, (char *)pop); 253 } 254 255 for(pop=md_pseudo_table; pop->poc_name && !*errtxt; pop++) 256 errtxt = hash_insert (po_hash, pop->poc_name, (char *)pop); 257 258 if (*errtxt) 259 { 260 as_fatal ("error constructing pseudo-op table"); 261 } 262 } /* pobegin() */ 263 264 /* read_a_source_file() 265 * 266 * File has already been opened, and will be closed by our caller. 267 * 268 * We read the file, putting things into a web that 269 * represents what we have been reading. 270 */ 271 void 272 read_a_source_file (buffer) 273 char * buffer; /* 1st character of each buffer of lines is here. */ 274 { 275 register char c; 276 register char * s; /* string of symbol, '\0' appended */ 277 register int temp; 278 /* register struct frag * fragP; JF unused */ /* a frag we just made */ 279 pseudo_typeS *pop; 280 #ifdef DONTDEF 281 void gdb_block_beg(); 282 void gdb_block_position(); 283 void gdb_block_end(); 284 void gdb_symbols_fixup(); 285 #endif 286 287 subseg_new (SEG_TEXT, 0); 288 while ( buffer_limit = input_scrub_next_buffer (&buffer) ) 289 { /* We have another line to parse. */ 290 know( buffer_limit [-1] == '\n' ); /* Must have a sentinel. */ 291 input_line_pointer = buffer; 292 contin: /* JF this goto is my fault I admit it. Someone brave please re-write 293 the whole input section here? Pleeze??? */ 294 while ( input_line_pointer < buffer_limit ) 295 { /* We have more of this buffer to parse. */ 296 /* 297 * We now have input_line_pointer -> 1st char of next line. 298 * If input_line_pointer [-1] == '\n' then we just 299 * scanned another line: so bump line counters. 300 */ 301 if (input_line_pointer [-1] == '\n') 302 { 303 bump_line_counters (); 304 } 305 /* 306 * We are at the begining of a line, or similar place. 307 * We expect a well-formed assembler statement. 308 * A "symbol-name:" is a statement. 309 * 310 * Depending on what compiler is used, the order of these tests 311 * may vary to catch most common case 1st. 312 * Each test is independent of all other tests at the (top) level. 313 * PLEASE make a compiler that doesn't use this assembler. 314 * It is crufty to waste a compiler's time encoding things for this 315 * assembler, which then wastes more time decoding it. 316 * (And communicating via (linear) files is silly! 317 * If you must pass stuff, please pass a tree!) 318 */ 319 if ( (c= * input_line_pointer ++) == '\t' || c == ' ' || c=='\f') 320 { 321 c = * input_line_pointer ++; 322 } 323 know( c != ' ' ); /* No further leading whitespace. */ 324 /* 325 * C is the 1st significant character. 326 * Input_line_pointer points after that character. 327 */ 328 if ( is_name_beginner(c) ) 329 { /* want user-defined label or pseudo/opcode */ 330 s = -- input_line_pointer; 331 c = get_symbol_end(); /* name's delimiter */ 332 /* 333 * C is character after symbol. 334 * That character's place in the input line is now '\0'. 335 * S points to the beginning of the symbol. 336 * [In case of pseudo-op, s -> '.'.] 337 * Input_line_pointer -> '\0' where c was. 338 */ 339 if ( c == ':' ) 340 { 341 if (flagseen['g']) 342 /* set line number for function definition */ 343 funcstab(s); 344 colon(s); /* user-defined label */ 345 * input_line_pointer ++ = ':'; /* Put ':' back for error messages' sake. */ 346 /* Input_line_pointer -> after ':'. */ 347 SKIP_WHITESPACE(); 348 } 349 else if(c=='=' || input_line_pointer[1]=='=') /* JF deal with FOO=BAR */ 350 { 351 equals(s); 352 demand_empty_rest_of_line(); 353 } 354 else 355 { /* expect pseudo-op or machine instruction */ 356 if ( *s=='.' ) 357 { 358 /* 359 * PSEUDO - OP. 360 * 361 * WARNING: c has next char, which may be end-of-line. 362 * We lookup the pseudo-op table with s+1 because we 363 * already know that the pseudo-op begins with a '.'. 364 */ 365 366 pop= (pseudo_typeS *) hash_find (po_hash, s+1); 367 368 /* Print the error msg now, while we still can */ 369 if(!pop) 370 as_bad("Unknown pseudo-op: '%s'",s); 371 372 /* Put it back for error messages etc. */ 373 * input_line_pointer = c; 374 /* The following skip of whitespace is compulsory. */ 375 /* A well shaped space is sometimes all that seperates keyword from operands. */ 376 if ( c == ' ' || c == '\t' ) 377 { /* Skip seperator after keyword. */ 378 input_line_pointer ++; 379 } 380 /* 381 * Input_line is restored. 382 * Input_line_pointer -> 1st non-blank char 383 * after pseudo-operation. 384 */ 385 if(!pop) { 386 ignore_rest_of_line(); 387 break; 388 } 389 else 390 (*pop->poc_handler)(pop->poc_val); 391 } 392 else 393 { /* machine instruction */ 394 /* If source file debugging, emit a stab. */ 395 if (flagseen['g']) 396 linestab(); 397 398 /* WARNING: c has char, which may be end-of-line. */ 399 /* Also: input_line_pointer -> `\0` where c was. */ 400 * input_line_pointer = c; 401 while ( ! is_end_of_line [* input_line_pointer] ) 402 { 403 input_line_pointer ++; 404 } 405 c = * input_line_pointer; 406 * input_line_pointer = '\0'; 407 md_assemble (s); /* Assemble 1 instruction. */ 408 * input_line_pointer ++ = c; 409 /* We resume loop AFTER the end-of-line from this instruction */ 410 } /* if (*s=='.') */ 411 } /* if c==':' */ 412 continue; 413 } /* if (is_name_beginner(c) */ 414 415 416 if ( is_end_of_line [c] ) 417 { /* empty statement */ 418 continue; 419 } 420 421 if ( isdigit(c) ) 422 { /* local label ("4:") */ 423 temp = c - '0'; 424 #ifdef SUN_ASM_SYNTAX 425 if( *input_line_pointer=='$') 426 input_line_pointer++; 427 #endif 428 if ( * input_line_pointer ++ == ':' ) 429 { 430 local_colon (temp); 431 } 432 else 433 { 434 as_bad( "Spurious digit %d.", temp); 435 input_line_pointer -- ; 436 ignore_rest_of_line(); 437 } 438 continue; 439 } 440 if(c && index(line_comment_chars,c)) { /* Its a comment. Better say APP or NO_APP */ 441 char *ends; 442 char *strstr(); 443 char *new_buf; 444 char *new_tmp; 445 int new_length; 446 char *tmp_buf = 0; 447 extern char *scrub_string,*scrub_last_string; 448 int scrub_from_string(); 449 void scrub_to_string(); 450 451 bump_line_counters(); 452 s=input_line_pointer; 453 if(strncmp(s,"APP\n",4)) 454 continue; /* We ignore it */ 455 s+=4; 456 457 ends=strstr(s,"#NO_APP\n"); 458 459 if(!ends) { 460 int tmp_len; 461 int num; 462 463 /* The end of the #APP wasn't in this buffer. We 464 keep reading in buffers until we find the #NO_APP 465 that goes with this #APP There is one. The specs 466 guarentee it. . .*/ 467 tmp_len=buffer_limit-s; 468 tmp_buf=xmalloc(tmp_len); 469 bcopy(s,tmp_buf,tmp_len); 470 do { 471 new_tmp = input_scrub_next_buffer(&buffer); 472 if(!new_tmp) 473 break; 474 else 475 buffer_limit = new_tmp; 476 input_line_pointer = buffer; 477 ends = strstr(buffer,"#NO_APP\n"); 478 if(ends) 479 num=ends-buffer; 480 else 481 num=buffer_limit-buffer; 482 483 tmp_buf=xrealloc(tmp_buf,tmp_len+num); 484 bcopy(buffer,tmp_buf+tmp_len,num); 485 tmp_len+=num; 486 } while(!ends); 487 488 input_line_pointer= ends ? ends+8 : NULL; 489 490 s=tmp_buf; 491 ends=s+tmp_len; 492 493 } else { 494 input_line_pointer=ends+8; 495 } 496 new_buf=xmalloc(100); 497 new_length=100; 498 new_tmp=new_buf; 499 500 scrub_string=s; 501 scrub_last_string = ends; 502 for(;;) { 503 int ch; 504 505 ch=do_scrub_next_char(scrub_from_string,scrub_to_string); 506 if(ch==EOF) break; 507 *new_tmp++=ch; 508 if(new_tmp==new_buf+new_length) { 509 new_buf=xrealloc(new_buf,new_length+100); 510 new_tmp=new_buf+new_length; 511 new_length+=100; 512 } 513 } 514 515 if(tmp_buf) 516 free(tmp_buf); 517 old_buffer=buffer; 518 old_input=input_line_pointer; 519 old_limit=buffer_limit; 520 buffer=new_buf; 521 input_line_pointer=new_buf; 522 buffer_limit=new_tmp; 523 continue; 524 } 525 526 as_bad("Junk character %d.",c); 527 ignore_rest_of_line(); 528 } /* while (input_line_pointer<buffer_limit )*/ 529 if(old_buffer) { 530 bump_line_counters(); 531 if(old_input == 0) 532 return; 533 buffer=old_buffer; 534 input_line_pointer=old_input; 535 buffer_limit=old_limit; 536 old_buffer = 0; 537 goto contin; 538 } 539 } /* while (more bufrers to scan) */ 540 } /* read_a_source_file() */ 541 542 void 543 s_abort() 544 { 545 as_fatal(".abort detected. Abandoning ship."); 546 } 547 548 #ifdef OTHER_ALIGN 549 static void 550 s_align() 551 { 552 register unsigned int temp; 553 register long int temp_fill; 554 unsigned int i; 555 556 temp = get_absolute_expression (); 557 #define MAX_ALIGNMENT (1 << 15) 558 if ( temp > MAX_ALIGNMENT ) { 559 as_bad("Alignment too large: %d. assumed.", temp = MAX_ALIGNMENT); 560 } 561 562 /* 563 * For the sparc, `.align (1<<n)' actually means `.align n' 564 * so we have to convert it. 565 */ 566 if (temp != 0) { 567 for (i = 0; (temp & 1) == 0; temp >>= 1, ++i) 568 ; 569 } 570 if (temp != 1) 571 as_bad("Alignment not a power of 2"); 572 573 temp = i; 574 if (*input_line_pointer == ',') { 575 input_line_pointer ++; 576 temp_fill = get_absolute_expression (); 577 } else { 578 temp_fill = 0; 579 } 580 /* Only make a frag if we HAVE to. . . */ 581 if (temp && ! need_pass_2) 582 frag_align (temp, (int)temp_fill); 583 584 demand_empty_rest_of_line(); 585 } 586 #else 587 588 void 589 s_align() 590 { 591 register int temp; 592 register long int temp_fill; 593 594 temp = get_absolute_expression (); 595 #define MAX_ALIGNMENT (15) 596 if ( temp > MAX_ALIGNMENT ) 597 as_bad("Alignment too large: %d. assumed.", temp = MAX_ALIGNMENT); 598 else if ( temp < 0 ) { 599 as_bad("Alignment negative. 0 assumed."); 600 temp = 0; 601 } 602 if ( *input_line_pointer == ',' ) { 603 input_line_pointer ++; 604 temp_fill = get_absolute_expression (); 605 } else 606 temp_fill = 0; 607 /* Only make a frag if we HAVE to. . . */ 608 if ( temp && ! need_pass_2 ) 609 frag_align (temp, (int)temp_fill); 610 demand_empty_rest_of_line(); 611 } 612 #endif 613 614 void 615 s_comm() 616 { 617 register char *name; 618 register char c; 619 register char *p; 620 register int temp; 621 register symbolS * symbolP; 622 623 name = input_line_pointer; 624 c = get_symbol_end(); 625 /* just after name is now '\0' */ 626 p = input_line_pointer; 627 *p = c; 628 SKIP_WHITESPACE(); 629 if ( * input_line_pointer != ',' ) { 630 as_bad("Expected comma after symbol-name"); 631 ignore_rest_of_line(); 632 return; 633 } 634 input_line_pointer ++; /* skip ',' */ 635 if ( (temp = get_absolute_expression ()) < 0 ) { 636 as_warn(".COMMon length (%d.) <0! Ignored.", temp); 637 ignore_rest_of_line(); 638 return; 639 } 640 *p = 0; 641 symbolP = symbol_find_or_make (name); 642 *p = c; 643 if ( (symbolP -> sy_type & N_TYPE) != N_UNDF || 644 symbolP -> sy_other != 0 || symbolP -> sy_desc != 0) { 645 as_warn( "Ignoring attempt to re-define symbol"); 646 ignore_rest_of_line(); 647 return; 648 } 649 if (symbolP -> sy_value) { 650 if (symbolP -> sy_value != temp) 651 as_warn( "Length of .comm \"%s\" is already %d. Not changed to %d.", 652 symbolP -> sy_name, symbolP -> sy_value, temp); 653 } else { 654 symbolP -> sy_value = temp; 655 symbolP -> sy_type |= N_EXT; 656 } 657 #ifdef VMS 658 if(!temp) 659 symbolP->sy_other = const_flag; 660 #endif 661 know( symbolP -> sy_frag == &zero_address_frag ); 662 demand_empty_rest_of_line(); 663 } 664 665 #ifdef VMS 666 void 667 s_const() 668 { 669 register int temp; 670 671 temp = get_absolute_expression (); 672 subseg_new (SEG_DATA, (subsegT)temp); 673 const_flag = 1; 674 demand_empty_rest_of_line(); 675 } 676 #endif 677 678 void 679 s_data() 680 { 681 register int temp; 682 683 temp = get_absolute_expression (); 684 subseg_new (SEG_DATA, (subsegT)temp); 685 #ifdef VMS 686 const_flag = 0; 687 #endif 688 demand_empty_rest_of_line(); 689 } 690 691 void 692 s_desc() 693 { 694 register char *name; 695 register char c; 696 register char *p; 697 register symbolS * symbolP; 698 register int temp; 699 700 /* 701 * Frob invented at RMS' request. Set the n_desc of a symbol. 702 */ 703 name = input_line_pointer; 704 c = get_symbol_end(); 705 p = input_line_pointer; 706 symbolP = symbol_table_lookup (name); 707 * p = c; 708 SKIP_WHITESPACE(); 709 if ( * input_line_pointer != ',' ) { 710 *p = 0; 711 as_bad("Expected comma after name \"%s\"", name); 712 *p = c; 713 ignore_rest_of_line(); 714 } else { 715 input_line_pointer ++; 716 temp = get_absolute_expression (); 717 *p = 0; 718 symbolP = symbol_find_or_make (name); 719 *p = c; 720 symbolP -> sy_desc = temp; 721 } 722 demand_empty_rest_of_line(); 723 } 724 725 void 726 s_file() 727 { 728 register char *s; 729 int length; 730 731 /* Some assemblers tolerate immediately following '"' */ 732 if ( s = demand_copy_string( & length ) ) { 733 new_logical_line (s, -1); 734 demand_empty_rest_of_line(); 735 } 736 } 737 738 void 739 s_fill() 740 { 741 long int temp_repeat; 742 long int temp_size; 743 register long int temp_fill; 744 char *p; 745 746 if ( get_absolute_expression_and_terminator(& temp_repeat) != ',' ) { 747 input_line_pointer --; /* Backup over what was not a ','. */ 748 as_warn("Expect comma after rep-size in .fill"); 749 ignore_rest_of_line(); 750 return; 751 } 752 if ( get_absolute_expression_and_terminator( & temp_size) != ',' ) { 753 input_line_pointer --; /* Backup over what was not a ','. */ 754 as_warn("Expected comma after size in .fill"); 755 ignore_rest_of_line(); 756 return; 757 } 758 /* 759 * This is to be compatible with BSD 4.2 AS, not for any rational reason. 760 */ 761 #define BSD_FILL_SIZE_CROCK_8 (8) 762 if ( temp_size > BSD_FILL_SIZE_CROCK_8 ) { 763 as_bad(".fill size clamped to %d.", BSD_FILL_SIZE_CROCK_8); 764 temp_size = BSD_FILL_SIZE_CROCK_8 ; 765 } if ( temp_size < 0 ) { 766 as_warn("Size negative: .fill ignored."); 767 temp_size = 0; 768 } else if ( temp_repeat <= 0 ) { 769 as_warn("Repeat < 0, .fill ignored"); 770 temp_size = 0; 771 } 772 temp_fill = get_absolute_expression (); 773 if ( temp_size && !need_pass_2 ) { 774 p = frag_var (rs_fill, (int)temp_size, (int)temp_size, (relax_substateT)0, (symbolS *)0, temp_repeat, (char *)0); 775 bzero (p, (int)temp_size); 776 /* 777 * The magic number BSD_FILL_SIZE_CROCK_4 is from BSD 4.2 VAX flavoured AS. 778 * The following bizzare behaviour is to be compatible with above. 779 * I guess they tried to take up to 8 bytes from a 4-byte expression 780 * and they forgot to sign extend. Un*x Sux. 781 */ 782 #define BSD_FILL_SIZE_CROCK_4 (4) 783 md_number_to_chars (p, temp_fill, temp_size > BSD_FILL_SIZE_CROCK_4 ? BSD_FILL_SIZE_CROCK_4 : (int)temp_size); 784 /* 785 * Note: .fill (),0 emits no frag (since we are asked to .fill 0 bytes) 786 * but emits no error message because it seems a legal thing to do. 787 * It is a degenerate case of .fill but could be emitted by a compiler. 788 */ 789 } 790 demand_empty_rest_of_line(); 791 } 792 793 #ifdef DONTDEF 794 void 795 s_gdbbeg() 796 { 797 register int temp; 798 799 temp = get_absolute_expression (); 800 if (temp < 0) 801 as_warn( "Block number <0. Ignored." ); 802 else if (flagseen ['G']) 803 gdb_block_beg ( (long int) temp, frag_now, (long int)(obstack_next_free(& frags) - frag_now -> fr_literal)); 804 demand_empty_rest_of_line (); 805 } 806 807 void 808 s_gdbblock() 809 { 810 register int position; 811 int temp; 812 813 if (get_absolute_expression_and_terminator (&temp) != ',') { 814 as_warn( "expected comma before position in .gdbblock"); 815 --input_line_pointer; 816 ignore_rest_of_line (); 817 return; 818 } 819 position = get_absolute_expression (); 820 if (flagseen ['G']) 821 gdb_block_position ((long int) temp, (long int) position); 822 demand_empty_rest_of_line (); 823 } 824 825 void 826 s_gdbend() 827 { 828 register int temp; 829 830 temp = get_absolute_expression (); 831 if (temp < 0) 832 as_warn( "Block number <0. Ignored." ); 833 else if (flagseen ['G']) 834 gdb_block_end ( (long int) temp, frag_now, (long int)(obstack_next_free(& frags) - frag_now -> fr_literal)); 835 demand_empty_rest_of_line (); 836 } 837 838 void 839 s_gdbsym() 840 { 841 register char *name, 842 *p; 843 register char c; 844 register symbolS * symbolP; 845 register int temp; 846 847 name = input_line_pointer; 848 c = get_symbol_end(); 849 p = input_line_pointer; 850 symbolP = symbol_find_or_make (name); 851 *p = c; 852 SKIP_WHITESPACE(); 853 if ( * input_line_pointer != ',' ) { 854 as_warn("Expected comma after name"); 855 ignore_rest_of_line(); 856 return; 857 } 858 input_line_pointer ++; 859 if ( (temp = get_absolute_expression ()) < 0 ) { 860 as_warn("Bad GDB symbol file offset (%d.) <0! Ignored.", temp); 861 ignore_rest_of_line(); 862 return; 863 } 864 if (flagseen ['G']) 865 gdb_symbols_fixup (symbolP, (long int)temp); 866 demand_empty_rest_of_line (); 867 } 868 869 void 870 s_gdbline() 871 { 872 int file_number, 873 lineno; 874 875 if(get_absolute_expression_and_terminator(&file_number) != ',') { 876 as_warn("expected comman after filenum in .gdbline"); 877 ignore_rest_of_line(); 878 return; 879 } 880 lineno=get_absolute_expression(); 881 if(flagseen['G']) 882 gdb_line(file_number,lineno); 883 demand_empty_rest_of_line(); 884 } 885 886 887 void 888 s_gdblinetab() 889 { 890 int file_number, 891 offset; 892 893 if(get_absolute_expression_and_terminator(&file_number) != ',') { 894 as_warn("expected comman after filenum in .gdblinetab"); 895 ignore_rest_of_line(); 896 return; 897 } 898 offset=get_absolute_expression(); 899 if(flagseen['G']) 900 gdb_line_tab(file_number,offset); 901 demand_empty_rest_of_line(); 902 } 903 #endif 904 905 void 906 s_globl() 907 { 908 register char *name; 909 register int c; 910 register symbolS * symbolP; 911 912 do { 913 name = input_line_pointer; 914 c = get_symbol_end(); 915 symbolP = symbol_find_or_make (name); 916 * input_line_pointer = c; 917 SKIP_WHITESPACE(); 918 symbolP -> sy_type |= N_EXT; 919 if(c==',') { 920 input_line_pointer++; 921 SKIP_WHITESPACE(); 922 if(*input_line_pointer=='\n') 923 c='\n'; 924 } 925 } while(c==','); 926 demand_empty_rest_of_line(); 927 } 928 929 void 930 s_lcomm() 931 { 932 register char *name; 933 register char c; 934 register char *p; 935 register int temp; 936 register symbolS * symbolP; 937 938 name = input_line_pointer; 939 c = get_symbol_end(); 940 p = input_line_pointer; 941 *p = c; 942 SKIP_WHITESPACE(); 943 if ( * input_line_pointer != ',' ) { 944 as_warn("Expected comma after name"); 945 ignore_rest_of_line(); 946 return; 947 } 948 input_line_pointer ++; 949 if ( (temp = get_absolute_expression ()) < 0 ) { 950 as_warn("BSS length (%d.) <0! Ignored.", temp); 951 ignore_rest_of_line(); 952 return; 953 } 954 *p = 0; 955 symbolP = symbol_find_or_make (name); 956 *p = c; 957 if ( symbolP -> sy_other == 0 958 && symbolP -> sy_desc == 0 959 && ( ( symbolP -> sy_type == N_BSS 960 && symbolP -> sy_value == local_bss_counter) 961 || ( (symbolP -> sy_type & N_TYPE) == N_UNDF 962 && symbolP -> sy_value == 0))) { 963 symbolP -> sy_value = local_bss_counter; 964 symbolP -> sy_type = N_BSS; 965 symbolP -> sy_frag = & bss_address_frag; 966 local_bss_counter += temp; 967 } else 968 as_warn( "Ignoring attempt to re-define symbol from %d. to %d.", 969 symbolP -> sy_value, local_bss_counter ); 970 demand_empty_rest_of_line(); 971 } 972 973 void 974 s_line() 975 { 976 /* Assume delimiter is part of expression. */ 977 /* BSD4.2 as fails with delightful bug, so we */ 978 /* are not being incompatible here. */ 979 new_logical_line ((char *)NULL, (int)(get_absolute_expression ())); 980 demand_empty_rest_of_line(); 981 } 982 983 void 984 s_long() 985 { 986 cons(4); 987 } 988 989 void 990 s_int() 991 { 992 cons(4); 993 } 994 995 void 996 s_lsym() 997 { 998 register char *name; 999 register char c; 1000 register char *p; 1001 register segT segment; 1002 expressionS exp; 1003 register symbolS *symbolP; 1004 1005 /* we permit ANY expression: BSD4.2 demands constants */ 1006 name = input_line_pointer; 1007 c = get_symbol_end(); 1008 p = input_line_pointer; 1009 *p = c; 1010 SKIP_WHITESPACE(); 1011 if ( * input_line_pointer != ',' ) { 1012 *p = 0; 1013 as_warn("Expected comma after name \"%s\"", name); 1014 *p = c; 1015 ignore_rest_of_line(); 1016 return; 1017 } 1018 input_line_pointer ++; 1019 segment = expression (& exp); 1020 if ( segment != SEG_ABSOLUTE && segment != SEG_DATA && 1021 segment != SEG_TEXT && segment != SEG_BSS) { 1022 as_bad("Bad expression: %s", seg_name [(int)segment]); 1023 ignore_rest_of_line(); 1024 return; 1025 } 1026 know( segment == SEG_ABSOLUTE || segment == SEG_DATA || segment == SEG_TEXT || segment == SEG_BSS ); 1027 *p = 0; 1028 symbolP = symbol_new (name,(unsigned char)(seg_N_TYPE [(int) segment]), 1029 0, 0, (valueT)(exp . X_add_number), & zero_address_frag); 1030 *p = c; 1031 demand_empty_rest_of_line(); 1032 } 1033 1034 void 1035 s_org() 1036 { 1037 register segT segment; 1038 expressionS exp; 1039 register long int temp_fill; 1040 register char *p; 1041 /* 1042 * Don't believe the documentation of BSD 4.2 AS. 1043 * There is no such thing as a sub-segment-relative origin. 1044 * Any absolute origin is given a warning, then assumed to be segment-relative. 1045 * Any segmented origin expression ("foo+42") had better be in the right 1046 * segment or the .org is ignored. 1047 * 1048 * BSD 4.2 AS warns if you try to .org backwards. We cannot because we 1049 * never know sub-segment sizes when we are reading code. 1050 * BSD will crash trying to emit -ve numbers of filler bytes in certain 1051 * .orgs. We don't crash, but see as-write for that code. 1052 */ 1053 /* 1054 * Don't make frag if need_pass_2==TRUE. 1055 */ 1056 segment = get_known_segmented_expression(& exp); 1057 if ( *input_line_pointer == ',' ) { 1058 input_line_pointer ++; 1059 temp_fill = get_absolute_expression (); 1060 } else 1061 temp_fill = 0; 1062 if ( ! need_pass_2 ) { 1063 if (segment != now_seg && segment != SEG_ABSOLUTE) 1064 as_warn("Illegal segment \"%s\". Segment \"%s\" assumed.", 1065 seg_name [(int) segment], seg_name [(int) now_seg]); 1066 p = frag_var (rs_org, 1, 1, (relax_substateT)0, exp . X_add_symbol, 1067 exp . X_add_number, (char *)0); 1068 * p = temp_fill; 1069 } /* if (ok to make frag) */ 1070 demand_empty_rest_of_line(); 1071 } 1072 1073 void 1074 s_set() 1075 { 1076 register char *name; 1077 register char delim; 1078 register char *end_name; 1079 register symbolS *symbolP; 1080 1081 /* 1082 * Especial apologies for the random logic: 1083 * this just grew, and could be parsed much more simply! 1084 * Dean in haste. 1085 */ 1086 name = input_line_pointer; 1087 delim = get_symbol_end(); 1088 end_name = input_line_pointer; 1089 *end_name = delim; 1090 SKIP_WHITESPACE(); 1091 if ( * input_line_pointer != ',' ) { 1092 *end_name = 0; 1093 as_warn("Expected comma after name \"%s\"", name); 1094 *end_name = delim; 1095 ignore_rest_of_line(); 1096 return; 1097 } 1098 input_line_pointer ++; 1099 *end_name = 0; 1100 if(name[0]=='.' && name[1]=='\0') { 1101 /* Turn '. = mumble' into a .org mumble */ 1102 register segT segment; 1103 expressionS exp; 1104 register char *ptr; 1105 1106 segment = get_known_segmented_expression(& exp); 1107 if ( ! need_pass_2 ) { 1108 if (segment != now_seg && segment != SEG_ABSOLUTE) 1109 as_warn("Illegal segment \"%s\". Segment \"%s\" assumed.", 1110 seg_name [(int) segment], seg_name [(int) now_seg]); 1111 ptr = frag_var (rs_org, 1, 1, (relax_substateT)0, exp.X_add_symbol, 1112 exp.X_add_number, (char *)0); 1113 *ptr= 0; 1114 } /* if (ok to make frag) */ 1115 *end_name = delim; 1116 return; 1117 } 1118 symbolP = symbol_find_or_make (name); 1119 *end_name = delim; 1120 pseudo_set (symbolP); 1121 demand_empty_rest_of_line (); 1122 } 1123 1124 void 1125 s_space() 1126 { 1127 long int temp_repeat; 1128 register long int temp_fill; 1129 register char *p; 1130 1131 /* Just like .fill, but temp_size = 1 */ 1132 if ( get_absolute_expression_and_terminator( & temp_repeat) == ',' ) { 1133 temp_fill = get_absolute_expression (); 1134 } else { 1135 input_line_pointer --; /* Backup over what was not a ','. */ 1136 temp_fill = 0; 1137 } 1138 if ( temp_repeat <= 0 ) { 1139 as_warn("Repeat < 0, .space ignored"); 1140 ignore_rest_of_line(); 1141 return; 1142 } 1143 if ( ! need_pass_2 ) { 1144 p = frag_var (rs_fill, 1, 1, (relax_substateT)0, (symbolS *)0, 1145 temp_repeat, (char *)0); 1146 * p = temp_fill; 1147 } 1148 demand_empty_rest_of_line(); 1149 } 1150 1151 void 1152 s_text() 1153 { 1154 register int temp; 1155 1156 temp = get_absolute_expression (); 1157 subseg_new (SEG_TEXT, (subsegT)temp); 1158 demand_empty_rest_of_line(); 1159 } 1160 1161 1162 /*( JF was static, but can't be if machine dependent pseudo-ops are to use it */ 1163 1164 void 1165 demand_empty_rest_of_line() 1166 { 1167 SKIP_WHITESPACE(); 1168 if ( is_end_of_line [* input_line_pointer] ) 1169 { 1170 input_line_pointer ++; 1171 } 1172 else 1173 { 1174 ignore_rest_of_line(); 1175 } 1176 /* Return having already swallowed end-of-line. */ 1177 } /* Return pointing just after end-of-line. */ 1178 1179 1180 void 1181 ignore_rest_of_line() /* For suspect lines: gives warning. */ 1182 { 1183 if ( ! is_end_of_line [* input_line_pointer]) 1184 { 1185 as_warn("Rest of line ignored. 1st junk character valued %d (%c)." 1186 , * input_line_pointer, *input_line_pointer); 1187 while ( input_line_pointer < buffer_limit 1188 && ! is_end_of_line [* input_line_pointer] ) 1189 { 1190 input_line_pointer ++; 1191 } 1192 } 1193 input_line_pointer ++; /* Return pointing just after end-of-line. */ 1194 know( is_end_of_line [input_line_pointer [-1]] ); 1195 } 1196 1197 /* 1198 * stab() 1199 * 1200 * Handle .stabX directives, which used to be open-coded. 1201 * So much creeping featurism overloaded the semantics that we decided 1202 * to put all .stabX thinking in one place. Here. 1203 * 1204 * We try to make any .stabX directive legal. Other people's AS will often 1205 * do assembly-time consistency checks: eg assigning meaning to n_type bits 1206 * and "protecting" you from setting them to certain values. (They also zero 1207 * certain bits before emitting symbols. Tut tut.) 1208 * 1209 * If an expression is not absolute we either gripe or use the relocation 1210 * information. Other people's assemblers silently forget information they 1211 * don't need and invent information they need that you didn't supply. 1212 * 1213 * .stabX directives always make a symbol table entry. It may be junk if 1214 * the rest of your .stabX directive is malformed. 1215 */ 1216 static void 1217 stab (what) 1218 int what; 1219 { 1220 register symbolS * symbolP; 1221 register char * string; 1222 int saved_type; 1223 int length; 1224 int goof; /* TRUE if we have aborted. */ 1225 long int longint; 1226 1227 /* 1228 * Enter with input_line_pointer pointing past .stabX and any following 1229 * whitespace. 1230 */ 1231 goof = FALSE; /* JF who forgot this?? */ 1232 if (what == 's') { 1233 string = demand_copy_C_string (& length); 1234 SKIP_WHITESPACE(); 1235 if (* input_line_pointer == ',') 1236 input_line_pointer ++; 1237 else { 1238 as_warn( "I need a comma after symbol's name" ); 1239 goof = TRUE; 1240 } 1241 } else 1242 string = ""; 1243 1244 /* 1245 * Input_line_pointer->after ','. String -> symbol name. 1246 */ 1247 if (! goof) { 1248 symbolP = symbol_new (string, 0,0,0,0,(struct frag *)0); 1249 switch (what) { 1250 case 'd': 1251 symbolP->sy_name = NULL; /* .stabd feature. */ 1252 symbolP->sy_value = obstack_next_free(& frags) - frag_now->fr_literal; 1253 symbolP->sy_frag = frag_now; 1254 break; 1255 1256 case 'n': 1257 symbolP->sy_frag = &zero_address_frag; 1258 break; 1259 1260 case 's': 1261 symbolP->sy_frag = & zero_address_frag; 1262 break; 1263 1264 default: 1265 BAD_CASE( what ); 1266 break; 1267 } 1268 if (get_absolute_expression_and_terminator (& longint) == ',') 1269 symbolP->sy_type = saved_type = longint; 1270 else { 1271 as_warn( "I want a comma after the n_type expression" ); 1272 goof = TRUE; 1273 input_line_pointer --; /* Backup over a non-',' char. */ 1274 } 1275 } 1276 if (! goof) { 1277 if (get_absolute_expression_and_terminator (& longint) == ',') 1278 symbolP->sy_other = longint; 1279 else { 1280 as_warn( "I want a comma after the n_other expression" ); 1281 goof = TRUE; 1282 input_line_pointer --; /* Backup over a non-',' char. */ 1283 } 1284 } 1285 if (! goof) { 1286 symbolP->sy_desc = get_absolute_expression (); 1287 if (what == 's' || what == 'n') { 1288 if (* input_line_pointer != ',') { 1289 as_warn( "I want a comma after the n_desc expression" ); 1290 goof = TRUE; 1291 } else { 1292 input_line_pointer ++; 1293 } 1294 } 1295 } 1296 if ((! goof) && (what=='s' || what=='n')) { 1297 pseudo_set (symbolP); 1298 symbolP->sy_type = saved_type; 1299 } 1300 if (goof) 1301 ignore_rest_of_line (); 1302 else 1303 demand_empty_rest_of_line (); 1304 } 1305 1306 /* 1307 * pseudo_set() 1308 * 1309 * In: Pointer to a symbol. 1310 * Input_line_pointer -> expression. 1311 * 1312 * Out: Input_line_pointer -> just after any whitespace after expression. 1313 * Tried to set symbol to value of expression. 1314 * Will change sy_type, sy_value, sy_frag; 1315 * May set need_pass_2 == TRUE. 1316 */ 1317 static void 1318 pseudo_set (symbolP) 1319 symbolS * symbolP; 1320 { 1321 expressionS exp; 1322 register segT segment; 1323 int ext; 1324 1325 know( symbolP ); /* NULL pointer is logic error. */ 1326 ext=(symbolP->sy_type&N_EXT); 1327 if ((segment = expression( & exp )) == SEG_NONE) 1328 { 1329 as_warn( "Missing expression: absolute 0 assumed" ); 1330 exp . X_seg = SEG_ABSOLUTE; 1331 exp . X_add_number = 0; 1332 } 1333 switch (segment) 1334 { 1335 case SEG_BIG: 1336 as_warn( "%s number illegal. Absolute 0 assumed.", 1337 exp . X_add_number > 0 ? "Bignum" : "Floating-Point" ); 1338 symbolP -> sy_type = N_ABS | ext; 1339 symbolP -> sy_value = 0; 1340 symbolP -> sy_frag = & zero_address_frag; 1341 break; 1342 1343 case SEG_NONE: 1344 as_warn("No expression: Using absolute 0"); 1345 symbolP -> sy_type = N_ABS | ext; 1346 symbolP -> sy_value = 0; 1347 symbolP -> sy_frag = & zero_address_frag; 1348 break; 1349 1350 case SEG_DIFFERENCE: 1351 if (exp.X_add_symbol && exp.X_subtract_symbol 1352 && (exp.X_add_symbol->sy_type & N_TYPE) 1353 == (exp.X_subtract_symbol->sy_type & N_TYPE)) { 1354 if(exp.X_add_symbol->sy_frag != exp.X_subtract_symbol->sy_frag) { 1355 as_bad("Unknown expression: symbols %s and %s are in different frags.",exp.X_add_symbol->sy_name, exp.X_subtract_symbol->sy_name); 1356 need_pass_2++; 1357 } 1358 exp.X_add_number+=exp.X_add_symbol->sy_value - exp.X_subtract_symbol->sy_value; 1359 } else 1360 as_warn( "Complex expression. Absolute segment assumed." ); 1361 case SEG_ABSOLUTE: 1362 symbolP -> sy_type = N_ABS | ext; 1363 symbolP -> sy_value = exp . X_add_number; 1364 symbolP -> sy_frag = & zero_address_frag; 1365 break; 1366 1367 case SEG_DATA: 1368 case SEG_TEXT: 1369 case SEG_BSS: 1370 symbolP -> sy_type = seg_N_TYPE [(int) segment] | ext; 1371 symbolP -> sy_value= exp . X_add_number + exp . X_add_symbol -> sy_value; 1372 symbolP -> sy_frag = exp . X_add_symbol -> sy_frag; 1373 break; 1374 1375 case SEG_PASS1: /* Not an error. Just try another pass. */ 1376 symbolP->sy_forward=exp.X_add_symbol; 1377 as_warn("Unknown expression"); 1378 know( need_pass_2 == TRUE ); 1379 break; 1380 1381 case SEG_UNKNOWN: 1382 symbolP->sy_forward=exp.X_add_symbol; 1383 /* as_warn("unknown symbol"); */ 1384 /* need_pass_2 = TRUE; */ 1385 break; 1386 1387 default: 1388 BAD_CASE( segment ); 1389 break; 1390 } 1391 } 1392 1393 /* 1394 * stabs(file), stabf(func) and stabd(line) -- for the purpose of 1395 * source file debugging of assembly files, generate file, 1396 * function and line number stabs, respectively. 1397 * These functions have corresponding functions named 1398 * filestab(), funcstab() and linestab() in input-scrub.c, 1399 * where logical files and logical line numbers are handled. 1400 */ 1401 1402 #include <stab.h> 1403 1404 stabs(file) 1405 char *file; 1406 { 1407 /* .stabs "file",100,0,0,. */ 1408 (void) symbol_new(file, 1409 N_SO, 1410 0, 1411 0, 1412 obstack_next_free(& frags) - frag_now->fr_literal, 1413 frag_now); 1414 } 1415 1416 stabf(func) 1417 char *func; 1418 { 1419 symbolS *symbolP; 1420 static int void_undefined = 1; 1421 1422 /* crudely filter uninteresting labels: require an initial '_' */ 1423 if (*func++ != '_') 1424 return; 1425 1426 /* assembly functions are assumed to have void type */ 1427 if (void_undefined) 1428 { 1429 /* .stabs "void:t15=15",128,0,0,0 */ 1430 (void) symbol_new("void:t1=1", 1431 N_LSYM, 1432 0, 1433 0, 1434 0, 1435 &zero_address_frag); 1436 void_undefined = 0; 1437 } 1438 1439 /* .stabs "func:F1",36,0,0,. */ 1440 symbolP = symbol_new((char *) 0, 1441 N_FUN, 1442 0, 1443 0, 1444 obstack_next_free(& frags) - frag_now->fr_literal, 1445 frag_now); 1446 obstack_grow(¬es, func, strlen(func)); 1447 obstack_1grow(¬es, ':'); 1448 obstack_1grow(¬es, 'F'); 1449 obstack_1grow(¬es, '1'); 1450 obstack_1grow(¬es, '\0'); 1451 symbolP->sy_name = obstack_finish(¬es); 1452 } 1453 1454 stabd(line) 1455 unsigned line; 1456 { 1457 /* .stabd 68,0,line */ 1458 (void) symbol_new((char *)0, 1459 N_SLINE, 1460 0, 1461 line, 1462 obstack_next_free(& frags) - frag_now->fr_literal, 1463 frag_now); 1464 } 1465 1466 /* 1467 * cons() 1468 * 1469 * CONStruct more frag of .bytes, or .words etc. 1470 * Should need_pass_2 be TRUE then emit no frag(s). 1471 * This understands EXPRESSIONS, as opposed to big_cons(). 1472 * 1473 * Bug (?) 1474 * 1475 * This has a split personality. We use expression() to read the 1476 * value. We can detect if the value won't fit in a byte or word. 1477 * But we can't detect if expression() discarded significant digits 1478 * in the case of a long. Not worth the crocks required to fix it. 1479 */ 1480 void 1481 cons(nbytes) /* worker to do .byte etc statements */ 1482 /* clobbers input_line_pointer, checks */ 1483 /* end-of-line. */ 1484 register int nbytes; /* 1=.byte, 2=.word, 4=.long */ 1485 { 1486 register char c; 1487 register long int mask; /* High-order bits we will left-truncate, */ 1488 /* but includes sign bit also. */ 1489 register long int get; /* what we get */ 1490 register long int use; /* get after truncation. */ 1491 register long int unmask; /* what bits we will store */ 1492 register char * p; 1493 register segT segment; 1494 expressionS exp; 1495 #ifdef NS32K 1496 void fix_new_ns32k(); 1497 #else 1498 void fix_new(); 1499 #endif 1500 1501 /* 1502 * Input_line_pointer -> 1st char after pseudo-op-code and could legally 1503 * be a end-of-line. (Or, less legally an eof - which we cope with.) 1504 */ 1505 /* JF << of >= number of bits in the object is undefined. In particular 1506 SPARC (Sun 4) has problems */ 1507 if(nbytes>=sizeof(long int)) 1508 mask = 0; 1509 else 1510 mask = ~0 << (BITS_PER_CHAR * nbytes); /* Don't store these bits. */ 1511 unmask = ~ mask; /* Do store these bits. */ 1512 #ifdef NEVER 1513 "Do this mod if you want every overflow check to assume SIGNED 2's complement data."; 1514 mask = ~ (unmask >> 1); /* Includes sign bit now. */ 1515 #endif 1516 /* 1517 * The following awkward logic is to parse ZERO or more expressions, 1518 * comma seperated. Recall an expression includes its leading & 1519 * trailing blanks. We fake a leading ',' if there is (supposed to 1520 * be) a 1st expression, and keep demanding 1 expression for each ','. 1521 */ 1522 if (is_it_end_of_statement()) 1523 { 1524 c = 0; /* Skip loop. */ 1525 input_line_pointer ++; /* Matches end-of-loop 'correction'. */ 1526 } 1527 else 1528 c = ','; /* Do loop. */ 1529 while ( c == ',' ) 1530 { 1531 segment = expression( &exp ); /* At least scan over the expression. */ 1532 if ( ! need_pass_2 ) 1533 { /* Still worthwhile making frags. */ 1534 1535 /* Don't call this if we are going to junk this pass anyway! */ 1536 know( segment != SEG_PASS1 ); 1537 1538 if ( segment == SEG_DIFFERENCE && exp . X_add_symbol == NULL ) 1539 { 1540 as_warn( "Subtracting symbol \"%s\"(segment\"%s\") is too hard. Absolute segment assumed.", 1541 exp . X_subtract_symbol -> sy_name, 1542 seg_name [(int) N_TYPE_seg [exp . X_subtract_symbol -> sy_type & N_TYPE]]); 1543 segment = SEG_ABSOLUTE; 1544 /* Leave exp . X_add_number alone. */ 1545 } 1546 p = frag_more (nbytes); 1547 switch (segment) 1548 { 1549 case SEG_BIG: 1550 as_warn( "%s number illegal. Absolute 0 assumed.", 1551 exp . X_add_number > 0 ? "Bignum" : "Floating-Point"); 1552 md_number_to_chars (p, (long)0, nbytes); 1553 break; 1554 1555 case SEG_NONE: 1556 as_warn( "0 assumed for missing expression" ); 1557 exp . X_add_number = 0; 1558 know( exp . X_add_symbol == NULL ); 1559 /* fall into SEG_ABSOLUTE */ 1560 case SEG_ABSOLUTE: 1561 get = exp . X_add_number; 1562 use = get & unmask; 1563 if ( (get & mask) && (get & mask) != mask ) 1564 { /* Leading bits contain both 0s & 1s. */ 1565 as_warn("Value x%x truncated to x%x.", get, use); 1566 } 1567 md_number_to_chars (p, use, nbytes); /* put bytes in right order. */ 1568 break; 1569 1570 case SEG_DIFFERENCE: 1571 #ifndef WORKING_DOT_WORD 1572 if(nbytes==2) { 1573 struct broken_word *x; 1574 1575 x=(struct broken_word *)xmalloc(sizeof(struct broken_word)); 1576 x->next_broken_word=broken_words; 1577 broken_words=x; 1578 x->frag=frag_now; 1579 x->word_goes_here=p; 1580 x->dispfrag=0; 1581 x->add=exp.X_add_symbol; 1582 x->sub=exp.X_subtract_symbol; 1583 x->addnum=exp.X_add_number; 1584 x->added=0; 1585 new_broken_words++; 1586 break; 1587 } 1588 /* Else Fall through into. . . */ 1589 #endif 1590 case SEG_BSS: 1591 case SEG_UNKNOWN: 1592 case SEG_TEXT: 1593 case SEG_DATA: 1594 #if defined(SPARC) || defined(I860) 1595 fix_new (frag_now, p - frag_now -> fr_literal, nbytes, 1596 exp . X_add_symbol, exp . X_subtract_symbol, 1597 exp . X_add_number, 0, RELOC_32); 1598 #endif 1599 #ifdef NS32K 1600 fix_new_ns32k (frag_now, p - frag_now -> fr_literal, nbytes, 1601 exp . X_add_symbol, exp . X_subtract_symbol, 1602 exp . X_add_number, 0, 0, 2, 0, 0); 1603 #endif 1604 #if !defined(SPARC) && !defined(NS32K) && !defined(I860) 1605 fix_new (frag_now, p - frag_now -> fr_literal, nbytes, 1606 exp . X_add_symbol, exp . X_subtract_symbol, 1607 exp . X_add_number, 0); 1608 #endif 1609 break; 1610 1611 default: 1612 BAD_CASE( segment ); 1613 break; 1614 } /* switch(segment) */ 1615 } /* if(!need_pass_2) */ 1616 c = * input_line_pointer ++; 1617 } /* while(c==',') */ 1618 input_line_pointer --; /* Put terminator back into stream. */ 1619 demand_empty_rest_of_line(); 1620 } /* cons() */ 1621 1622 /* 1623 * big_cons() 1624 * 1625 * CONStruct more frag(s) of .quads, or .octa etc. 1626 * Makes 0 or more new frags. 1627 * If need_pass_2 == TRUE, generate no frag. 1628 * This understands only bignums, not expressions. Cons() understands 1629 * expressions. 1630 * 1631 * Constants recognised are '0...'(octal) '0x...'(hex) '...'(decimal). 1632 * 1633 * This creates objects with struct obstack_control objs, destroying 1634 * any context objs held about a partially completed object. Beware! 1635 * 1636 * 1637 * I think it sucks to have 2 different types of integers, with 2 1638 * routines to read them, store them etc. 1639 * It would be nicer to permit bignums in expressions and only 1640 * complain if the result overflowed. However, due to "efficiency"... 1641 */ 1642 void 1643 big_cons(nbytes) /* worker to do .quad etc statements */ 1644 /* clobbers input_line_pointer, checks */ 1645 /* end-of-line. */ 1646 register int nbytes; /* 8=.quad 16=.octa ... */ 1647 { 1648 register char c; /* input_line_pointer -> c. */ 1649 register int radix; 1650 register long int length; /* Number of chars in an object. */ 1651 register int digit; /* Value of 1 digit. */ 1652 register int carry; /* For multi-precision arithmetic. */ 1653 register int work; /* For multi-precision arithmetic. */ 1654 register char * p; /* For multi-precision arithmetic. */ 1655 1656 extern char hex_value[]; /* In hex_value.c. */ 1657 1658 /* 1659 * The following awkward logic is to parse ZERO or more strings, 1660 * comma seperated. Recall an expression includes its leading & 1661 * trailing blanks. We fake a leading ',' if there is (supposed to 1662 * be) a 1st expression, and keep demanding 1 expression for each ','. 1663 */ 1664 if (is_it_end_of_statement()) 1665 { 1666 c = 0; /* Skip loop. */ 1667 } 1668 else 1669 { 1670 c = ','; /* Do loop. */ 1671 -- input_line_pointer; 1672 } 1673 while (c == ',') 1674 { 1675 ++ input_line_pointer; 1676 SKIP_WHITESPACE(); 1677 c = * input_line_pointer; 1678 /* C contains 1st non-blank character of what we hope is a number. */ 1679 if (c == '0') 1680 { 1681 c = * ++ input_line_pointer; 1682 if (c == 'x' || c=='X') 1683 { 1684 c = * ++ input_line_pointer; 1685 radix = 16; 1686 } 1687 else 1688 { 1689 radix = 8; 1690 } 1691 } 1692 else 1693 { 1694 radix = 10; 1695 } 1696 /* 1697 * This feature (?) is here to stop people worrying about 1698 * mysterious zero constants: which is what they get when 1699 * they completely omit digits. 1700 */ 1701 if (hex_value[c] >= radix) 1702 { 1703 as_warn( "Missing digits. 0 assumed." ); 1704 } 1705 bignum_high = bignum_low - 1; /* Start constant with 0 chars. */ 1706 for( ; (digit = hex_value [c]) < radix; c = * ++ input_line_pointer) 1707 { 1708 /* Multiply existing number by radix, then add digit. */ 1709 carry = digit; 1710 for (p=bignum_low; p <= bignum_high; p++) 1711 { 1712 work = (*p & MASK_CHAR) * radix + carry; 1713 *p = work & MASK_CHAR; 1714 carry = work >> BITS_PER_CHAR; 1715 } 1716 if (carry) 1717 { 1718 grow_bignum(); 1719 * bignum_high = carry & MASK_CHAR; 1720 know( (carry & ~ MASK_CHAR) == 0); 1721 } 1722 } 1723 length = bignum_high - bignum_low + 1; 1724 if (length > nbytes) 1725 { 1726 as_warn( "Most significant bits truncated in integer constant." ); 1727 } 1728 else 1729 { 1730 register long int leading_zeroes; 1731 1732 for(leading_zeroes = nbytes - length; 1733 leading_zeroes; 1734 leading_zeroes --) 1735 { 1736 grow_bignum(); 1737 * bignum_high = 0; 1738 } 1739 } 1740 if (! need_pass_2) 1741 { 1742 p = frag_more (nbytes); 1743 bcopy (bignum_low, p, (int)nbytes); 1744 } 1745 /* C contains character after number. */ 1746 SKIP_WHITESPACE(); 1747 c = * input_line_pointer; 1748 /* C contains 1st non-blank character after number. */ 1749 } 1750 demand_empty_rest_of_line(); 1751 } /* big_cons() */ 1752 1753 static void 1754 grow_bignum() /* Extend bignum by 1 char. */ 1755 { 1756 register long int length; 1757 1758 bignum_high ++; 1759 if (bignum_high >= bignum_limit) 1760 { 1761 length = bignum_limit - bignum_low; 1762 bignum_low = xrealloc (bignum_low, length + length); 1763 bignum_high = bignum_low + length; 1764 bignum_limit = bignum_low + length + length; 1765 } 1766 } /* grow_bignum(); */ 1767 1768 /* 1769 * float_cons() 1770 * 1771 * CONStruct some more frag chars of .floats .ffloats etc. 1772 * Makes 0 or more new frags. 1773 * If need_pass_2 == TRUE, no frags are emitted. 1774 * This understands only floating literals, not expressions. Sorry. 1775 * 1776 * A floating constant is defined by atof_generic(), except it is preceded 1777 * by 0d 0f 0g or 0h. After observing the STRANGE way my BSD AS does its 1778 * reading, I decided to be incompatible. This always tries to give you 1779 * rounded bits to the precision of the pseudo-op. Former AS did premature 1780 * truncatation, restored noisy bits instead of trailing 0s AND gave you 1781 * a choice of 2 flavours of noise according to which of 2 floating-point 1782 * scanners you directed AS to use. 1783 * 1784 * In: input_line_pointer -> whitespace before, or '0' of flonum. 1785 * 1786 */ 1787 1788 void /* JF was static, but can't be if VAX.C is goning to use it */ 1789 float_cons(float_type) /* Worker to do .float etc statements. */ 1790 /* Clobbers input_line-pointer, checks end-of-line. */ 1791 register float_type; /* 'f':.ffloat ... 'F':.float ... */ 1792 { 1793 register char * p; 1794 register char c; 1795 int length; /* Number of chars in an object. */ 1796 register char * err; /* Error from scanning floating literal. */ 1797 char temp [MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT]; 1798 1799 /* 1800 * The following awkward logic is to parse ZERO or more strings, 1801 * comma seperated. Recall an expression includes its leading & 1802 * trailing blanks. We fake a leading ',' if there is (supposed to 1803 * be) a 1st expression, and keep demanding 1 expression for each ','. 1804 */ 1805 if (is_it_end_of_statement()) 1806 { 1807 c = 0; /* Skip loop. */ 1808 ++ input_line_pointer; /* -> past termintor. */ 1809 } 1810 else 1811 { 1812 c = ','; /* Do loop. */ 1813 } 1814 while (c == ',') 1815 { 1816 /* input_line_pointer -> 1st char of a flonum (we hope!). */ 1817 SKIP_WHITESPACE(); 1818 /* Skip any 0{letter} that may be present. Don't even check if the 1819 * letter is legal. Someone may invent a "z" format and this routine 1820 * has no use for such information. Lusers beware: you get 1821 * diagnostics if your input is ill-conditioned. 1822 */ 1823 1824 if(input_line_pointer[0]=='0' && isalpha(input_line_pointer[1])) 1825 input_line_pointer+=2; 1826 1827 err = md_atof (float_type, temp, &length); 1828 know( length <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT); 1829 know( length > 0 ); 1830 if (* err) 1831 { 1832 as_warn( "Bad floating literal: %s", err); 1833 ignore_rest_of_line(); 1834 /* Input_line_pointer -> just after end-of-line. */ 1835 c = 0; /* Break out of loop. */ 1836 } 1837 else 1838 { 1839 if ( ! need_pass_2) 1840 { 1841 p = frag_more (length); 1842 bcopy (temp, p, length); 1843 } 1844 SKIP_WHITESPACE(); 1845 c = * input_line_pointer ++; 1846 /* C contains 1st non-white character after number. */ 1847 /* input_line_pointer -> just after terminator (c). */ 1848 } 1849 } 1850 -- input_line_pointer; /* -> terminator (is not ','). */ 1851 demand_empty_rest_of_line(); 1852 } /* float_cons() */ 1853 1854 /* 1855 * stringer() 1856 * 1857 * We read 0 or more ',' seperated, double-quoted strings. 1858 * 1859 * Caller should have checked need_pass_2 is FALSE because we don't check it. 1860 */ 1861 static void 1862 stringer(append_zero) /* Worker to do .ascii etc statements. */ 1863 /* Checks end-of-line. */ 1864 register int append_zero; /* 0: don't append '\0', else 1 */ 1865 { 1866 /* register char * p; JF unused */ 1867 /* register int length; JF unused */ /* Length of string we read, excluding */ 1868 /* trailing '\0' implied by closing quote. */ 1869 /* register char * where; JF unused */ 1870 /* register fragS * fragP; JF unused */ 1871 register int c; 1872 1873 /* 1874 * The following awkward logic is to parse ZERO or more strings, 1875 * comma seperated. Recall a string expression includes spaces 1876 * before the opening '\"' and spaces after the closing '\"'. 1877 * We fake a leading ',' if there is (supposed to be) 1878 * a 1st, expression. We keep demanding expressions for each 1879 * ','. 1880 */ 1881 if (is_it_end_of_statement()) 1882 { 1883 c = 0; /* Skip loop. */ 1884 ++ input_line_pointer; /* Compensate for end of loop. */ 1885 } 1886 else 1887 { 1888 c = ','; /* Do loop. */ 1889 } 1890 for ( ; c == ','; c = *input_line_pointer ++) 1891 { 1892 SKIP_WHITESPACE(); 1893 if (* input_line_pointer == '\"') 1894 { 1895 ++ input_line_pointer; /* -> 1st char of string. */ 1896 while ( (c = next_char_of_string()) >= 0) 1897 { 1898 FRAG_APPEND_1_CHAR( c ); 1899 } 1900 if (append_zero) 1901 { 1902 FRAG_APPEND_1_CHAR( 0 ); 1903 } 1904 know( input_line_pointer [-1] == '\"' ); 1905 } 1906 else 1907 { 1908 as_warn( "Expected \"-ed string" ); 1909 } 1910 SKIP_WHITESPACE(); 1911 } 1912 -- input_line_pointer; 1913 demand_empty_rest_of_line(); 1914 } /* stringer() */ 1915 1916 static int 1917 next_char_of_string () 1918 { 1919 register int c; 1920 1921 c = * input_line_pointer ++; 1922 switch (c) 1923 { 1924 case '\"': 1925 c = -1; 1926 break; 1927 1928 case '\\': 1929 switch (c = * input_line_pointer ++) 1930 { 1931 case 'b': 1932 c = '\b'; 1933 break; 1934 1935 case 'f': 1936 c = '\f'; 1937 break; 1938 1939 case 'n': 1940 c = '\n'; 1941 break; 1942 1943 case 'r': 1944 c = '\r'; 1945 break; 1946 1947 case 't': 1948 c = '\t'; 1949 break; 1950 1951 case '\\': 1952 case '"': 1953 break; /* As itself. */ 1954 1955 case '0': 1956 case '1': 1957 case '2': 1958 case '3': 1959 case '4': 1960 case '5': 1961 case '6': 1962 case '7': 1963 case '8': 1964 case '9': 1965 { 1966 long int number; 1967 1968 for (number = 0; isdigit(c); c = * input_line_pointer ++) 1969 { 1970 number = number * 8 + c - '0'; 1971 } 1972 c = number; 1973 } 1974 -- input_line_pointer; 1975 break; 1976 1977 case '\n': 1978 /* as_fatal( "Unterminated string - use app!" ); */ 1979 /* To be compatible with BSD 4.2 as: give the luser a linefeed!! */ 1980 c = '\n'; 1981 break; 1982 1983 default: 1984 as_warn( "Bad escaped character in string, '?' assumed" ); 1985 c = '?'; 1986 break; 1987 } 1988 break; 1989 1990 default: 1991 break; 1992 } 1993 return (c); 1994 } 1995 1996 static segT 1997 get_segmented_expression ( expP ) 1998 register expressionS * expP; 1999 { 2000 register segT retval; 2001 2002 if ( (retval = expression( expP )) == SEG_PASS1 || retval == SEG_NONE || retval == SEG_BIG ) 2003 { 2004 as_warn("Expected address expression: absolute 0 assumed"); 2005 retval = expP -> X_seg = SEG_ABSOLUTE; 2006 expP -> X_add_number = 0; 2007 expP -> X_add_symbol = expP -> X_subtract_symbol = 0; 2008 } 2009 return (retval); /* SEG_ ABSOLUTE,UNKNOWN,DATA,TEXT,BSS */ 2010 } 2011 2012 static segT 2013 get_known_segmented_expression ( expP ) 2014 register expressionS * expP; 2015 { 2016 register segT retval; 2017 register char * name1; 2018 register char * name2; 2019 2020 if ( (retval = get_segmented_expression (expP)) == SEG_UNKNOWN 2021 ) 2022 { 2023 name1 = expP -> X_add_symbol ? expP -> X_add_symbol -> sy_name : ""; 2024 name2 = expP -> X_subtract_symbol ? expP -> X_subtract_symbol -> sy_name : ""; 2025 if ( name1 && name2 ) 2026 { 2027 as_warn("Symbols \"%s\" \"%s\" are undefined: absolute 0 assumed.", 2028 name1, name2); 2029 } 2030 else 2031 { 2032 as_warn("Symbol \"%s\" undefined: absolute 0 assumed.", 2033 name1 ? name1 : name2); 2034 } 2035 retval = expP -> X_seg = SEG_ABSOLUTE; 2036 expP -> X_add_number = 0; 2037 expP -> X_add_symbol = expP -> X_subtract_symbol = NULL; 2038 } 2039 know( retval == SEG_ABSOLUTE || retval == SEG_DATA || retval == SEG_TEXT || retval == SEG_BSS || retval == SEG_DIFFERENCE ); 2040 return (retval); 2041 } /* get_known_segmented_expression() */ 2042 2043 2044 2045 /* static */ long int /* JF was static, but can't be if the MD pseudos are to use it */ 2046 get_absolute_expression () 2047 { 2048 expressionS exp; 2049 register segT s; 2050 2051 if ( (s = expression(& exp)) != SEG_ABSOLUTE ) 2052 { 2053 if ( s != SEG_NONE ) 2054 { 2055 as_warn( "Bad Absolute Expression, absolute 0 assumed."); 2056 } 2057 exp . X_add_number = 0; 2058 } 2059 return (exp . X_add_number); 2060 } 2061 2062 static char /* return terminator */ 2063 get_absolute_expression_and_terminator( val_pointer) 2064 long int * val_pointer; /* return value of expression */ 2065 { 2066 * val_pointer = get_absolute_expression (); 2067 return ( * input_line_pointer ++ ); 2068 } 2069 2070 /* 2071 * demand_copy_C_string() 2072 * 2073 * Like demand_copy_string, but return NULL if the string contains any '\0's. 2074 * Give a warning if that happens. 2075 */ 2076 static char * 2077 demand_copy_C_string (len_pointer) 2078 int * len_pointer; 2079 { 2080 register char * s; 2081 2082 if (s = demand_copy_string (len_pointer)) 2083 { 2084 register int len; 2085 2086 for (len = * len_pointer; 2087 len > 0; 2088 len--) 2089 { 2090 if (* s == 0) 2091 { 2092 s = 0; 2093 len = 1; 2094 * len_pointer = 0; 2095 as_warn( "This string may not contain \'\\0\'" ); 2096 } 2097 } 2098 } 2099 return (s); 2100 } 2101 2102 /* 2103 * demand_copy_string() 2104 * 2105 * Demand string, but return a safe (=private) copy of the string. 2106 * Return NULL if we can't read a string here. 2107 */ 2108 static char * 2109 demand_copy_string (lenP) 2110 int * lenP; 2111 { 2112 register int c; 2113 register int len; 2114 char * retval; 2115 2116 len = 0; 2117 SKIP_WHITESPACE(); 2118 if (* input_line_pointer == '\"') 2119 { 2120 input_line_pointer ++; /* Skip opening quote. */ 2121 while ( (c = next_char_of_string()) >= 0 ) { 2122 obstack_1grow ( ¬es, c ); 2123 len ++; 2124 } 2125 /* JF this next line is so demand_copy_C_string will return a null 2126 termanated string. */ 2127 obstack_1grow(¬es,'\0'); 2128 retval=obstack_finish( ¬es); 2129 } else { 2130 as_warn( "Missing string" ); 2131 retval = NULL; 2132 ignore_rest_of_line (); 2133 } 2134 * lenP = len; 2135 return (retval); 2136 } 2137 2138 /* 2139 * is_it_end_of_statement() 2140 * 2141 * In: Input_line_pointer -> next character. 2142 * 2143 * Do: Skip input_line_pointer over all whitespace. 2144 * 2145 * Out: TRUE if input_line_pointer -> end-of-line. 2146 */ 2147 static int 2148 is_it_end_of_statement() 2149 { 2150 SKIP_WHITESPACE(); 2151 return (is_end_of_line [* input_line_pointer]); 2152 } 2153 2154 void 2155 equals(sym_name) 2156 char *sym_name; 2157 { 2158 register struct symbol * symbolP; /* symbol we are working with */ 2159 2160 input_line_pointer++; 2161 if(*input_line_pointer=='=') 2162 input_line_pointer++; 2163 2164 while(*input_line_pointer==' ' || *input_line_pointer=='\t') 2165 input_line_pointer++; 2166 2167 if(sym_name[0]=='.' && sym_name[1]=='\0') { 2168 /* Turn '. = mumble' into a .org mumble */ 2169 register segT segment; 2170 expressionS exp; 2171 register char *p; 2172 2173 segment = get_known_segmented_expression(& exp); 2174 if ( ! need_pass_2 ) { 2175 if (segment != now_seg && segment != SEG_ABSOLUTE) 2176 as_warn("Illegal segment \"%s\". Segment \"%s\" assumed.", 2177 seg_name [(int) segment], seg_name [(int) now_seg]); 2178 p = frag_var (rs_org, 1, 1, (relax_substateT)0, exp.X_add_symbol, 2179 exp.X_add_number, (char *)0); 2180 * p = 0; 2181 } /* if (ok to make frag) */ 2182 } else { 2183 symbolP=symbol_find_or_make(sym_name); 2184 pseudo_set(symbolP); 2185 } 2186 } 2187 2188 /* end: read.c */ 2189