|
|
1.1 ! root 1: /* read.c - read a source file - ! 2: Copyright (C) 1986,1987 Free Software Foundation, Inc. ! 3: ! 4: This file is part of GAS, the GNU Assembler. ! 5: ! 6: GAS is free software; you can redistribute it and/or modify ! 7: it under the terms of the GNU General Public License as published by ! 8: the Free Software Foundation; either version 1, or (at your option) ! 9: any later version. ! 10: ! 11: GAS is distributed in the hope that it will be useful, ! 12: but WITHOUT ANY WARRANTY; without even the implied warranty of ! 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 14: GNU General Public License for more details. ! 15: ! 16: You should have received a copy of the GNU General Public License ! 17: along with GAS; see the file COPYING. If not, write to ! 18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ! 19: ! 20: #define MASK_CHAR (0xFF) /* If your chars aren't 8 bits, you will ! 21: change this a bit. But then, GNU isn't ! 22: spozed to run on your machine anyway. ! 23: (RMS is so shortsighted sometimes.) ! 24: */ ! 25: ! 26: #define MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT (16) ! 27: /* This is the largest known floating point */ ! 28: /* format (for now). It will grow when we */ ! 29: /* do 4361 style flonums. */ ! 30: ! 31: ! 32: /* Routines that read assembler source text to build spagetti in memory. */ ! 33: /* Another group of these functions is in the expr.c module */ ! 34: ! 35: #include <ctype.h> ! 36: #include <string.h> ! 37: #include <stdlib.h> ! 38: #include <sys/types.h> ! 39: #include <sys/stat.h> ! 40: #include "stuff/round.h" ! 41: #include "as.h" ! 42: #include "flonum.h" ! 43: #include "struc-symbol.h" ! 44: #include "expr.h" ! 45: #include "read.h" ! 46: #include "hash.h" ! 47: #include "obstack.h" ! 48: #include "md.h" ! 49: #include "symbols.h" ! 50: #include "sections.h" ! 51: #include "input-scrub.h" ! 52: #include "input-file.h" ! 53: #include "hex_value.h" ! 54: #include "messages.h" ! 55: #include "xmalloc.h" ! 56: #include "app.h" ! 57: ! 58: /* ! 59: * Parsing of input is done off of this pointer which points to the next char ! 60: * of source file to parse. ! 61: */ ! 62: char *input_line_pointer = NULL; ! 63: ! 64: /* ! 65: * buffer_limit is the value returned by the input_scrub_next_buffer() in ! 66: * read_a_source_file() and is not static only so read_an_include_file can save ! 67: * and restore it. ! 68: */ ! 69: char *buffer_limit = NULL; /* -> 1 + last char in buffer. */ ! 70: ! 71: /* ! 72: * This table is used by the macros is_name_beginner() and is_part_of_name() ! 73: * defined in read.h . ! 74: */ ! 75: const char lex_type[256] = { ! 76: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* @ABCDEFGHIJKLMNO */ ! 77: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* PQRSTUVWXYZ[\]^_ */ ! 78: 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, /* _!"#$%&'()*+,-./ */ ! 79: 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 0123456789:;<=>? */ ! 80: 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* @ABCDEFGHIJKLMNO */ ! 81: 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 3, /* PQRSTUVWXYZ[\]^_ */ ! 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, 0, /* pqrstuvwxyz{|}~. */ ! 84: 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* Allow all chars */ ! 85: 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* with the high bit */ ! 86: 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* set in names */ ! 87: 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, ! 88: 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, ! 89: 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, ! 90: 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ! 91: }; ! 92: ! 93: /* ! 94: * In: a character. ! 95: * Out: TRUE if this character ends a line. ! 96: */ ! 97: #define _ (0) ! 98: static const char is_end_of_line[256] = { ! 99: _, _, _, _, _, _, _, _, _, _,99, _, _, _, _, _, /* @abcdefghijklmno */ ! 100: _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ ! 101: _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ ! 102: _, _, _, _, _, _, _, _, _, _, _,99, _, _, _, _, /* 0123456789:;<=>? */ ! 103: #if defined(M88K) || defined(M98K) || defined(HPPA) ! 104: 99, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* @ABCDEFGHIJKLMNO */ ! 105: #else ! 106: _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ ! 107: #endif ! 108: _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ ! 109: _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ ! 110: _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ ! 111: _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ ! 112: _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ ! 113: _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ ! 114: _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */ ! 115: _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ /* */ ! 116: }; ! 117: #undef _ ! 118: ! 119: /* ! 120: * The conditional assembly feature (.if, .else, .elseif and .endif) is ! 121: * implemented with cond_state that tells us what we are in the middle of ! 122: * processing. ignore can be either TRUE or FALSE. When TRUE we are ignoring ! 123: * the block of code in the middle of a conditional. MAX_IF_DEPTH is the ! 124: * maximum depth that if's can be nested. ! 125: */ ! 126: #define MAX_IF_DEPTH 20 ! 127: typedef enum { ! 128: no_cond, /* no conditional is being processed */ ! 129: if_cond, /* inside if conditional */ ! 130: elseif_cond,/* inside elseif conditional */ ! 131: else_cond /* inside else conditional */ ! 132: }cond_type; ! 133: ! 134: struct cond_state { ! 135: cond_type the_cond; ! 136: int cond_met; ! 137: int ignore; ! 138: }; ! 139: typedef struct cond_state cond_stateS; ! 140: static cond_stateS the_cond_state = {no_cond, FALSE, FALSE}; ! 141: static cond_stateS last_states[MAX_IF_DEPTH]; ! 142: static int if_depth = 0; ! 143: ! 144: /* ! 145: * Assembler macros are implemented with these variables and functions. ! 146: */ ! 147: #define MAX_MACRO_DEPTH 20 ! 148: static int macro_depth = 0; ! 149: static struct hash_control ! 150: *ma_hash = NULL; /* use before set up: NULL-> address error */ ! 151: static struct obstack macros; /* obstack for macro text */ ! 152: static char *macro_name = NULL; /* name of macro we are defining */ ! 153: static int count_lines = TRUE; /* turns line number counting on and off */ ! 154: static int macros_on = TRUE; /* .macros_on and .macros_off toggles this to ! 155: allow macros to be turned off, which allows ! 156: macros to override a machine instruction and ! 157: still use it. */ ! 158: static void expand_macro(char *macro_contents); ! 159: static void macro_begin(void); ! 160: ! 161: ! 162: /* ! 163: * The .dump and .load feature is implemented with these variables and ! 164: * functions. ! 165: */ ! 166: static FILE *dump_fp = NULL; ! 167: static char *write_macro(char *string, char *value); ! 168: static char * write_symbol(char *string, char *value); ! 169: ! 170: ! 171: /* Functions private to this file */ ! 172: static void parse_a_buffer(char *buffer); ! 173: static void parse_line_comment(char **buffer); ! 174: static segT get_segmented_expression(expressionS *expP); ! 175: static void pseudo_op_begin(void); ! 176: static void pseudo_set(symbolS *symbolP); ! 177: static void stab(int what); ! 178: static char get_absolute_expression_and_terminator(long *val_pointer); ! 179: static char *demand_copy_C_string(int *len_pointer); ! 180: static char *demand_copy_string(int *lenP); ! 181: static int is_it_end_of_statement(void); ! 182: static void equals(char *sym_name); ! 183: static int next_char_of_string(void); ! 184: ! 185: #ifdef M68K /* we allow big cons only on the 68k machines */ ! 186: /* ! 187: * This is setup by read_begin() and used by big_cons() with using grow_bignum() ! 188: * to make it bigger if needed. ! 189: */ ! 190: #define BIGNUM_BEGIN_SIZE (16) ! 191: static char *bignum_low; /* Lowest char of bignum. */ ! 192: static char *bignum_limit;/* 1st illegal address of bignum. */ ! 193: static char *bignum_high; /* Highest char of bignum, may point to ! 194: (bignum_start-1), never >= bignum_limit. */ ! 195: static void grow_bignum(void); ! 196: #endif /* M68K */ ! 197: /* ! 198: * This is set in read_a_source_file() to the section number of the text section ! 199: * for used by the machine dependent md_assemble() to create line number stabs ! 200: * for assembly instructions in the text section when -g is seen. ! 201: */ ! 202: unsigned long text_nsect = 0; ! 203: ! 204: /* ! 205: * These are the names of the section types used by the .section directive. ! 206: */ ! 207: struct type_name { ! 208: char *name; ! 209: unsigned type; ! 210: }; ! 211: static struct type_name type_names[] = { ! 212: { "regular", S_REGULAR }, ! 213: { "cstring_literals", S_CSTRING_LITERALS }, ! 214: { "4byte_literals", S_4BYTE_LITERALS }, ! 215: { "8byte_literals", S_8BYTE_LITERALS }, ! 216: { "literal_pointers", S_LITERAL_POINTERS }, ! 217: { "non_lazy_symbol_pointers", S_NON_LAZY_SYMBOL_POINTERS }, ! 218: { "lazy_symbol_pointers", S_LAZY_SYMBOL_POINTERS }, ! 219: { "symbol_stubs", S_SYMBOL_STUBS }, ! 220: { "mod_init_funcs", S_MOD_INIT_FUNC_POINTERS }, ! 221: { NULL, 0 } ! 222: }; ! 223: ! 224: /* ! 225: * These are the names of the section attributes used by the .section directive. ! 226: */ ! 227: struct attribute_name { ! 228: char *name; ! 229: unsigned attribute; ! 230: }; ! 231: static struct attribute_name attribute_names[] = { ! 232: { "none", 0 }, ! 233: { "pure_instructions", S_ATTR_PURE_INSTRUCTIONS }, ! 234: { "reloc_at_launch", S_ATTR_RELOC_AT_LAUNCH }, ! 235: { NULL, 0 } ! 236: }; ! 237: ! 238: /* ! 239: * These are the built in sections know to the assembler with a directive. ! 240: * They are known as which segment and section name as well as the type & ! 241: * attribute, and default alignment. ! 242: */ ! 243: struct builtin_section { ! 244: char *directive; ! 245: char *segname; ! 246: char *sectname; ! 247: unsigned long flags; /* type & attribute */ ! 248: unsigned long default_align; ! 249: unsigned long sizeof_stub; ! 250: }; ! 251: static const struct builtin_section builtin_sections[] = { ! 252: /* ! 253: * The text section must be first in this list as it is used by ! 254: * read_a_source_file() to do the equivalent of a .text at the start ! 255: * of the file and for s_builtin_section() to set S_ATTR_PURE_INSTRUCTIONS. ! 256: */ ! 257: { "text", "__TEXT", "__text" }, ! 258: { "const", "__TEXT", "__const" }, ! 259: { "static_const", "__TEXT", "__static_const" }, ! 260: { "cstring", "__TEXT", "__cstring", S_CSTRING_LITERALS }, ! 261: { "literal4", "__TEXT", "__literal4", S_4BYTE_LITERALS, 2 }, ! 262: { "literal8", "__TEXT", "__literal8", S_8BYTE_LITERALS, 3 }, ! 263: { "constructor", "__TEXT", "__constructor" }, ! 264: { "destructor", "__TEXT", "__destructor" }, ! 265: { "fvmlib_init0", "__TEXT", "__fvmlib_init0" }, ! 266: { "fvmlib_init1", "__TEXT", "__fvmlib_init1" }, ! 267: { "mod_init_func", "__TEXT", "__mod_init_func", ! 268: S_MOD_INIT_FUNC_POINTERS, 2 }, ! 269: { "symbol_stub", "__TEXT", "__symbol_stub", ! 270: S_SYMBOL_STUBS | S_ATTR_PURE_INSTRUCTIONS, ! 271: #if defined(M68K) ! 272: 1, 20 ! 273: #endif ! 274: #if defined(I386) ! 275: 0, 16 ! 276: #endif ! 277: #if defined(HPPA) ! 278: 2, 28 ! 279: #endif ! 280: #if defined(SPARC) ! 281: 2, 30 ! 282: #endif ! 283: }, ! 284: { "picsymbol_stub", "__TEXT", "__picsymbol_stub", ! 285: S_SYMBOL_STUBS | S_ATTR_PURE_INSTRUCTIONS, ! 286: #if defined(M68K) ! 287: 1, 24 ! 288: #endif ! 289: #if defined(I386) ! 290: 0, 26 ! 291: #endif ! 292: #if defined(HPPA) ! 293: 2, 32 ! 294: #endif ! 295: #if defined(SPARC) ! 296: 2, 40 ! 297: #endif ! 298: }, ! 299: { "non_lazy_symbol_pointer","__DATA","__nl_symbol_ptr", ! 300: S_NON_LAZY_SYMBOL_POINTERS, 2 }, ! 301: { "lazy_symbol_pointer", "__DATA", "__la_symbol_ptr", ! 302: S_LAZY_SYMBOL_POINTERS, 2 }, ! 303: { "dyld", "__DATA", "__dyld" }, ! 304: { "data", "__DATA", "__data" }, ! 305: { "static_data", "__DATA", "__static_data" }, ! 306: { "objc_class", "__OBJC", "__class" }, ! 307: { "objc_meta_class", "__OBJC", "__meta_class" }, ! 308: { "objc_string_object", "__OBJC", "__string_object" }, ! 309: { "objc_protocol", "__OBJC", "__protocol" }, ! 310: { "objc_cat_cls_meth", "__OBJC", "__cat_cls_meth" }, ! 311: { "objc_cat_inst_meth", "__OBJC", "__cat_inst_meth" }, ! 312: { "objc_cls_meth", "__OBJC", "__cls_meth" }, ! 313: { "objc_inst_meth", "__OBJC", "__inst_meth" }, ! 314: { "objc_message_refs", "__OBJC", "__message_refs", S_LITERAL_POINTERS, 2}, ! 315: { "objc_cls_refs", "__OBJC", "__cls_refs", S_LITERAL_POINTERS, 2}, ! 316: { "objc_class_names", "__OBJC", "__class_names", S_CSTRING_LITERALS }, ! 317: { "objc_module_info", "__OBJC", "__module_info" }, ! 318: { "objc_symbols", "__OBJC", "__symbols" }, ! 319: { "objc_category", "__OBJC", "__category" }, ! 320: { "objc_meth_var_types", "__OBJC", "__meth_var_types", S_CSTRING_LITERALS }, ! 321: { "objc_class_vars", "__OBJC", "__class_vars" }, ! 322: { "objc_instance_vars", "__OBJC", "__instance_vars" }, ! 323: { "objc_meth_var_names", "__OBJC", "__meth_var_names", S_CSTRING_LITERALS }, ! 324: { "objc_selector_strs", "__OBJC", "__selector_strs", S_CSTRING_LITERALS }, ! 325: { 0 } ! 326: }; ! 327: ! 328: /* set up pseudo-op tables */ ! 329: static struct hash_control *po_hash = NULL; ! 330: ! 331: #if !defined(I860) /* i860 has it's own align and org */ ! 332: static void s_align(int value); ! 333: static void s_org(int value); ! 334: #endif ! 335: static void s_private_extern(int value); ! 336: static void s_indirect_symbol(int value); ! 337: static void s_abort(int value); ! 338: static void s_comm(int value); ! 339: static void s_desc(int value); ! 340: static void s_file(int value); ! 341: static void s_fill(int value); ! 342: static void s_lcomm(int value); ! 343: static void s_lsym(int value); ! 344: static void s_set(int value); ! 345: static void s_reference(int value); ! 346: static void s_lazy_reference(int value); ! 347: static void s_include(int value); ! 348: static void s_dump(int value); ! 349: static void s_load(int value); ! 350: static void s_if(int value); ! 351: static void s_elseif(int value); ! 352: static void s_else(int value); ! 353: static void s_endif(int value); ! 354: static void s_macros_on(int value); ! 355: static void s_macros_off(int value); ! 356: static void s_section(int value); ! 357: static void s_zerofill(int value); ! 358: static unsigned long s_builtin_section(const struct builtin_section *s); ! 359: ! 360: /* ! 361: * The machine independent pseudo op table. ! 362: */ ! 363: static const pseudo_typeS pseudo_table[] = { ! 364: #if !defined(I860) /* i860 has it's own align and org */ ! 365: { "align", s_align, 0 }, ! 366: { "org", s_org, 0 }, ! 367: #endif ! 368: #ifndef M88K /* m88k has it's own abs that uses the s_abs() in here */ ! 369: { "abs", s_abs, 0 }, ! 370: #endif ! 371: { "private_extern", s_private_extern, 0}, ! 372: { "indirect_symbol", s_indirect_symbol, 0}, ! 373: { "abort", s_abort, 0 }, ! 374: { "ascii", stringer, 0 }, ! 375: { "asciz", stringer, 1 }, ! 376: { "byte", cons, 1 }, ! 377: { "comm", s_comm, 0 }, ! 378: { "desc", s_desc, 0 }, ! 379: { "double", float_cons, 'd' }, ! 380: { "file", s_file, 0 }, ! 381: { "fill", s_fill, 0 }, ! 382: { "globl", s_globl, 0 }, ! 383: { "lcomm", s_lcomm, 0 }, ! 384: { "line", s_line, 0 }, ! 385: { "long", cons, 4 }, ! 386: { "lsym", s_lsym, 0 }, ! 387: { "section", s_section, 0 }, ! 388: { "zerofill", s_zerofill, 0 }, ! 389: { "set", s_set, 0 }, ! 390: { "short", cons, 2 }, ! 391: { "single", float_cons, 'f' }, ! 392: { "space", s_space, 0 }, ! 393: { "stabd", stab, 'd' }, ! 394: { "stabn", stab, 'n' }, ! 395: { "stabs", stab, 's' }, ! 396: { "reference",s_reference, 0 }, ! 397: { "lazy_reference",s_lazy_reference, 0 }, ! 398: { "include", s_include, 0 }, ! 399: { "macro", s_macro, 0 }, ! 400: { "endmacro", s_endmacro, 0 }, ! 401: { "macros_on",s_macros_on, 0 }, ! 402: { "macros_off",s_macros_off, 0 }, ! 403: { "if", s_if, 0 }, ! 404: { "elseif", s_elseif, 0 }, ! 405: { "else", s_else, 0 }, ! 406: { "endif", s_endif, 0 }, ! 407: { "dump", s_dump, 0 }, ! 408: { "load", s_load, 0 }, ! 409: { NULL } /* end sentinel */ ! 410: }; ! 411: ! 412: /* ! 413: * read_begin() initializes the assember to read assembler source input. ! 414: */ ! 415: void ! 416: read_begin( ! 417: void) ! 418: { ! 419: pseudo_op_begin(); ! 420: macro_begin(); ! 421: obstack_begin(¬es, 5000); ! 422: ! 423: #ifdef M68K /* we allow big cons only on the 68k machines */ ! 424: bignum_low = xmalloc((long)BIGNUM_BEGIN_SIZE); ! 425: bignum_limit = bignum_low + BIGNUM_BEGIN_SIZE; ! 426: #endif ! 427: } ! 428: ! 429: /* ! 430: * pseudo_op_begin() creates a hash table of pseudo ops from the machine ! 431: * independent and machine dependent pseudo op tables. ! 432: */ ! 433: static ! 434: void ! 435: pseudo_op_begin( ! 436: void) ! 437: { ! 438: char *errtxt; ! 439: const pseudo_typeS *pop; ! 440: unsigned long i; ! 441: pseudo_typeS *sections_pseudo_table; ! 442: ! 443: po_hash = hash_new(); ! 444: errtxt = ""; ! 445: for(pop = pseudo_table; pop->poc_name && *errtxt == '\0'; pop++) ! 446: errtxt = hash_insert(po_hash, pop->poc_name, (char *)pop); ! 447: ! 448: for(pop = md_pseudo_table; pop->poc_name && *errtxt == '\0'; pop++) ! 449: errtxt = hash_insert(po_hash, pop->poc_name, (char *)pop); ! 450: ! 451: for(i = 0; builtin_sections[i].directive != NULL; i++) ! 452: ; ! 453: sections_pseudo_table = xmalloc((i + 1) * sizeof(pseudo_typeS)); ! 454: for(i = 0; builtin_sections[i].directive != NULL; i++){ ! 455: sections_pseudo_table[i].poc_name = builtin_sections[i].directive; ! 456: sections_pseudo_table[i].poc_handler = ! 457: (void (*)(int))s_builtin_section; ! 458: sections_pseudo_table[i].poc_val = (int)(builtin_sections + i); ! 459: } ! 460: sections_pseudo_table[i].poc_name = NULL; ! 461: for(pop = (const pseudo_typeS *)sections_pseudo_table; ! 462: pop->poc_name && *errtxt == '\0'; ! 463: pop++) ! 464: errtxt = hash_insert(po_hash, pop->poc_name, (char *)pop); ! 465: ! 466: if(*errtxt != '\0'){ ! 467: as_fatal("error constructing pseudo-op table (%s)", errtxt); ! 468: } ! 469: } ! 470: ! 471: /* ! 472: * The NeXT version of: read_a_source_file() ! 473: * ! 474: * This differs from the GNU version by taking the guts of the GNU ! 475: * read_a_source_file() (with the outer most loop removed) and renaming it ! 476: * parse_a_buffer(). With the NeXT version of read_a_source file simply ! 477: * containing that outer loop and a call to parse_a_buffer(). This is done ! 478: * So that expand_macro() and parse_line_comment() can call parse_a_buffer() ! 479: * with the buffers they create. ! 480: */ ! 481: void ! 482: read_a_source_file( ! 483: char *buffer) /* 1st character of each buffer of lines is here. */ ! 484: { ! 485: cond_stateS starting_cond_state; ! 486: short starting_if_depth; ! 487: ! 488: symbolS *symbolP; ! 489: ! 490: starting_cond_state = the_cond_state; ! 491: starting_if_depth = if_depth; ! 492: ! 493: /* Do not change segments or subsegments if this is a .include */ ! 494: if(doing_include == FALSE){ ! 495: /* ! 496: * This is a new file so switch start as if a .text was seen. This ! 497: * call to s_builtin_section() relys on the fact that the text ! 498: * section is first in the built in sections list. ! 499: */ ! 500: if(flagseen['n'] == FALSE) ! 501: text_nsect = s_builtin_section(builtin_sections); ! 502: ! 503: /* ! 504: * If the -g flag is present generate the lead stabs for this ! 505: * physical file that is not an include file. Each physical file's ! 506: * stabs are enclosed by a pair of source name stabs, N_SO, (one at ! 507: * the begining of the file with the name of the file and one at the ! 508: * end with the name ""). This is seen by nm(1) as: ! 509: * 00000000 - 01 0000 SO {standard input} ! 510: * ... ! 511: * 00000020 - 01 0000 SO ! 512: * To make the debugger work line numbers stabs, N_SLINE, must be ! 513: * contained "in a function" (after a function stab, N_FUN). To ! 514: * make a function stab work it must have a type number. Since type ! 515: * numbers 1 and 2 (the 1 in "int:t1=..." and the 2 in "char:t2=..." ! 516: * are "magic" to the debugger we use type 3 for the types of the ! 517: * function stabs we generate for each text label (see the routine ! 518: * make_stab_for_symbol() in symbols.c). So at lead stabs at the ! 519: * begining of each physical file include three type stabs, L_LSYM ! 520: * with the correct symbol name. The since we must have the types ! 521: * 1 and 2 they are just what the 'C' would produce but we don't ! 522: * use them. Type 3 is the void type like the 'C' compiler would ! 523: * produce which we use for the function stabs' type. These three ! 524: * look like this to nm(1): ! 525: * 00000000 - 00 0000 LSYM int:t1=r1;-2147483648;2147483647; ! 526: * 00000000 - 00 0000 LSYM char:t2=r2;0;127; ! 527: * 00000000 - 00 0000 LSYM void:t3=3 ! 528: * ! 529: * Then for each text label we see, make_stab_for_symbol() will ! 530: * generate a stab like this (for the example lable _main): ! 531: * 00000000 - 01 0007 FUN _main:F3 ! 532: * where the 'F' in F3 is an upper case 'F' for global labels and ! 533: * a lower case 'f' for non globals. ! 534: * ! 535: * Then for each instruction we assemble in the text we generate ! 536: * a line number, S_LINE, stab (see md_assembler in m68k.c, m88k.c ! 537: * etc). These look like: ! 538: * 00000000 - 01 0008 SLINE ! 539: * where the 0008 is the line number. ! 540: */ ! 541: if(flagseen['g']){ ! 542: symbolP = symbol_new( ! 543: physical_input_file, ! 544: 100 /* N_SO */, ! 545: text_nsect, ! 546: 0, ! 547: obstack_next_free(&frags) - frag_now->fr_literal, ! 548: frag_now); ! 549: symbolP = symbol_new( ! 550: "int:t1=r1;-2147483648;2147483647;", ! 551: 128 /* N_LSYM */, ! 552: 0,0,0, ! 553: &zero_address_frag); ! 554: symbolP = symbol_new( ! 555: "char:t2=r2;0;127;", ! 556: 128 /* N_LSYM */, ! 557: 0,0,0, ! 558: &zero_address_frag); ! 559: symbolP = symbol_new( ! 560: "void:t3=3", ! 561: 128 /* N_LSYM */, ! 562: 0,0,0, ! 563: &zero_address_frag); ! 564: } ! 565: } ! 566: else{ ! 567: /* ! 568: * If we are now reading an include file we will bracket it's ! 569: * stabs with a pair of: ! 570: * 00000010 - 01 0000 SOL include_file ! 571: * ... ! 572: * 0000001c - 01 0000 SOL previous_file ! 573: * We generate the first N_SOL here and the one for the ! 574: * previous_file in s_include() in read.c. ! 575: * ! 576: * CAVAT: This will only work if the include file starts off in the ! 577: * (__TEXT,__text) sections and ends in the (__TEXT,__text) section. ! 578: */ ! 579: if(flagseen['g'] && frchain_now->frch_nsect == text_nsect){ ! 580: symbolP = symbol_new( ! 581: physical_input_file, ! 582: 132 /* N_SOL */, ! 583: text_nsect, ! 584: 0, ! 585: obstack_next_free(&frags) - frag_now->fr_literal, ! 586: frag_now); ! 587: } ! 588: } ! 589: ! 590: while((buffer_limit = input_scrub_next_buffer(&buffer)) != NULL) ! 591: parse_a_buffer(buffer); ! 592: ! 593: if(the_cond_state.the_cond != starting_cond_state.the_cond || ! 594: the_cond_state.ignore != starting_cond_state.ignore|| ! 595: if_depth != starting_if_depth) ! 596: as_warn("file contains unmatched .ifs or .elses"); ! 597: ! 598: if(doing_include == FALSE){ ! 599: /* See the comment at the top of this routine for a description of ! 600: what is going on here */ ! 601: if(flagseen['n'] == FALSE) ! 602: text_nsect = s_builtin_section(builtin_sections); ! 603: if(flagseen['g']){ ! 604: (void)symbol_new( ! 605: "", ! 606: 100 /* N_SO */, ! 607: text_nsect, ! 608: 0, ! 609: obstack_next_free(&frags) - frag_now->fr_literal, ! 610: frag_now); ! 611: } ! 612: } ! 613: } ! 614: ! 615: /* ! 616: * parse_a_buffer() operates on a buffer of lines. It drives the ! 617: * parsing of lines of assembly code. The lines are assumed to be "well formed" ! 618: * assembly so the syntax recognized in here is that produced by the output of ! 619: * the assembly preprocessor (app) or by the compiler when it produces a file ! 620: * that starts with "#NO_APP\n". A "well formed" assembly is lines with exactly ! 621: * zero or one leading "well formed space character" (' ', '\t' or '\f') ! 622: * followed by lines of: ! 623: * zero or more lables (a name or a digit followed by a colon) ! 624: * each followed by zero or one "well formed space character" ! 625: * exactly one of the following followed by a logicial end of line: ! 626: * a pseudo opcode ! 627: * followed by zero or one space (' ') characters and it's ! 628: * arguments (the space is required when the first ! 629: * character of the first argument could be part of a name) ! 630: * a macro to be expanded ! 631: * a machine opcode ! 632: * a null statement ! 633: * an assignment to a symbol ! 634: * a full line comment (in the case of "well formed" assembly it ! 635: * must be "#APP\n" of a collection of lines ! 636: * wrapped in "#APP\n ... #NO_APP\n") ! 637: * ! 638: * input: ! 639: * buffer pointer to the start of the buffer of lines ! 640: * (passed as an argument) ! 641: * buffer_limit pointer to the end of the buffer of lines, that is the ! 642: * the character it points to is NOT part of the buffer ! 643: * (buffer_limit is declared in this file) ! 644: * ! 645: * Assumptions about the buffer of lines: ! 646: * buffer[-1] == '\n' as done in input-scrub.c with the cpp macro ! 647: * BEFORE_STRING ("\n") ! 648: * buffer_limit[-1] == '\n' also as done in input-scrub.c which handles ! 649: * partial lines internally to itself and always ! 650: * passes back a buffer of complete lines. ! 651: * ! 652: * input/output: (for other parsing routines) ! 653: * input_line_pointer pointer to the next thing in the buffer after ! 654: * what has been recognized (a global) ! 655: */ ! 656: static ! 657: void ! 658: parse_a_buffer( ! 659: char *buffer) ! 660: { ! 661: char c; /* contains the first non-space character the current ! 662: word used to figure out what it is */ ! 663: char *s; /* points to a name with character after the name ! 664: replaced with a '\0' so it is a 'C' string */ ! 665: char after_name; /* contains that first character after a name that ! 666: got replaced with a '\0' */ ! 667: char *after_name_pointer;/* points to the end of the name where the '\0' is ! 668: for error use only */ ! 669: char end_of_line; /* contains an end of line character that got replaced ! 670: with a '\0' */ ! 671: char *start_of_line;/* points to the locical start of line we're parsing, ! 672: used only for macro expansion */ ! 673: pseudo_typeS *pop; /* pointer to a pseudo op stucture returned by ! 674: hash_find(po_hash, s+1) to determine if it is one */ ! 675: char *the_macro; /* pointer to a macro name returned by ! 676: hash_find(ma_hash, s) to determine if it is one */ ! 677: int digit_value; /* the value of a digit label as an integer, 1: == 1 */ ! 678: ! 679: /* since this is a buffer of full lines it must end in a new line */ ! 680: know(buffer_limit[-1] == '\n'); ! 681: ! 682: input_line_pointer = buffer; ! 683: ! 684: /* while we have more of this buffer to parse keep parsing */ ! 685: while(input_line_pointer < buffer_limit){ ! 686: /* ! 687: * At the top of this loop we know that we just parsed a label or we ! 688: * are at the beginning of a logical line (since their can be more ! 689: * than one label on a line). start_of_line is only used by ! 690: * expand_macro() ! 691: */ ! 692: start_of_line = input_line_pointer; ! 693: ! 694: /* ! 695: * If we are not counting lines (as in the case when called by ! 696: * expand_macro() ) and we just previously scaned over a newline ! 697: * (a physical end of line) bump the line counters (see the comments ! 698: * at the head of this routine about "assumptions about the buffer" ! 699: * and why it is safe to index input_line_pointer by -1. ! 700: */ ! 701: if(count_lines == TRUE && input_line_pointer[-1] == '\n') ! 702: bump_line_counters (); ! 703: ! 704: /* ! 705: * We expect a "well-formed" assembler statement. This means it was ! 706: * processed by app or produced by a compiler where the file started ! 707: * with a leading "#APP\n". A "well-formed" statement allows zero ! 708: * or one leading white space characters. ! 709: */ ! 710: c = *input_line_pointer; ! 711: input_line_pointer++; ! 712: if(c == '\t' || c == ' ' || c=='\f'){ ! 713: c = *input_line_pointer; ! 714: input_line_pointer++; ! 715: } ! 716: know(c != ' '); /* No further leading whitespace. */ ! 717: /* ! 718: * c contains the 1st significant character, *input_line_pointer ! 719: * points after that character. ! 720: */ ! 721: ! 722: /* ! 723: * look for the begining of a name which could be one of the ! 724: * following assembly statements: ! 725: * A pseudo opcode and locical end of line ! 726: * A macro to be expanded and locical end of line ! 727: * A machine opcode and locical end of line ! 728: * A user-defined label (name not digit)(no end of line needed) ! 729: * At NeXT labels can be enclosed in ""'s so that Objective-C like ! 730: * names (with spaces and colons) can be part of a name, the ! 731: * routine get_symbol_end() knows about this. ! 732: */ ! 733: if(is_name_beginner(c) || c == '"'){ ! 734: if( c == '"') ! 735: s = input_line_pointer--; ! 736: else ! 737: s = --input_line_pointer; ! 738: after_name = get_symbol_end(); /* name's delimiter */ ! 739: after_name_pointer = input_line_pointer; ! 740: /* ! 741: * after_name is the character after symbol. That character's ! 742: * place in the input line is now '\0',done by get_symbol_end(). ! 743: * s points to the beginning of the symbol (in the case of a ! 744: * pseudo-op, *s == '.'). *input_line_pointer == '\0' where ! 745: * after_name was. after_name_pointer is recorded so it their ! 746: * is an error after the line has been restored the '\0' can ! 747: * be reset and the name printed. ! 748: */ ! 749: ! 750: /* ! 751: * Look for a name that should be a pseudo op. That is it is ! 752: * not a user defined label or an assignment to a symbol name. ! 753: * This must be done so such thing as ".foo:" and ".bar=1" are ! 754: * not mistaken for illegal pseudo ops and that something like ! 755: * ".long: .long 1" creates a symbol named ".long". ! 756: */ ! 757: if(*s == '.' && ! 758: (after_name != ':' && ! 759: after_name != '=' && ! 760: !((after_name == ' ' || after_name == '\t') && ! 761: input_line_pointer[1] == '=') ) ){ ! 762: /* ! 763: * Lookup what should be a pseudo op and then restore the ! 764: * line. ! 765: */ ! 766: pop = (pseudo_typeS *)hash_find(po_hash, s+1); ! 767: *input_line_pointer = after_name; ! 768: ! 769: /* ! 770: * A pseudo op must be followed by character that is not ! 771: * part of a name so it can be parsed. If their is a first ! 772: * argument that could start with a character in a name then ! 773: * one "well formed space" (space or a tab) must follow the ! 774: * pseudo op (otherwise the space is optional). ! 775: */ ! 776: if(after_name == ' ' || after_name == '\t') ! 777: input_line_pointer++; ! 778: ! 779: /* ! 780: * Now the current state of the line is the after_name has ! 781: * been placed back in the line (the line is restored) and ! 782: * input_line_pointer is at the start of the first argument ! 783: * of the pseudo op (if any). ! 784: */ ! 785: if(the_cond_state.ignore){ ! 786: /* ! 787: * When ignoring a block of code during conditional ! 788: * assembly we can't ignore .if, .else, and .endif ! 789: * pseudo ops. ! 790: */ ! 791: if(pop != NULL && ! 792: ( (pop->poc_handler == s_if) || ! 793: (pop->poc_handler == s_elseif) || ! 794: (pop->poc_handler == s_else) || ! 795: (pop->poc_handler == s_endif) ) ) ! 796: (*pop->poc_handler)(pop->poc_val); ! 797: else ! 798: totally_ignore_line(); ! 799: } ! 800: else if(macro_name){ ! 801: /* ! 802: * When defining a macro we can't ignore .endmacro ! 803: * pseudo ops. ! 804: */ ! 805: if(pop != NULL && ! 806: pop->poc_handler == s_endmacro) ! 807: (*pop->poc_handler)(pop->poc_val); ! 808: else ! 809: add_to_macro_definition(start_of_line); ! 810: } ! 811: else{ ! 812: if(pop != NULL) ! 813: (*pop->poc_handler)(pop->poc_val); ! 814: else{ ! 815: after_name = *after_name_pointer; ! 816: *after_name_pointer = '\0'; ! 817: /* ! 818: * If macros are on see if this is a use of a macro ! 819: * otherwise it is an unknown pseudo op. ! 820: */ ! 821: if(macros_on == TRUE && ! 822: (the_macro = hash_find(ma_hash, s)) != NULL){ ! 823: *after_name_pointer = after_name; ! 824: expand_macro(the_macro); ! 825: } ! 826: else{ ! 827: as_warn ("Unknown pseudo-op: %s", s); ! 828: *after_name_pointer = after_name; ! 829: ignore_rest_of_line(); ! 830: } ! 831: } ! 832: } ! 833: continue; ! 834: ! 835: } /* if(*s == '.' && ... ) */ ! 836: ! 837: /* ! 838: * If we are in a conditional and the state is that we are now ! 839: * not including lines to be assembled then ignore the line. ! 840: */ ! 841: if(the_cond_state.ignore){ ! 842: *input_line_pointer = after_name; ! 843: totally_ignore_line(); ! 844: } ! 845: /* ! 846: * If we are in the state of defining a macro then take the line ! 847: * for the macro definition. ! 848: */ ! 849: else if(macro_name != NULL){ ! 850: *input_line_pointer = after_name; ! 851: add_to_macro_definition(start_of_line); ! 852: } ! 853: /* ! 854: * Look for a user defined label. ! 855: */ ! 856: else if(after_name == ':'){ ! 857: colon(s); ! 858: #ifdef I860 ! 859: /* ! 860: * Intel :: feature, which makes the label global if ! 861: * followed by two "::"'s . This is ifdef'ed in so their ! 862: * is no else cause thus the slightly odd logic. ! 863: */ ! 864: if(input_line_pointer[1] == ':'){ ! 865: struct symbol *symbolP; ! 866: ! 867: symbolP = symbol_find_or_make(s); ! 868: symbolP->sy_type |= N_EXT; /* make symbol name global */ ! 869: *input_line_pointer = ':'; /* Restore first ':' */ ! 870: input_line_pointer++; /* step over first ':' */ ! 871: } ! 872: #endif ! 873: /* put ':' back for error messages and step over it */ ! 874: *input_line_pointer = ':'; ! 875: input_line_pointer++; ! 876: } ! 877: /* ! 878: * Parse the assignment to a symbol. The syntax for this is ! 879: * <symbol><equal><expression>. ! 880: */ ! 881: else if(after_name == '=' || ! 882: ((after_name == ' ' || after_name == '\t') && ! 883: input_line_pointer[1] == '=')){ ! 884: equals(s); ! 885: demand_empty_rest_of_line(); ! 886: } ! 887: /* ! 888: * If macros are on see if this is a use of a macro. ! 889: */ ! 890: else if(macros_on == TRUE && ! 891: (the_macro = hash_find(ma_hash, s)) != NULL){ ! 892: *input_line_pointer = after_name; ! 893: expand_macro(the_macro); ! 894: } ! 895: /* ! 896: * Now assume it is a machine instruction and if not it ! 897: * will be handled as an error. Machine instructions must be ! 898: * one to a line. ! 899: */ ! 900: else{ ! 901: *input_line_pointer = after_name; ! 902: while(is_end_of_line[(int)*input_line_pointer] == FALSE) ! 903: input_line_pointer ++; ! 904: end_of_line = *input_line_pointer; ! 905: *input_line_pointer = '\0'; ! 906: md_assemble(s); ! 907: *input_line_pointer = end_of_line; ! 908: input_line_pointer++; ! 909: } ! 910: /* ! 911: * At this point we have parsed all things that could have ! 912: * started with a name. Since one of these things (user defined ! 913: * lables could appear more than once on a line we do a continue ! 914: * here and start parsing as if at the begining of another ! 915: * logicial line. ! 916: */ ! 917: continue; ! 918: ! 919: } /* if(is_name_beginner(c) || c == '"') */ ! 920: ! 921: /* empty statement */ ! 922: if(is_end_of_line[(int)c]) ! 923: continue; ! 924: ! 925: /* ! 926: * If we are in a conditional and the state is that we are now ! 927: * not including lines to be assembled then ignore the line. ! 928: */ ! 929: if(the_cond_state.ignore){ ! 930: totally_ignore_line(); ! 931: continue; ! 932: } ! 933: ! 934: /* ! 935: * If we are in the state of defining a macro then take the line ! 936: * for the macro definition. ! 937: */ ! 938: if(macro_name != NULL){ ! 939: add_to_macro_definition(start_of_line); ! 940: continue; ! 941: } ! 942: ! 943: /* local label ("4:") */ ! 944: if(isdigit(c)){ ! 945: digit_value = c - '0'; ! 946: if(*input_line_pointer++ == ':' ){ ! 947: local_colon(digit_value); ! 948: } ! 949: else{ ! 950: as_warn("Spurious digit %d.", digit_value); ! 951: input_line_pointer--; ! 952: ignore_rest_of_line(); ! 953: } ! 954: continue; ! 955: } ! 956: ! 957: /* ! 958: * The only full line comment that should make it here is the first ! 959: * of the pair of "#APP\n ... #NO_APP\n" that the compiler uses to ! 960: * wrap around asm() statements. If that is the case then ! 961: * parse_line_comment() creates a buffer with those lines in it and ! 962: * calls parse_a_buffer() with that buffer. Then returns here ! 963: * skiping over that part of the current buffer. ! 964: */ ! 965: if(c != '\0' && strchr(md_line_comment_chars, c) != NULL){ ! 966: parse_line_comment(&buffer); ! 967: continue; ! 968: } ! 969: ! 970: as_warn("Junk character %d.",c); ! 971: ignore_rest_of_line(); ! 972: ! 973: } /* while(input_line_pointer < buffer_limit) */ ! 974: } ! 975: ! 976: /* ! 977: * parse_line_comment() parses a line comment for parse_a_buffer(). Since ! 978: * parse_a_buffer() only operates on "well formed" assembly the only legal ! 979: * line comment that should appear is a "#APP\n ... #NO_APP\n" pair which ! 980: * tells us to scrub the characters between them and then parse them. ! 981: */ ! 982: static ! 983: void ! 984: parse_line_comment( ! 985: char **buffer) ! 986: { ! 987: char *s; ! 988: char *ends; ! 989: ! 990: char *new_buf; ! 991: char *new_tmp; ! 992: int new_length; ! 993: ! 994: char *tmp_buf; ! 995: char *old_input_line_pointer; ! 996: char *old_buffer_limit; ! 997: ! 998: ! 999: /* parse_a_buffer should never see any line comment if app is on */ ! 1000: know(preprocess == FALSE); ! 1001: ! 1002: s = input_line_pointer; ! 1003: /* This must be a #APP\n line comment if not ignore it */ ! 1004: if(strncmp(s,"APP\n",4) != 0) ! 1005: return; ! 1006: ! 1007: if(count_lines == TRUE) ! 1008: bump_line_counters(); ! 1009: s += sizeof("APP\n") - 1; ! 1010: ! 1011: /* ! 1012: * Search for the matching #NO_APP\n in this buffer, if it is found ! 1013: * in this buffer the un-scrubed characters between the "#APP\n" and ! 1014: * "#NO_APP\n" start where s is pointing to and end where ends is ! 1015: * pointing to. ! 1016: */ ! 1017: ends = strstr(s, "#NO_APP\n"); ! 1018: ! 1019: tmp_buf = NULL; ! 1020: if(ends == NULL){ ! 1021: /* The matching #NO_APP\n for the #APP\n wasn't in this buffer. */ ! 1022: int tmp_len; ! 1023: int num; ! 1024: ! 1025: /* ! 1026: * First create a temporary place (tmp_buf of size tmp_len) to ! 1027: * collect the un-scrubbed characters between the "#APP\n" and the ! 1028: * "#NO_APP\n" (or end of file) when we find it in some buffer. ! 1029: */ ! 1030: tmp_len = buffer_limit - s; ! 1031: tmp_buf = xmalloc(tmp_len); ! 1032: ! 1033: /* ! 1034: * Copy the end of the buffer that contains the first part of ! 1035: * the un-scrubbed contents starting just after the "#APP\n". ! 1036: * This is so the the current buffer (buffer) can be used to ! 1037: * collect the the rest of the un-scrubbed contents and to find ! 1038: * the matching "#NO_APP\n". ! 1039: */ ! 1040: memcpy(tmp_buf, s, tmp_len); ! 1041: ! 1042: /* ! 1043: * This loop collects the remaining un-scrubed contents between ! 1044: * "#APP\n" and the "#NO_APP\n" into tmp_buf (adjusting tmp_len) ! 1045: * and looks for the matching "#NO_APP\n". ! 1046: */ ! 1047: do{ ! 1048: buffer_limit = input_scrub_next_buffer(buffer); ! 1049: /* ! 1050: * We treat runing into the end of the file as if it was the ! 1051: * "#NO_APP" we were looking for. ! 1052: */ ! 1053: if(buffer_limit == NULL) ! 1054: break; ! 1055: ! 1056: ends = strstr(*buffer, "#NO_APP\n"); ! 1057: if(ends != NULL) ! 1058: num = ends - *buffer; ! 1059: else ! 1060: num = buffer_limit - *buffer; ! 1061: ! 1062: tmp_buf = xrealloc(tmp_buf, tmp_len + num); ! 1063: memcpy(tmp_buf + tmp_len, *buffer, num); ! 1064: tmp_len += num; ! 1065: }while(ends == NULL); ! 1066: ! 1067: /* ! 1068: * Now set up buffer, buffer_limit and input_line_pointer be past ! 1069: * all the characters of the "#APP\n ... #NO_APP\n" set so that ! 1070: * when we return parsing will be picked up from their. ! 1071: */ ! 1072: if(ends != NULL) ! 1073: input_line_pointer = ends + sizeof("#NO_APP\n") - 1; ! 1074: else{ ! 1075: input_line_pointer = *buffer; ! 1076: buffer_limit = *buffer; ! 1077: } ! 1078: ! 1079: /* ! 1080: * Now set s to the start, and ends to the end of the un-scrubed ! 1081: * contents of the collected characters between the "#APP\n" and ! 1082: * "#NO_APP\n" pair. ! 1083: */ ! 1084: s = tmp_buf; ! 1085: ends = s + tmp_len; ! 1086: } ! 1087: else{ ! 1088: /* ! 1089: * The matching "#NO_APP\n" was in the buffer as we were called so ! 1090: * s is the start, and ends is the end of the un-scrubed contents ! 1091: * of the characters between the "#APP\n" and "#NO_APP\n" pair. ! 1092: * Now to set up buffer, buffer_limit and input_line_pointer be past ! 1093: * all the characters of the "#APP\n ... #NO_APP\n" set so that ! 1094: * when we return parsing will be picked up from their all that has ! 1095: * to be done is move the input_line_pointer past the "#NO_APP\n". ! 1096: */ ! 1097: input_line_pointer = ends + sizeof("#NO_APP\n") - 1; ! 1098: } ! 1099: ! 1100: /* ! 1101: * Now that we have the un-scrubed characters beween s and ends setup ! 1102: * to scrub them into a new buffer (new_buf of size new_length to ! 1103: * new_tmp). ! 1104: */ ! 1105: new_length = 100; ! 1106: new_buf = xmalloc(new_length); ! 1107: new_tmp = new_buf; ! 1108: *new_tmp++ = '\n'; /* place leading \n in buffer for parse_a_buffer */ ! 1109: ! 1110: scrub_string = s; ! 1111: scrub_last_string = ends; ! 1112: for(;;){ ! 1113: int c; ! 1114: ! 1115: c = do_scrub_next_char(scrub_from_string, scrub_to_string); ! 1116: if(c == EOF) ! 1117: break; ! 1118: *new_tmp++ = c; ! 1119: if(new_tmp == new_buf + new_length){ ! 1120: new_buf = xrealloc(new_buf, new_length + 100); ! 1121: new_tmp = new_buf + new_length; ! 1122: new_length += 100; ! 1123: } ! 1124: } ! 1125: *new_tmp = '\n'; /* place trailing \n in buffer for parse_a_buffer */ ! 1126: ! 1127: /* ! 1128: * If we used a temporary buffer to collect the un-scrubbed characters ! 1129: * it is no longer needed and can be free()'ed. ! 1130: */ ! 1131: if(tmp_buf != NULL) ! 1132: free(tmp_buf); ! 1133: ! 1134: /* ! 1135: * Now we are ready to recursively call parse_a_buffer() with our buffer ! 1136: * of scrubed characters. So save the state of parse_a_buffer() and set ! 1137: * it up with our buffer of scrubed characters. ! 1138: */ ! 1139: old_input_line_pointer = input_line_pointer; ! 1140: old_buffer_limit = buffer_limit; ! 1141: ! 1142: input_line_pointer = new_buf; ! 1143: buffer_limit = new_tmp; ! 1144: parse_a_buffer(new_buf); ! 1145: ! 1146: /* ! 1147: * Free the buffer that held the scrubbed characters ! 1148: */ ! 1149: free(new_buf); ! 1150: ! 1151: /* ! 1152: * After coming back from our recursive call parse_a_buffer() we want ! 1153: * resume parsing after the "#NO_APP\n". So bump the line counters ! 1154: * for the "#NO_APP\n" and restore the state so we can return to ! 1155: * parse_a_buffer(). ! 1156: */ ! 1157: if(count_lines == TRUE) ! 1158: bump_line_counters(); ! 1159: input_line_pointer = old_input_line_pointer; ! 1160: buffer_limit = old_buffer_limit; ! 1161: ! 1162: return; ! 1163: } ! 1164: ! 1165: /* ! 1166: * s_abort() implements the pseudo op: ! 1167: * .abort [ "abort_string" ] ! 1168: */ ! 1169: static ! 1170: void ! 1171: s_abort( ! 1172: int value) ! 1173: { ! 1174: char *p; ! 1175: ! 1176: p = input_line_pointer; ! 1177: while(is_end_of_line[(int)*p] == FALSE) ! 1178: p++; ! 1179: *p = '\0'; ! 1180: ! 1181: as_fatal(".abort %s detected. Assembly stopping.", input_line_pointer); ! 1182: } ! 1183: ! 1184: #if !defined(I860) /* i860 has it's own align and org */ ! 1185: /* ! 1186: * s_align() implements the pseudo op ! 1187: * .align expression [ , fill_expression ] ! 1188: */ ! 1189: static ! 1190: void ! 1191: s_align( ! 1192: int value) ! 1193: { ! 1194: int temp; ! 1195: long temp_fill; ! 1196: ! 1197: temp = get_absolute_expression(); ! 1198: #define MAX_ALIGNMENT (15) ! 1199: if(temp > MAX_ALIGNMENT) ! 1200: as_warn("Alignment too large: %d. assumed.", temp = MAX_ALIGNMENT); ! 1201: else if(temp < 0){ ! 1202: as_warn("Alignment negative. 0 assumed."); ! 1203: temp = 0; ! 1204: } ! 1205: if(*input_line_pointer == ','){ ! 1206: input_line_pointer ++; ! 1207: temp_fill = get_absolute_expression (); ! 1208: } ! 1209: else ! 1210: temp_fill = 0; ! 1211: ! 1212: /* Only make a frag if we HAVE to. . . */ ! 1213: if(temp != 0) ! 1214: frag_align(temp, (int)temp_fill); ! 1215: ! 1216: /* ! 1217: * If this alignment is larger than any previous alignment then this ! 1218: * becomes the section's alignment. ! 1219: */ ! 1220: if(frchain_now->frch_section.align < temp) ! 1221: frchain_now->frch_section.align = temp; ! 1222: ! 1223: demand_empty_rest_of_line(); ! 1224: } ! 1225: #endif /* !defined(I860) i860 has it's own align and org */ ! 1226: ! 1227: /* ! 1228: * s_comm() implements the pseudo op: ! 1229: * .comm name , expression ! 1230: */ ! 1231: static ! 1232: void ! 1233: s_comm( ! 1234: int value) ! 1235: { ! 1236: char *name; ! 1237: char c; ! 1238: char *p; ! 1239: int temp; ! 1240: symbolS *symbolP; ! 1241: ! 1242: if(*input_line_pointer == '"') ! 1243: name = input_line_pointer + 1; ! 1244: else ! 1245: name = input_line_pointer; ! 1246: c = get_symbol_end(); ! 1247: /* just after name is now '\0' */ ! 1248: p = input_line_pointer; ! 1249: *p = c; ! 1250: SKIP_WHITESPACE(); ! 1251: if(*input_line_pointer != ','){ ! 1252: as_warn("Expected comma after symbol-name"); ! 1253: ignore_rest_of_line(); ! 1254: return; ! 1255: } ! 1256: input_line_pointer++; /* skip ',' */ ! 1257: if((temp = get_absolute_expression ()) < 0){ ! 1258: as_warn(".COMMon length (%d.) <0! Ignored.", temp); ! 1259: ignore_rest_of_line(); ! 1260: return; ! 1261: } ! 1262: *p = 0; ! 1263: symbolP = symbol_find_or_make(name); ! 1264: *p = c; ! 1265: if((symbolP->sy_type & N_TYPE) != N_UNDF || ! 1266: symbolP->sy_other != 0 || ! 1267: symbolP->sy_desc != 0) { ! 1268: as_warn("Ignoring attempt to re-define symbol"); ! 1269: ignore_rest_of_line(); ! 1270: return; ! 1271: } ! 1272: if(symbolP->sy_value != 0){ ! 1273: if(symbolP->sy_value != temp) ! 1274: as_warn("Length of .comm \"%s\" is already %ld. Not changed " ! 1275: "to %d.", symbolP->sy_name, symbolP->sy_value, temp); ! 1276: } ! 1277: else{ ! 1278: symbolP -> sy_value = temp; ! 1279: symbolP -> sy_type |= N_EXT; ! 1280: } ! 1281: know(symbolP->sy_frag == &zero_address_frag); ! 1282: demand_empty_rest_of_line(); ! 1283: } ! 1284: ! 1285: /* ! 1286: * s_desc() implements the pseudo op: ! 1287: * .desc name , expression ! 1288: * sets the n_desc field of a symbol. ! 1289: */ ! 1290: static ! 1291: void ! 1292: s_desc( ! 1293: int value) ! 1294: { ! 1295: char *name; ! 1296: char c; ! 1297: char *p; ! 1298: symbolS *symbolP; ! 1299: int temp; ! 1300: ! 1301: if(*input_line_pointer == '"') ! 1302: name = input_line_pointer + 1; ! 1303: else ! 1304: name = input_line_pointer; ! 1305: c = get_symbol_end(); ! 1306: p = input_line_pointer; ! 1307: symbolP = symbol_table_lookup(name); ! 1308: *p = c; ! 1309: SKIP_WHITESPACE(); ! 1310: if(*input_line_pointer != ','){ ! 1311: *p = 0; ! 1312: as_warn("Expected comma after name \"%s\"", name); ! 1313: *p = c; ! 1314: ignore_rest_of_line(); ! 1315: } ! 1316: else{ ! 1317: input_line_pointer++; ! 1318: temp = get_absolute_expression(); ! 1319: *p = 0; ! 1320: symbolP = symbol_find_or_make(name); ! 1321: *p = c; ! 1322: symbolP->sy_desc = temp; ! 1323: } ! 1324: demand_empty_rest_of_line(); ! 1325: } ! 1326: ! 1327: /* ! 1328: * s_file() implements the pseudo op: ! 1329: * .file name [ level_number ] ! 1330: * the level number is generated by /lib/cpp and is just ignored. ! 1331: */ ! 1332: static ! 1333: void ! 1334: s_file( ! 1335: int value) ! 1336: { ! 1337: char *s; ! 1338: int length; ! 1339: struct symbol *symbolP; ! 1340: ! 1341: /* Some assemblers tolerate immediately following '"' */ ! 1342: if((s = demand_copy_string(&length))){ ! 1343: SKIP_WHITESPACE(); ! 1344: if(*input_line_pointer >= '0' && *input_line_pointer <= '9'){ ! 1345: while(*input_line_pointer >= '0' && ! 1346: *input_line_pointer <= '9') ! 1347: input_line_pointer++; ! 1348: } ! 1349: new_logical_line(s, -1); ! 1350: demand_empty_rest_of_line(); ! 1351: ! 1352: /* ! 1353: * This is to generate stabs for debugging assembly code. ! 1354: * See the comments about stabs in read_a_source_file() ! 1355: * for a description of what is going on here. ! 1356: */ ! 1357: if(flagseen['g'] && frchain_now->frch_nsect == text_nsect){ ! 1358: symbolP = symbol_new( ! 1359: logical_input_file, ! 1360: 132 /* N_SOL */, ! 1361: text_nsect, ! 1362: 0, ! 1363: obstack_next_free(&frags) - frag_now->fr_literal, ! 1364: frag_now); ! 1365: } ! 1366: } ! 1367: } ! 1368: ! 1369: /* ! 1370: * s_fill() implements the pseudo op: ! 1371: * .fill repeat_expression , fill_size , fill_expression ! 1372: */ ! 1373: static ! 1374: void ! 1375: s_fill( ! 1376: int value) ! 1377: { ! 1378: long temp_repeat; ! 1379: long temp_size; ! 1380: long temp_fill; ! 1381: char *p; ! 1382: ! 1383: if(get_absolute_expression_and_terminator(&temp_repeat) != ','){ ! 1384: input_line_pointer--; /* Backup over what was not a ','. */ ! 1385: as_warn("Expect comma after rep-size in .fill"); ! 1386: ignore_rest_of_line(); ! 1387: return; ! 1388: } ! 1389: if(get_absolute_expression_and_terminator(&temp_size) != ','){ ! 1390: input_line_pointer--; /* Backup over what was not a ','. */ ! 1391: as_warn("Expected comma after size in .fill"); ! 1392: ignore_rest_of_line(); ! 1393: return; ! 1394: } ! 1395: /* ! 1396: * This is to be compatible with BSD 4.2 AS, not for any rational ! 1397: * reason. ! 1398: */ ! 1399: #define BSD_FILL_SIZE_CROCK_8 (8) ! 1400: if(temp_size > BSD_FILL_SIZE_CROCK_8){ ! 1401: as_warn(".fill size clamped to %d.", BSD_FILL_SIZE_CROCK_8); ! 1402: temp_size = BSD_FILL_SIZE_CROCK_8 ; ! 1403: } ! 1404: if(temp_size < 0){ ! 1405: as_warn("Size negative: .fill ignored."); ! 1406: temp_size = 0; ! 1407: } ! 1408: /* ! 1409: * bug fix, if md_number_to_chars() is called with something other than ! 1410: * 1,2 or 4 it calls abort(). So we don't let the size be something ! 1411: * like 3. Bug #13017. ! 1412: */ ! 1413: else if(temp_size != 0 && ! 1414: temp_size != 1 && ! 1415: temp_size != 2 && ! 1416: temp_size != 4){ ! 1417: as_warn("Repeat must be 0,1,2 or 4, .fill ignored"); ! 1418: temp_size = 0; ! 1419: } ! 1420: else if(temp_repeat <= 0){ ! 1421: as_warn("Repeat < 0, .fill ignored"); ! 1422: temp_size = 0; ! 1423: } ! 1424: temp_fill = get_absolute_expression(); ! 1425: /* ! 1426: * Note: .fill (),0 emits no frag (since we are asked to .fill 0 bytes) ! 1427: * but emits no error message because it seems a legal thing to do. ! 1428: * It is a degenerate case of .fill but could be emitted by a compiler. ! 1429: */ ! 1430: if(temp_size != 0){ ! 1431: p = frag_var(rs_fill, ! 1432: (int)temp_size, ! 1433: (int)temp_size, ! 1434: (relax_substateT)0, ! 1435: (symbolS *)0, ! 1436: temp_repeat, ! 1437: (char *)0); ! 1438: memset(p, '\0', (int)temp_size); ! 1439: /* ! 1440: * The magic number BSD_FILL_SIZE_CROCK_4 is from BSD 4.2 VAX ! 1441: * flavoured AS. The following bizzare behaviour is to be ! 1442: * compatible with above. I guess they tried to take up to 8 ! 1443: * bytes from a 4-byte expression and they forgot to sign extend. ! 1444: */ ! 1445: #define BSD_FILL_SIZE_CROCK_4 (4) ! 1446: md_number_to_chars(p, ! 1447: temp_fill, ! 1448: temp_size > BSD_FILL_SIZE_CROCK_4 ? ! 1449: BSD_FILL_SIZE_CROCK_4 : (int)temp_size); ! 1450: } ! 1451: demand_empty_rest_of_line(); ! 1452: } ! 1453: ! 1454: /* ! 1455: * s_globl() implements the pseudo op: ! 1456: * .globl name [ , name ] ! 1457: */ ! 1458: void ! 1459: s_globl( ! 1460: int value) ! 1461: { ! 1462: char *name; ! 1463: int c; ! 1464: symbolS *symbolP; ! 1465: ! 1466: do{ ! 1467: if(*input_line_pointer == '"') ! 1468: name = input_line_pointer + 1; ! 1469: else ! 1470: name = input_line_pointer; ! 1471: c = get_symbol_end(); ! 1472: symbolP = symbol_find_or_make(name); ! 1473: *input_line_pointer = c; ! 1474: SKIP_WHITESPACE(); ! 1475: symbolP->sy_type |= N_EXT; ! 1476: if(c == ','){ ! 1477: input_line_pointer++; ! 1478: SKIP_WHITESPACE(); ! 1479: if(*input_line_pointer == '\n') ! 1480: c = '\n'; ! 1481: } ! 1482: }while(c == ','); ! 1483: demand_empty_rest_of_line(); ! 1484: } ! 1485: ! 1486: /* ! 1487: * s_private_extern() implements the pseudo op: ! 1488: * .private_extern name [ , name ] ! 1489: */ ! 1490: static ! 1491: void ! 1492: s_private_extern( ! 1493: int value) ! 1494: { ! 1495: char *name; ! 1496: int c; ! 1497: symbolS *symbolP; ! 1498: ! 1499: if(!flagseen['k']) ! 1500: as_fatal("incompatible feature used: .private_extern (must specify " ! 1501: "\"-dynamic\" to be used)"); ! 1502: do{ ! 1503: if(*input_line_pointer == '"') ! 1504: name = input_line_pointer + 1; ! 1505: else ! 1506: name = input_line_pointer; ! 1507: c = get_symbol_end(); ! 1508: symbolP = symbol_find_or_make(name); ! 1509: *input_line_pointer = c; ! 1510: SKIP_WHITESPACE(); ! 1511: symbolP->sy_type |= N_EXT; ! 1512: symbolP->sy_type |= N_PEXT; ! 1513: if(c == ','){ ! 1514: input_line_pointer++; ! 1515: SKIP_WHITESPACE(); ! 1516: if(*input_line_pointer == '\n') ! 1517: c = '\n'; ! 1518: } ! 1519: }while(c == ','); ! 1520: demand_empty_rest_of_line(); ! 1521: } ! 1522: ! 1523: /* ! 1524: * s_indirect_symbol() implements the pseudo op: ! 1525: * .indirect_symbol name ! 1526: */ ! 1527: static ! 1528: void ! 1529: s_indirect_symbol( ! 1530: int value) ! 1531: { ! 1532: char *name; ! 1533: int c; ! 1534: unsigned long section_type; ! 1535: ! 1536: if(!flagseen['k']) ! 1537: as_fatal("incompatible feature used: .indirect_symbol (must " ! 1538: "specify \"-dynamic\" to be used)"); ! 1539: if(frchain_now == NULL){ ! 1540: know(flagseen['n']); ! 1541: as_fatal("with -n a section directive must be seen before assembly " ! 1542: "can begin"); ! 1543: } ! 1544: section_type = frchain_now->frch_section.flags & SECTION_TYPE; ! 1545: if(section_type != S_NON_LAZY_SYMBOL_POINTERS && ! 1546: section_type != S_LAZY_SYMBOL_POINTERS && ! 1547: section_type != S_SYMBOL_STUBS){ ! 1548: as_warn("indirect symbol not in a symbol pointer or stub section, " ! 1549: ".indirect_symbol ignored"); ! 1550: ignore_rest_of_line(); ! 1551: return; ! 1552: } ! 1553: ! 1554: if(*input_line_pointer == '"') ! 1555: name = input_line_pointer + 1; ! 1556: else ! 1557: name = input_line_pointer; ! 1558: c = get_symbol_end(); ! 1559: indirect_symbol_new(name, ! 1560: frag_now, ! 1561: obstack_next_free(&frags) - frag_now->fr_literal); ! 1562: *input_line_pointer = c; ! 1563: ! 1564: demand_empty_rest_of_line(); ! 1565: } ! 1566: ! 1567: /* ! 1568: * s_lcomm() implements the pseudo op: ! 1569: * .lcomm name , size_expression [ , align_expression ] ! 1570: */ ! 1571: static ! 1572: void ! 1573: s_lcomm( ! 1574: int value) ! 1575: { ! 1576: char *name; ! 1577: char c; ! 1578: char *p; ! 1579: int size; ! 1580: symbolS *symbolP; ! 1581: int align; ! 1582: static frchainS *bss = NULL; ! 1583: ! 1584: if(*input_line_pointer == '"') ! 1585: name = input_line_pointer + 1; ! 1586: else ! 1587: name = input_line_pointer; ! 1588: c = get_symbol_end(); ! 1589: p = input_line_pointer; ! 1590: *p = c; ! 1591: SKIP_WHITESPACE(); ! 1592: if(*input_line_pointer != ','){ ! 1593: as_warn("Expected comma after name"); ! 1594: ignore_rest_of_line(); ! 1595: return; ! 1596: } ! 1597: input_line_pointer ++; ! 1598: if((size = get_absolute_expression()) < 0){ ! 1599: as_warn("BSS length (%d.) <0! Ignored.", size); ! 1600: ignore_rest_of_line(); ! 1601: return; ! 1602: } ! 1603: #define MAX_ALIGNMENT (15) ! 1604: align = 0; ! 1605: if(*input_line_pointer == ','){ ! 1606: input_line_pointer++; ! 1607: align = get_absolute_expression(); ! 1608: if(align > MAX_ALIGNMENT){ ! 1609: as_warn("Alignment too large: %d. assumed.", MAX_ALIGNMENT); ! 1610: align = MAX_ALIGNMENT; ! 1611: } ! 1612: else if(align < 0){ ! 1613: as_warn("Alignment negative. 0 assumed."); ! 1614: align = 0; ! 1615: } ! 1616: } ! 1617: *p = 0; ! 1618: symbolP = symbol_find_or_make(name); ! 1619: *p = c; ! 1620: ! 1621: if((symbolP->sy_type & N_TYPE) == N_UNDF && symbolP->sy_value == 0){ ! 1622: if(bss == NULL){ ! 1623: bss = section_new(SEG_DATA, SECT_BSS, S_ZEROFILL, 0, 0); ! 1624: bss->frch_root = xmalloc(SIZEOF_STRUCT_FRAG); ! 1625: memset(bss->frch_root, '\0', SIZEOF_STRUCT_FRAG); ! 1626: bss->frch_last = bss->frch_root; ! 1627: } ! 1628: bss->frch_root->fr_address = round(bss->frch_root->fr_address, ! 1629: 1 << align); ! 1630: symbolP->sy_value = bss->frch_root->fr_address; ! 1631: symbolP->sy_type = N_SECT; ! 1632: symbolP->sy_other = bss->frch_nsect; ! 1633: symbolP->sy_frag = bss->frch_root; ! 1634: bss->frch_root->fr_address += size; ! 1635: /* ! 1636: * If this alignment is larger than any previous alignment then this ! 1637: * becomes the section's alignment. ! 1638: */ ! 1639: if(bss->frch_section.align < align) ! 1640: bss->frch_section.align = align; ! 1641: } ! 1642: else ! 1643: as_warn("Ignoring attempt to re-define symbol."); ! 1644: demand_empty_rest_of_line(); ! 1645: } ! 1646: ! 1647: /* ! 1648: * s_line() implements the pseudo op: ! 1649: * .line line_number ! 1650: */ ! 1651: void ! 1652: s_line( ! 1653: int value) ! 1654: { ! 1655: /* ! 1656: * Assume delimiter is part of expression. BSD4.2 as fails with ! 1657: * delightful bug, so we are not being incompatible here. ! 1658: */ ! 1659: /* ! 1660: * Since the assembler bumps it's line counters at the end of a line ! 1661: * and it is the case that the .line is on it's own line what the ! 1662: * intent is that the line number is for the next line. Thus ! 1663: * the -1 . This is the way cpp'ed assembler files work which is the ! 1664: * common case. ! 1665: */ ! 1666: new_logical_line((char *)NULL, (int)(get_absolute_expression()) - 1); ! 1667: demand_empty_rest_of_line(); ! 1668: } ! 1669: ! 1670: /* ! 1671: * s_lsym() implements the pseudo op: ! 1672: * .lsym name , expression ! 1673: */ ! 1674: static ! 1675: void ! 1676: s_lsym( ! 1677: int value) ! 1678: { ! 1679: char *name; ! 1680: char c; ! 1681: char *p; ! 1682: segT segment; ! 1683: expressionS exp; ! 1684: symbolS *symbolP; ! 1685: ! 1686: /* we permit ANY expression: BSD4.2 demands constants */ ! 1687: if(*input_line_pointer == '"') ! 1688: name = input_line_pointer + 1; ! 1689: else ! 1690: name = input_line_pointer; ! 1691: c = get_symbol_end(); ! 1692: p = input_line_pointer; ! 1693: *p = c; ! 1694: SKIP_WHITESPACE(); ! 1695: if(*input_line_pointer != ','){ ! 1696: *p = 0; ! 1697: as_warn("Expected comma after name \"%s\"", name); ! 1698: *p = c; ! 1699: ignore_rest_of_line(); ! 1700: return; ! 1701: } ! 1702: input_line_pointer++; ! 1703: segment = expression(&exp); ! 1704: if(segment != SEG_ABSOLUTE && segment != SEG_SECT){ ! 1705: /* this warning still need fixing */ ! 1706: as_warn("Bad expression: %s", seg_name[(int)segment]); ! 1707: ignore_rest_of_line(); ! 1708: return; ! 1709: } ! 1710: know(segment == SEG_ABSOLUTE || segment == SEG_SECT); ! 1711: *p = 0; ! 1712: if(segment == SEG_SECT) ! 1713: symbolP = symbol_new(name, ! 1714: N_SECT, ! 1715: frchain_now->frch_nsect, ! 1716: 0, ! 1717: (valueT)(exp.X_add_number), ! 1718: &zero_address_frag); ! 1719: else ! 1720: symbolP = symbol_new(name, ! 1721: N_ABS, ! 1722: 0, ! 1723: 0, ! 1724: (valueT)(exp.X_add_number), ! 1725: &zero_address_frag); ! 1726: *p = c; ! 1727: demand_empty_rest_of_line(); ! 1728: } ! 1729: ! 1730: #if !defined(I860) /* i860 has it's own align and org */ ! 1731: /* ! 1732: * s_org() implements the pseudo op: ! 1733: * .org expression ! 1734: */ ! 1735: static ! 1736: void ! 1737: s_org( ! 1738: int value) ! 1739: { ! 1740: segT segment; ! 1741: expressionS exp; ! 1742: long temp_fill; ! 1743: char *p; ! 1744: ! 1745: /* ! 1746: * Don't believe the documentation of BSD 4.2 AS. ! 1747: * There is no such thing as a sub-segment-relative origin. ! 1748: * Any absolute origin is given a warning, then assumed to be ! 1749: * segment-relative. ! 1750: * Any segmented origin expression ("foo+42") had better be in the right ! 1751: * segment or the .org is ignored. ! 1752: * ! 1753: * BSD 4.2 AS warns if you try to .org backwards. We cannot because we ! 1754: * never know sub-segment sizes when we are reading code. ! 1755: * BSD will crash trying to emit -ve numbers of filler bytes in certain ! 1756: * .orgs. We don't crash, but see as-write for that code. ! 1757: */ ! 1758: segment = get_known_segmented_expression(&exp); ! 1759: if(*input_line_pointer == ','){ ! 1760: input_line_pointer ++; ! 1761: temp_fill = get_absolute_expression (); ! 1762: } ! 1763: else ! 1764: temp_fill = 0; ! 1765: if((segment != SEG_SECT || ! 1766: exp.X_add_symbol->sy_other != frchain_now->frch_nsect) && ! 1767: segment != SEG_ABSOLUTE) ! 1768: as_warn("Illegal expression. current section assumed."); ! 1769: p = frag_var(rs_org, ! 1770: 1, ! 1771: 1, ! 1772: (relax_substateT)0, ! 1773: exp.X_add_symbol, ! 1774: exp.X_add_number, ! 1775: (char *)0); ! 1776: *p = temp_fill; ! 1777: demand_empty_rest_of_line(); ! 1778: } ! 1779: #endif /* !defined(I860) i860 has it's own align and org */ ! 1780: ! 1781: /* ! 1782: * s_set() implements the pseudo op: ! 1783: * .set name , expression ! 1784: */ ! 1785: static ! 1786: void ! 1787: s_set( ! 1788: int value) ! 1789: { ! 1790: char *name; ! 1791: char delim; ! 1792: char *end_name; ! 1793: symbolS *symbolP; ! 1794: ! 1795: if( * input_line_pointer == '"') ! 1796: name = input_line_pointer + 1; ! 1797: else ! 1798: name = input_line_pointer; ! 1799: delim = get_symbol_end(); ! 1800: end_name = input_line_pointer; ! 1801: *end_name = delim; ! 1802: SKIP_WHITESPACE(); ! 1803: if(*input_line_pointer != ','){ ! 1804: *end_name = 0; ! 1805: as_warn("Expected comma after name \"%s\"", name); ! 1806: *end_name = delim; ! 1807: ignore_rest_of_line(); ! 1808: return; ! 1809: } ! 1810: input_line_pointer++; ! 1811: *end_name = 0; ! 1812: if(name[0] == '.' && name[1] == '\0'){ ! 1813: /* Turn 'set . , mumble' into a .org mumble */ ! 1814: segT segment; ! 1815: expressionS exp; ! 1816: char *ptr; ! 1817: ! 1818: segment = get_known_segmented_expression(&exp); ! 1819: if((segment != SEG_SECT || ! 1820: exp.X_add_symbol->sy_other != frchain_now->frch_nsect) && ! 1821: segment != SEG_ABSOLUTE) ! 1822: as_warn("Illegal expression. current section assumed."); ! 1823: ptr = frag_var(rs_org, ! 1824: 1, ! 1825: 1, ! 1826: (relax_substateT)0, ! 1827: exp.X_add_symbol, ! 1828: exp.X_add_number, ! 1829: (char *)0); ! 1830: *ptr = 0; ! 1831: *end_name = delim; ! 1832: return; ! 1833: } ! 1834: symbolP = symbol_find_or_make(name); ! 1835: *end_name = delim; ! 1836: pseudo_set(symbolP); ! 1837: demand_empty_rest_of_line(); ! 1838: } ! 1839: ! 1840: /* ! 1841: * s_abs() implements the pseudo op: ! 1842: * .abs name , expression ! 1843: * which sets symbol to 1 or 0 depending on if the expression is an absolute ! 1844: * expression. This is intended for use in macros. ! 1845: */ ! 1846: void ! 1847: s_abs( ! 1848: int value) ! 1849: { ! 1850: char *name; ! 1851: char c; ! 1852: char *p; ! 1853: segT segment; ! 1854: expressionS exp; ! 1855: symbolS *symbolP; ! 1856: ! 1857: if(*input_line_pointer == '"') ! 1858: name = input_line_pointer + 1; ! 1859: else ! 1860: name = input_line_pointer; ! 1861: c = get_symbol_end(); ! 1862: p = input_line_pointer; ! 1863: *p = c; ! 1864: SKIP_WHITESPACE(); ! 1865: if(*input_line_pointer != ','){ ! 1866: *p = 0; ! 1867: as_warn("Expected comma after name \"%s\"", name); ! 1868: *p = c; ! 1869: ignore_rest_of_line(); ! 1870: return; ! 1871: } ! 1872: input_line_pointer++; ! 1873: *p = 0; ! 1874: segment = expression(&exp); ! 1875: symbolP = symbol_find_or_make(name); ! 1876: symbolP->sy_type = N_ABS; ! 1877: symbolP->sy_other = 0; /* NO_SECT */ ! 1878: symbolP->sy_frag = &zero_address_frag; ! 1879: if(segment == SEG_ABSOLUTE) ! 1880: symbolP->sy_value = 1; ! 1881: else ! 1882: symbolP->sy_value = 0; ! 1883: *p = c; ! 1884: totally_ignore_line(); ! 1885: } ! 1886: ! 1887: /* ! 1888: * s_space() implements the pseudo op: ! 1889: * .space repeat_expression [ , fill_expression ] ! 1890: */ ! 1891: void ! 1892: s_space( ! 1893: int value) ! 1894: { ! 1895: long temp_repeat; ! 1896: long temp_fill; ! 1897: char *p; ! 1898: ! 1899: /* Just like .fill, but temp_size = 1 */ ! 1900: if(get_absolute_expression_and_terminator(&temp_repeat) == ','){ ! 1901: temp_fill = get_absolute_expression(); ! 1902: } ! 1903: else{ ! 1904: input_line_pointer--; /* Backup over what was not a ','. */ ! 1905: temp_fill = 0; ! 1906: } ! 1907: if(temp_repeat <= 0){ ! 1908: as_warn("Repeat < 0, .space ignored"); ! 1909: ignore_rest_of_line(); ! 1910: return; ! 1911: } ! 1912: p = frag_var(rs_fill, ! 1913: 1, ! 1914: 1, ! 1915: (relax_substateT)0, ! 1916: (symbolS *)0, ! 1917: temp_repeat, ! 1918: (char *)0); ! 1919: *p = temp_fill; ! 1920: demand_empty_rest_of_line(); ! 1921: } ! 1922: ! 1923: static ! 1924: unsigned long ! 1925: s_builtin_section( ! 1926: const struct builtin_section *s) ! 1927: { ! 1928: frchainS *frcP; ! 1929: ! 1930: if(!flagseen['k']){ ! 1931: if((s->flags & SECTION_TYPE) == S_NON_LAZY_SYMBOL_POINTERS || ! 1932: (s->flags & SECTION_TYPE) == S_LAZY_SYMBOL_POINTERS || ! 1933: (s->flags & SECTION_TYPE) == S_SYMBOL_STUBS || ! 1934: (s->flags & SECTION_TYPE) == S_MOD_INIT_FUNC_POINTERS || ! 1935: (s->flags & SECTION_ATTRIBUTES) != 0) ! 1936: as_fatal("incompatible feature used: directive .%s (must " ! 1937: "specify \"-dynamic\" to be used)", s->directive); ! 1938: } ! 1939: /* ! 1940: * If we allowed to use the new features that are incompatible with 3.2 ! 1941: * and this is the text section (which relys on the fact that the text ! 1942: * section is first in the built in sections list) then add the ! 1943: * S_ATTR_PURE_INSTRUCTIONS to the section attributes. ! 1944: */ ! 1945: if(flagseen['k'] && s == builtin_sections){ ! 1946: frcP = section_new(s->segname, s->sectname, ! 1947: s->flags & SECTION_TYPE, ! 1948: (s->flags & SECTION_ATTRIBUTES) | ! 1949: S_ATTR_PURE_INSTRUCTIONS, ! 1950: s->sizeof_stub); ! 1951: } ! 1952: else{ ! 1953: frcP = section_new(s->segname, s->sectname, ! 1954: s->flags & SECTION_TYPE, ! 1955: s->flags & SECTION_ATTRIBUTES, ! 1956: s->sizeof_stub); ! 1957: } ! 1958: if(frcP->frch_section.align < s->default_align) ! 1959: frcP->frch_section.align = s->default_align; ! 1960: return(frcP->frch_nsect); ! 1961: } ! 1962: ! 1963: /* ! 1964: * s_section() implements the pseudo op: ! 1965: * .section segname , sectname [[[ , type ] , attribute] , sizeof_stub] ! 1966: */ ! 1967: static ! 1968: void ! 1969: s_section( ! 1970: int value) ! 1971: { ! 1972: char *segname, *sectname, *typename; ! 1973: char c, d, e, *p, *q, *r; ! 1974: struct type_name *type_name; ! 1975: unsigned long type, attribute; ! 1976: struct section s; ! 1977: frchainS *frcP; ! 1978: unsigned long sizeof_stub; ! 1979: ! 1980: struct attribute_name *attribute_name; ! 1981: char *attributename, *sizeof_stub_name, f, g, *t, *u, *endp; ! 1982: ! 1983: segname = input_line_pointer; ! 1984: do{ ! 1985: c = *input_line_pointer++ ; ! 1986: }while(c != ',' && c != '\0' && c != '\n'); ! 1987: if(c != ','){ ! 1988: as_warn("Expected comma after segment-name"); ! 1989: ignore_rest_of_line(); ! 1990: return; ! 1991: } ! 1992: p = input_line_pointer - 1; ! 1993: ! 1994: sectname = input_line_pointer; ! 1995: do{ ! 1996: d = *input_line_pointer++ ; ! 1997: }while(d != ',' && d != '\0' && d != '\n'); ! 1998: if(p + 1 == input_line_pointer){ ! 1999: as_warn("Expected section-name after comma"); ! 2000: ignore_rest_of_line(); ! 2001: return; ! 2002: } ! 2003: q = input_line_pointer - 1; ! 2004: ! 2005: *p = 0; ! 2006: if(strlen(segname) > sizeof(s.segname)){ ! 2007: as_warn("segment-name: %s too long (maximum %ld characters)", ! 2008: segname, sizeof(s.segname)); ! 2009: ignore_rest_of_line(); ! 2010: *p = c; ! 2011: return; ! 2012: } ! 2013: ! 2014: *q = 0; ! 2015: if(strlen(sectname) > sizeof(s.sectname)){ ! 2016: as_warn("section-name: %s too long (maximum %ld characters)", ! 2017: sectname, sizeof(s.sectname)); ! 2018: ignore_rest_of_line(); ! 2019: return; ! 2020: } ! 2021: /* ! 2022: * Now see if the optional section type is present. ! 2023: */ ! 2024: type = 0; ! 2025: type_name = type_names; ! 2026: attribute = 0; ! 2027: attribute_name = attribute_names; ! 2028: sizeof_stub = 0; ! 2029: if(d == ','){ ! 2030: typename = input_line_pointer; ! 2031: do{ ! 2032: e = *input_line_pointer++ ; ! 2033: } ! 2034: while(e != ',' && e != '\0' && e != '\n'); ! 2035: r = input_line_pointer - 1; ! 2036: *r = 0; ! 2037: for(type_name = type_names; type_name->name != NULL; type_name++) ! 2038: if(strcmp(type_name->name, typename) == 0) ! 2039: break; ! 2040: if(type_name->name == NULL){ ! 2041: as_warn("unknown section type: %s", typename); ! 2042: ignore_rest_of_line(); ! 2043: return; ! 2044: } ! 2045: *r = e; ! 2046: type = type_name->type; ! 2047: /* ! 2048: * Now see if the optional section attribute is present. ! 2049: */ ! 2050: if(e == ','){ ! 2051: attributename = input_line_pointer; ! 2052: do{ ! 2053: f = *input_line_pointer++ ; ! 2054: }while(f != ',' && f != '\0' && f != '\n'); ! 2055: t = input_line_pointer - 1; ! 2056: *t = 0; ! 2057: for(attribute_name = attribute_names; ! 2058: attribute_name->name != NULL; ! 2059: attribute_name++) ! 2060: if(strcmp(attribute_name->name, attributename) == 0) ! 2061: break; ! 2062: if(attribute_name->name == NULL){ ! 2063: as_warn("unknown section attribute: %s", attributename); ! 2064: ignore_rest_of_line(); ! 2065: return; ! 2066: } ! 2067: *t = f; ! 2068: attribute = attribute_name->attribute; ! 2069: ! 2070: /* ! 2071: * Now get the section stub size if this is a stub section. ! 2072: */ ! 2073: if(type == S_SYMBOL_STUBS){ ! 2074: if(f == ','){ ! 2075: sizeof_stub_name = input_line_pointer; ! 2076: do{ ! 2077: g = *input_line_pointer++ ; ! 2078: }while(g != '\0' && g != '\n'); ! 2079: u = input_line_pointer - 1; ! 2080: *u = 0; ! 2081: sizeof_stub = strtoul(sizeof_stub_name, &endp, 0); ! 2082: if(*endp != '\0'){ ! 2083: as_warn("size of stub section: %s not a proper " ! 2084: "number", sizeof_stub_name); ! 2085: ignore_rest_of_line(); ! 2086: return; ! 2087: } ! 2088: *u = g; ! 2089: } ! 2090: else{ ! 2091: as_warn("missing size of stub section (%s,%s)", segname, ! 2092: sectname); ! 2093: ignore_rest_of_line(); ! 2094: return; ! 2095: } ! 2096: } ! 2097: } ! 2098: else if(type == S_SYMBOL_STUBS){ ! 2099: as_warn("missing size of stub section (%s,%s)", segname, ! 2100: sectname); ! 2101: ignore_rest_of_line(); ! 2102: return; ! 2103: } ! 2104: } ! 2105: input_line_pointer--; ! 2106: ! 2107: if(!flagseen['k']){ ! 2108: if(type == S_NON_LAZY_SYMBOL_POINTERS || ! 2109: type == S_LAZY_SYMBOL_POINTERS || ! 2110: type == S_SYMBOL_STUBS || ! 2111: type == S_MOD_INIT_FUNC_POINTERS) ! 2112: as_fatal("incompatible feature used: section type %s (must " ! 2113: "specify \"-dynamic\" to be " ! 2114: "used)", type_name->name); ! 2115: if(attribute != 0) ! 2116: as_fatal("incompatible feature used: section attribute %s " ! 2117: "(must specify \"-dynamic\" to be used)", ! 2118: attribute_name->name); ! 2119: } ! 2120: ! 2121: frcP = section_new(segname, sectname, type, attribute, sizeof_stub); ! 2122: *p = c; ! 2123: *q = d; ! 2124: demand_empty_rest_of_line(); ! 2125: } ! 2126: ! 2127: /* ! 2128: * s_zerofill() implements the pseudo op: ! 2129: * .zerofill segname , sectname [, symbolname , size_expression [ , align]] ! 2130: */ ! 2131: static ! 2132: void ! 2133: s_zerofill( ! 2134: int value) ! 2135: { ! 2136: char *segname, *sectname, c, d, *p, *q, *name; ! 2137: struct section s; ! 2138: frchainS *frcP; ! 2139: symbolS *symbolP; ! 2140: int size, align; ! 2141: ! 2142: segname = input_line_pointer; ! 2143: do{ ! 2144: c = *input_line_pointer++ ; ! 2145: }while(c != ',' && c != '\0' && c != '\n'); ! 2146: if(c != ','){ ! 2147: as_warn("Expected comma after segment-name"); ! 2148: ignore_rest_of_line(); ! 2149: return; ! 2150: } ! 2151: p = input_line_pointer - 1; ! 2152: ! 2153: sectname = input_line_pointer; ! 2154: do{ ! 2155: d = *input_line_pointer++ ; ! 2156: }while(d != ',' && d != '\0' && d != '\n'); ! 2157: if(p + 1 == input_line_pointer){ ! 2158: as_warn("Expected section-name after comma"); ! 2159: ignore_rest_of_line(); ! 2160: return; ! 2161: } ! 2162: q = input_line_pointer - 1; ! 2163: ! 2164: *p = 0; ! 2165: if(strlen(segname) > sizeof(s.segname)){ ! 2166: as_warn("segment-name: %s too long (maximum %ld characters)", ! 2167: segname, sizeof(s.segname)); ! 2168: ignore_rest_of_line(); ! 2169: *p = c; ! 2170: return; ! 2171: } ! 2172: ! 2173: *q = 0; ! 2174: if(strlen(sectname) > sizeof(s.sectname)){ ! 2175: as_warn("section-name: %s too long (maximum %ld characters)", ! 2176: sectname, sizeof(s.sectname)); ! 2177: ignore_rest_of_line(); ! 2178: *p = c; ! 2179: *q = d; ! 2180: return; ! 2181: } ! 2182: ! 2183: frcP = section_new(segname, sectname, S_ZEROFILL, 0, 0); ! 2184: if(frcP->frch_root == NULL){ ! 2185: frcP->frch_root = xmalloc(SIZEOF_STRUCT_FRAG); ! 2186: frcP->frch_last = frcP->frch_root; ! 2187: memset(frcP->frch_root, '\0', SIZEOF_STRUCT_FRAG); ! 2188: } ! 2189: *p = c; ! 2190: *q = d; ! 2191: /* ! 2192: * If this is the end of the line all that was wanted was to create the ! 2193: * the section which is now done, so return. ! 2194: */ ! 2195: if(d != ',') ! 2196: return; ! 2197: ! 2198: if(*input_line_pointer == '"') ! 2199: name = input_line_pointer + 1; ! 2200: else ! 2201: name = input_line_pointer; ! 2202: c = get_symbol_end(); ! 2203: p = input_line_pointer; ! 2204: *p = c; ! 2205: SKIP_WHITESPACE(); ! 2206: if(*input_line_pointer != ','){ ! 2207: as_warn("Expected comma after symbol-name"); ! 2208: ignore_rest_of_line(); ! 2209: return; ! 2210: } ! 2211: input_line_pointer ++; ! 2212: if((size = get_absolute_expression()) < 0){ ! 2213: as_warn("zerofill size (%d.) <0! Ignored.", size); ! 2214: ignore_rest_of_line(); ! 2215: return; ! 2216: } ! 2217: align = 0; ! 2218: if(*input_line_pointer == ','){ ! 2219: input_line_pointer++; ! 2220: align = get_absolute_expression(); ! 2221: if(align > MAX_ALIGNMENT){ ! 2222: as_warn("Alignment too large: %d. assumed.", MAX_ALIGNMENT); ! 2223: align = MAX_ALIGNMENT; ! 2224: } ! 2225: else if(align < 0){ ! 2226: as_warn("Alignment negative. 0 assumed."); ! 2227: align = 0; ! 2228: } ! 2229: } ! 2230: *p = 0; ! 2231: symbolP = symbol_find_or_make(name); ! 2232: *p = c; ! 2233: ! 2234: if((symbolP->sy_type & N_TYPE) == N_UNDF && symbolP->sy_value == 0){ ! 2235: frcP->frch_root->fr_address = round(frcP->frch_root->fr_address, ! 2236: 1 << align); ! 2237: symbolP->sy_value = frcP->frch_root->fr_address; ! 2238: symbolP->sy_type = N_SECT | (symbolP->sy_type & N_EXT); ! 2239: symbolP->sy_other = frcP->frch_nsect; ! 2240: symbolP->sy_frag = frcP->frch_root; ! 2241: frcP->frch_root->fr_address += size; ! 2242: } ! 2243: else ! 2244: as_warn("Ignoring attempt to re-define symbol."); ! 2245: ! 2246: demand_empty_rest_of_line(); ! 2247: } ! 2248: ! 2249: /* ! 2250: * s_reference() implements the pseudo op: ! 2251: * .reference name ! 2252: */ ! 2253: static ! 2254: void ! 2255: s_reference( ! 2256: int value) ! 2257: { ! 2258: char *name; ! 2259: char c; ! 2260: char *p; ! 2261: symbolS *symbolP; ! 2262: ! 2263: if(* input_line_pointer == '"') ! 2264: name = input_line_pointer + 1; ! 2265: else ! 2266: name = input_line_pointer; ! 2267: c = get_symbol_end(); ! 2268: p = input_line_pointer; ! 2269: ! 2270: *p = 0; ! 2271: symbolP = symbol_find_or_make(name); ! 2272: *p = c; ! 2273: demand_empty_rest_of_line(); ! 2274: } ! 2275: ! 2276: /* ! 2277: * s_lazy_reference() implements the pseudo op: ! 2278: * .lazy_reference name ! 2279: */ ! 2280: static ! 2281: void ! 2282: s_lazy_reference( ! 2283: int value) ! 2284: { ! 2285: char *name; ! 2286: char c; ! 2287: char *p; ! 2288: symbolS *symbolP; ! 2289: ! 2290: if(!flagseen['k']) ! 2291: as_fatal("incompatible feature used: .lazy_reference (must specify " ! 2292: "\"-dynamic\" to be used)"); ! 2293: ! 2294: if(* input_line_pointer == '"') ! 2295: name = input_line_pointer + 1; ! 2296: else ! 2297: name = input_line_pointer; ! 2298: c = get_symbol_end(); ! 2299: p = input_line_pointer; ! 2300: ! 2301: *p = 0; ! 2302: symbolP = symbol_find_or_make(name); ! 2303: if((symbolP->sy_type & N_TYPE) == N_UNDF && symbolP->sy_value == 0) ! 2304: symbolP->sy_desc |= REFERENCE_FLAG_UNDEFINED_LAZY; ! 2305: *p = c; ! 2306: demand_empty_rest_of_line(); ! 2307: } ! 2308: ! 2309: /* ! 2310: * s_include() implements the pseudo op: ! 2311: * .include "filename" ! 2312: */ ! 2313: static ! 2314: void ! 2315: s_include( ! 2316: int value) ! 2317: { ! 2318: char *filename; ! 2319: int length; ! 2320: symbolS *symbolP; ! 2321: ! 2322: /* Some assemblers tolerate immediately following '"' */ ! 2323: if((filename = demand_copy_string( & length ) )) { ! 2324: demand_empty_rest_of_line(); ! 2325: read_an_include_file(filename); ! 2326: } ! 2327: ! 2328: /* ! 2329: * This is to generate stabs for debugging assembly code. ! 2330: * See the second comment about stabs in read_a_source_file() ! 2331: * for a description of what is going on here ! 2332: */ ! 2333: if(flagseen['g'] && frchain_now->frch_nsect == text_nsect){ ! 2334: symbolP = symbol_new( ! 2335: physical_input_file, ! 2336: 132 /* N_SOL */, ! 2337: text_nsect, ! 2338: 0, ! 2339: obstack_next_free(&frags) - frag_now->fr_literal, ! 2340: frag_now); ! 2341: } ! 2342: } ! 2343: ! 2344: /* ! 2345: * demand_empty_rest_of_line() checks to make sure we are at the end of a line ! 2346: * and if not ignores the rest of the line. ! 2347: * This is global so machine dependent pseudo-ops can use this. ! 2348: */ ! 2349: void ! 2350: demand_empty_rest_of_line( ! 2351: void) ! 2352: { ! 2353: SKIP_WHITESPACE(); ! 2354: if(is_end_of_line[(int)*input_line_pointer]) ! 2355: input_line_pointer++; ! 2356: else ! 2357: ignore_rest_of_line(); ! 2358: } ! 2359: ! 2360: /* ! 2361: * ignore_rest_of_line() advances input_line_pointer to the next line and if ! 2362: * there is anything left on the current line print a warning. ! 2363: * This is global so machine dependent pseudo-ops can use this. ! 2364: */ ! 2365: void ! 2366: ignore_rest_of_line( ! 2367: void) ! 2368: { ! 2369: if(!is_end_of_line[(int)*input_line_pointer]){ ! 2370: as_warn("Rest of line ignored. 1st junk character valued %d (%c).", ! 2371: *input_line_pointer, *input_line_pointer); ! 2372: while(input_line_pointer < buffer_limit && ! 2373: !is_end_of_line[(int)*input_line_pointer]) ! 2374: input_line_pointer++; ! 2375: } ! 2376: input_line_pointer++; /* Return pointing just after end-of-line. */ ! 2377: know(is_end_of_line[(int)(input_line_pointer[-1])]); ! 2378: } ! 2379: ! 2380: /* ! 2381: * stab() ! 2382: * ! 2383: * Handle .stabX directives, which used to be open-coded. ! 2384: * So much creeping featurism overloaded the semantics that we decided ! 2385: * to put all .stabX thinking in one place. Here. ! 2386: * ! 2387: * We try to make any .stabX directive legal. Other people's AS will often ! 2388: * do assembly-time consistency checks: eg assigning meaning to n_type bits ! 2389: * and "protecting" you from setting them to certain values. (They also zero ! 2390: * certain bits before emitting symbols. Tut tut.) ! 2391: * ! 2392: * If an expression is not absolute we either gripe or use the relocation ! 2393: * information. Other people's assemblers silently forget information they ! 2394: * don't need and invent information they need that you didn't supply. ! 2395: * ! 2396: * .stabX directives always make a symbol table entry. It may be junk if ! 2397: * the rest of your .stabX directive is malformed. ! 2398: */ ! 2399: static ! 2400: void ! 2401: stab( ! 2402: int what) /* d == .stabd, n == .stabn, and s == .stabs */ ! 2403: { ! 2404: symbolS *symbolP; ! 2405: char *string; ! 2406: int saved_type; ! 2407: int length; ! 2408: int goof; /* TRUE if we have aborted. */ ! 2409: long longint; ! 2410: ! 2411: saved_type = 0; ! 2412: /* ! 2413: * Enter with input_line_pointer pointing past .stabX and any following ! 2414: * whitespace. ! 2415: */ ! 2416: goof = FALSE; ! 2417: if(what == 's'){ ! 2418: string = demand_copy_C_string(&length); ! 2419: SKIP_WHITESPACE(); ! 2420: if(*input_line_pointer == ',') ! 2421: input_line_pointer ++; ! 2422: else{ ! 2423: as_warn("I need a comma after symbol's name"); ! 2424: goof = TRUE; ! 2425: } ! 2426: } ! 2427: else ! 2428: string = ""; ! 2429: ! 2430: /* ! 2431: * Input_line_pointer->after ','. String -> symbol name. ! 2432: */ ! 2433: if(!goof){ ! 2434: symbolP = symbol_new(string, 0,0,0,0,(struct frag *)0); ! 2435: switch(what){ ! 2436: case 'd': ! 2437: symbolP->sy_name = NULL; /* .stabd feature. */ ! 2438: symbolP->sy_value = obstack_next_free(&frags) - ! 2439: frag_now->fr_literal; ! 2440: symbolP->sy_frag = frag_now; ! 2441: break; ! 2442: ! 2443: case 'n': ! 2444: case 's': ! 2445: symbolP->sy_frag = &zero_address_frag; ! 2446: break; ! 2447: ! 2448: default: ! 2449: BAD_CASE( what ); ! 2450: break; ! 2451: } ! 2452: if(get_absolute_expression_and_terminator(&longint) == ','){ ! 2453: saved_type = longint; ! 2454: symbolP->sy_type = longint; ! 2455: } ! 2456: else{ ! 2457: as_warn("I want a comma after the n_type expression"); ! 2458: goof = TRUE; ! 2459: input_line_pointer--; /* Backup over a non-',' char. */ ! 2460: } ! 2461: } ! 2462: ! 2463: if(!goof){ ! 2464: if(get_absolute_expression_and_terminator(&longint) == ',') ! 2465: symbolP->sy_other = longint; ! 2466: else { ! 2467: as_warn("I want a comma after the n_other expression"); ! 2468: goof = TRUE; ! 2469: input_line_pointer--; /* Backup over a non-',' char. */ ! 2470: } ! 2471: } ! 2472: ! 2473: if(!goof){ ! 2474: symbolP->sy_desc = get_absolute_expression(); ! 2475: if(what == 's' || what == 'n'){ ! 2476: if(*input_line_pointer != ','){ ! 2477: as_warn( "I want a comma after the n_desc expression" ); ! 2478: goof = TRUE; ! 2479: } ! 2480: else ! 2481: input_line_pointer ++; ! 2482: } ! 2483: } ! 2484: ! 2485: if((!goof) && (what=='s' || what=='n')){ ! 2486: pseudo_set(symbolP); ! 2487: symbolP->sy_type = saved_type; ! 2488: } ! 2489: else if(!goof){ ! 2490: /* for stabd the sy_other (n_sect) gets set to the current section*/ ! 2491: symbolP->sy_other = frchain_now->frch_nsect; ! 2492: } ! 2493: if(goof) ! 2494: ignore_rest_of_line(); ! 2495: else ! 2496: demand_empty_rest_of_line(); ! 2497: } ! 2498: ! 2499: /* ! 2500: * pseudo_set() ! 2501: * ! 2502: * In: Pointer to a symbol. ! 2503: * Input_line_pointer -> expression. ! 2504: * ! 2505: * Out: Input_line_pointer -> just after any whitespace after expression. ! 2506: * Tried to set symbol to value of expression. ! 2507: * Will change sy_type, sy_value, sy_frag; ! 2508: *(old ->> May set need_pass_2 == TRUE. <<-- commented out by GNU below it ! 2509: * uses symbolP->sy_forward = exp.X_add_symbol;) ! 2510: */ ! 2511: static ! 2512: void ! 2513: pseudo_set( ! 2514: symbolS *symbolP) ! 2515: { ! 2516: expressionS exp; ! 2517: segT segment; ! 2518: int ext; ! 2519: ! 2520: know(symbolP); /* NULL pointer is logic error. */ ! 2521: ext = (symbolP->sy_type & N_EXT); ! 2522: segment = expression(&exp); ! 2523: ! 2524: switch(segment){ ! 2525: case SEG_BIG: ! 2526: as_warn("%s number illegal. Absolute 0 assumed.", ! 2527: exp.X_add_number > 0 ? "Bignum" : "Floating-Point"); ! 2528: symbolP->sy_type = N_ABS | ext; ! 2529: symbolP->sy_other = 0; /* NO_SECT */ ! 2530: symbolP->sy_value = 0; ! 2531: symbolP->sy_frag = &zero_address_frag; ! 2532: break; ! 2533: ! 2534: case SEG_NONE: ! 2535: as_warn("No expression: Using absolute 0"); ! 2536: symbolP->sy_type = N_ABS | ext; ! 2537: symbolP->sy_other = 0; /* NO_SECT */ ! 2538: symbolP->sy_value = 0; ! 2539: symbolP->sy_frag = &zero_address_frag; ! 2540: break; ! 2541: ! 2542: case SEG_DIFFSECT: ! 2543: if(exp.X_add_symbol && exp.X_subtract_symbol && ! 2544: exp.X_add_symbol->sy_other == exp.X_subtract_symbol->sy_other) ! 2545: exp.X_add_number += exp.X_add_symbol->sy_value - ! 2546: exp.X_subtract_symbol->sy_value; ! 2547: else ! 2548: as_warn("Complex expression. Absolute segment assumed." ); ! 2549: /* fall through */ ! 2550: ! 2551: case SEG_ABSOLUTE: ! 2552: symbolP->sy_type = N_ABS | ext; ! 2553: symbolP->sy_other = 0; /* NO_SECT */ ! 2554: symbolP->sy_value = exp.X_add_number; ! 2555: symbolP->sy_frag = &zero_address_frag; ! 2556: break; ! 2557: ! 2558: case SEG_SECT: ! 2559: symbolP->sy_type = N_SECT | ext; ! 2560: symbolP->sy_other = exp.X_add_symbol->sy_other; ! 2561: symbolP->sy_value = exp.X_add_number + exp.X_add_symbol->sy_value; ! 2562: symbolP->sy_frag = exp.X_add_symbol->sy_frag; ! 2563: break; ! 2564: ! 2565: case SEG_UNKNOWN: ! 2566: symbolP->sy_forward = exp.X_add_symbol; ! 2567: /* commented out by GNU */ ! 2568: /* as_warn("unknown symbol"); */ ! 2569: /* need_pass_2 = TRUE; */ ! 2570: break; ! 2571: ! 2572: default: ! 2573: BAD_CASE(segment); ! 2574: break; ! 2575: } ! 2576: } ! 2577: ! 2578: /* ! 2579: * cons() ! 2580: * ! 2581: * CONStruct more frag of .bytes, or .words etc. ! 2582: * This understands EXPRESSIONS, as opposed to big_cons(). ! 2583: * ! 2584: * Bug (?) ! 2585: * ! 2586: * This has a split personality. We use expression() to read the ! 2587: * value. We can detect if the value won't fit in a byte or word. ! 2588: * But we can't detect if expression() discarded significant digits ! 2589: * in the case of a long. Not worth the crocks required to fix it. ! 2590: * ! 2591: * Worker function to do .byte, .short, .long, statements. ! 2592: * This clobbers input_line_pointer, checks end-of-line. ! 2593: */ ! 2594: void ! 2595: cons( ! 2596: int nbytes) /* nbytes == 1 for .byte, 2 for .word, 4 for .long */ ! 2597: { ! 2598: char c; ! 2599: long mask; /* high-order bits to truncate */ ! 2600: long unmask; /* what bits we will store */ ! 2601: long get; /* the bits of the expression we get */ ! 2602: long use; /* the bits of the expression after truncation */ ! 2603: char *p; /* points into the frag */ ! 2604: segT segment; ! 2605: expressionS exp; ! 2606: ! 2607: /* ! 2608: * Input_line_pointer -> 1st char after pseudo-op-code and could legally ! 2609: * be a end-of-line. (Or, less legally an eof - which we cope with.) ! 2610: */ ! 2611: if(nbytes >= sizeof(long int)) ! 2612: mask = 0; ! 2613: else ! 2614: mask = ~0 << (BITS_PER_CHAR * nbytes); /* Don't store these bits. */ ! 2615: unmask = ~mask; /* Do store these bits. */ ! 2616: ! 2617: /* ! 2618: * The following awkward logic is to parse ZERO or more expressions, ! 2619: * comma seperated. Recall an expression includes its leading & ! 2620: * trailing blanks. We fake a leading ',' if there is (supposed to ! 2621: * be) a 1st expression, and keep demanding 1 expression for each ','. ! 2622: */ ! 2623: if(is_it_end_of_statement()){ ! 2624: c = 0; /* Skip loop. */ ! 2625: input_line_pointer++; /* Matches end-of-loop 'correction'. */ ! 2626: } ! 2627: else ! 2628: c = ','; /* Do loop. */ ! 2629: ! 2630: while(c == ','){ ! 2631: segment = expression(&exp); /* At least scan over the expression */ ! 2632: ! 2633: if(segment == SEG_DIFFSECT && exp.X_add_symbol == NULL){ ! 2634: as_warn("Subtracting symbol \"%s\"(segment\"%s\") is too " ! 2635: "hard. Absolute segment assumed.", ! 2636: exp.X_subtract_symbol->sy_name, ! 2637: seg_name[(int)N_TYPE_seg[ ! 2638: exp.X_subtract_symbol->sy_type & N_TYPE]]); ! 2639: segment = SEG_ABSOLUTE; ! 2640: /* Leave exp .X_add_number alone. */ ! 2641: } ! 2642: p = frag_more(nbytes); ! 2643: switch(segment){ ! 2644: case SEG_BIG: ! 2645: as_warn("%s number illegal. Absolute 0 assumed.", ! 2646: exp.X_add_number > 0 ? "Bignum" : "Floating-Point"); ! 2647: md_number_to_chars(p, (long)0, nbytes); ! 2648: break; ! 2649: ! 2650: case SEG_NONE: ! 2651: as_warn("0 assumed for missing expression"); ! 2652: exp.X_add_number = 0; ! 2653: know(exp.X_add_symbol == NULL); ! 2654: /* fall into SEG_ABSOLUTE */ ! 2655: ! 2656: case SEG_ABSOLUTE: ! 2657: get = exp.X_add_number; ! 2658: use = get & unmask; ! 2659: if((get & mask) && (get & mask) != mask){ ! 2660: /* Leading bits contain both 0s & 1s. */ ! 2661: as_warn("Value x%x truncated to x%x.", (unsigned int)get, ! 2662: (unsigned int)use); ! 2663: } ! 2664: /* put bytes in right order. */ ! 2665: md_number_to_chars(p, use, nbytes); ! 2666: break; ! 2667: ! 2668: case SEG_DIFFSECT: ! 2669: case SEG_UNKNOWN: ! 2670: case SEG_SECT: ! 2671: fix_new(frag_now, ! 2672: p - frag_now->fr_literal, ! 2673: nbytes, ! 2674: exp.X_add_symbol, ! 2675: exp.X_subtract_symbol, ! 2676: exp.X_add_number, ! 2677: 0, ! 2678: 0, ! 2679: 0); ! 2680: break; ! 2681: ! 2682: default: ! 2683: BAD_CASE(segment); ! 2684: break; ! 2685: } /* switch(segment) */ ! 2686: c = *input_line_pointer++; ! 2687: } /* while(c==',') */ ! 2688: input_line_pointer--; /* Put terminator back into stream. */ ! 2689: demand_empty_rest_of_line(); ! 2690: } ! 2691: ! 2692: #ifdef M68K /* we allow big cons only on the 68k machines */ ! 2693: /* ! 2694: * big_cons() ! 2695: * ! 2696: * CONStruct more frag(s) of .quads, or .octa etc. ! 2697: * Makes 0 or more new frags. ! 2698: * This understands only bignums, not expressions. Cons() understands ! 2699: * expressions. ! 2700: * ! 2701: * Constants recognised are '0...'(octal) '0x...'(hex) '...'(decimal). ! 2702: * ! 2703: * This creates objects with struct obstack_control objs, destroying ! 2704: * any context objs held about a partially completed object. Beware! ! 2705: * ! 2706: * ! 2707: * I think it sucks to have 2 different types of integers, with 2 ! 2708: * routines to read them, store them etc. ! 2709: * It would be nicer to permit bignums in expressions and only ! 2710: * complain if the result overflowed. However, due to "efficiency"... ! 2711: * ! 2712: * Worker function to do .quad and .octa statements. ! 2713: * This clobbers input_line_pointer, checks end-of-line. ! 2714: */ ! 2715: void ! 2716: big_cons( ! 2717: int nbytes) /* 8 == .quad, 16 == .octa ... */ ! 2718: { ! 2719: char c; /* input_line_pointer -> c. */ ! 2720: int radix; ! 2721: long length;/* Number of chars in an object. */ ! 2722: int digit; /* Value of 1 digit. */ ! 2723: int carry; /* For multi-precision arithmetic. */ ! 2724: int work; /* For multi-precision arithmetic. */ ! 2725: char *p,*q; /* For multi-precision arithmetic. */ ! 2726: int i; ! 2727: ! 2728: /* ! 2729: * The following awkward logic is to parse ZERO or more strings, ! 2730: * comma seperated. Recall an expression includes its leading & ! 2731: * trailing blanks. We fake a leading ',' if there is (supposed to ! 2732: * be) a 1st expression, and keep demanding 1 expression for each ','. ! 2733: */ ! 2734: if(is_it_end_of_statement()){ ! 2735: c = 0; /* Skip loop. */ ! 2736: } ! 2737: else{ ! 2738: c = ','; /* Do loop. */ ! 2739: --input_line_pointer; ! 2740: } ! 2741: while(c == ','){ ! 2742: ++input_line_pointer; ! 2743: SKIP_WHITESPACE(); ! 2744: c = *input_line_pointer; ! 2745: /* c contains 1st non-blank char of what we hope is a number */ ! 2746: if(c == '0'){ ! 2747: c = *++input_line_pointer; ! 2748: if(c == 'x' || c=='X'){ ! 2749: c = *++input_line_pointer; ! 2750: radix = 16; ! 2751: } ! 2752: else{ ! 2753: radix = 8; ! 2754: } ! 2755: } ! 2756: else{ ! 2757: radix = 10; ! 2758: } ! 2759: /* ! 2760: * This feature (?) is here to stop people worrying about ! 2761: * mysterious zero constants: which is what they get when ! 2762: * they completely omit digits. ! 2763: */ ! 2764: if(hex_value[(int)c] >= radix){ ! 2765: as_warn("Missing digits. 0 assumed."); ! 2766: } ! 2767: bignum_high = bignum_low - 1; /* Start constant with 0 chars. */ ! 2768: for( ; ! 2769: (digit = hex_value[(int)c]) < radix; ! 2770: c = *++input_line_pointer){ ! 2771: /* Multiply existing number by radix, then add digit. */ ! 2772: carry = digit; ! 2773: for(p = bignum_low; p <= bignum_high; p++){ ! 2774: work = (*p & MASK_CHAR) * radix + carry; ! 2775: *p = work & MASK_CHAR; ! 2776: carry = work >> BITS_PER_CHAR; ! 2777: } ! 2778: if(carry){ ! 2779: grow_bignum(); ! 2780: *bignum_high = carry & MASK_CHAR; ! 2781: know((carry & ~ MASK_CHAR) == 0); ! 2782: } ! 2783: } ! 2784: length = bignum_high - bignum_low + 1; ! 2785: if(length > nbytes){ ! 2786: as_warn("Most significant bits truncated in integer constant."); ! 2787: } ! 2788: else{ ! 2789: long leading_zeroes; ! 2790: ! 2791: for(leading_zeroes = nbytes - length; ! 2792: leading_zeroes; ! 2793: leading_zeroes--){ ! 2794: grow_bignum(); ! 2795: *bignum_high = 0; ! 2796: } ! 2797: } ! 2798: p = frag_more(nbytes); ! 2799: if(md_target_byte_sex == BIG_ENDIAN_BYTE_SEX){ ! 2800: q = (char *)bignum_low; ! 2801: for(i = nbytes - 1; i >= 0; i--) ! 2802: *p++ = q[i]; ! 2803: } ! 2804: else{ ! 2805: memcpy(p, bignum_low, (int)nbytes); ! 2806: } ! 2807: /* C contains character after number. */ ! 2808: SKIP_WHITESPACE(); ! 2809: c = *input_line_pointer; ! 2810: /* C contains 1st non-blank character after number. */ ! 2811: } ! 2812: demand_empty_rest_of_line(); ! 2813: } ! 2814: ! 2815: /* ! 2816: * grow_bignum() extends bignum (that is adjust bignum_low, bignum_high and ! 2817: * bignum_limit). ! 2818: */ ! 2819: static ! 2820: void ! 2821: grow_bignum( ! 2822: void) ! 2823: { ! 2824: long length; ! 2825: ! 2826: bignum_high++; ! 2827: if(bignum_high >= bignum_limit) ! 2828: { ! 2829: length = bignum_limit - bignum_low; ! 2830: bignum_low = xrealloc(bignum_low, length + length); ! 2831: bignum_high = bignum_low + length; ! 2832: bignum_limit = bignum_low + length + length; ! 2833: } ! 2834: } ! 2835: #endif /* M68K we allow big cons only on the 68k machines */ ! 2836: ! 2837: /* ! 2838: * float_cons() ! 2839: * ! 2840: * CONStruct some more frag chars of .floats .ffloats etc. ! 2841: * Makes 0 or more new frags. ! 2842: * This understands only floating literals, not expressions. Sorry. ! 2843: * ! 2844: * A floating constant is defined by atof_generic(), except it is preceded ! 2845: * by 0d 0f 0g or 0h. After observing the STRANGE way my BSD AS does its ! 2846: * reading, I decided to be incompatible. This always tries to give you ! 2847: * rounded bits to the precision of the pseudo-op. Former AS did premature ! 2848: * truncatation, restored noisy bits instead of trailing 0s AND gave you ! 2849: * a choice of 2 flavours of noise according to which of 2 floating-point ! 2850: * scanners you directed AS to use. ! 2851: * ! 2852: * In: input_line_pointer -> whitespace before, or '0' of flonum. ! 2853: * ! 2854: * Worker function to do .double, .float, .single statements. ! 2855: * This clobbers input_line-pointer, checks end-of-line. ! 2856: */ ! 2857: void ! 2858: float_cons( ! 2859: int float_type) /* 'f':.ffloat ... 'F':.float ... */ ! 2860: { ! 2861: char *p; ! 2862: char c; ! 2863: int length; /* Number of chars in an object. */ ! 2864: char *err; /* Error from scanning floating literal. */ ! 2865: char temp[MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT]; ! 2866: ! 2867: /* ! 2868: * The following awkward logic is to parse ZERO or more strings, ! 2869: * comma seperated. Recall an expression includes its leading & ! 2870: * trailing blanks. We fake a leading ',' if there is (supposed to ! 2871: * be) a 1st expression, and keep demanding 1 expression for each ','. ! 2872: */ ! 2873: if(is_it_end_of_statement()){ ! 2874: c = 0; /* Skip loop. */ ! 2875: ++input_line_pointer; /* -> past termintor. */ ! 2876: } ! 2877: else{ ! 2878: c = ','; /* Do loop. */ ! 2879: } ! 2880: while(c == ','){ ! 2881: /* input_line_pointer -> 1st char of a flonum (we hope!). */ ! 2882: SKIP_WHITESPACE(); ! 2883: /* ! 2884: * Skip any 0{letter} that may be present. Don't even check if the ! 2885: * letter is legal. Someone may invent a "z" format and this routine ! 2886: * has no use for such information. Lusers beware: you get ! 2887: * diagnostics if your input is ill-conditioned. ! 2888: */ ! 2889: if(input_line_pointer[0] == '0' && isalpha(input_line_pointer[1])) ! 2890: input_line_pointer+=2; ! 2891: ! 2892: err = md_atof(float_type, temp, &length); ! 2893: know(length <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT); ! 2894: know(length > 0); ! 2895: if(*err != '\0'){ ! 2896: as_warn( "Bad floating literal: %s", err); ! 2897: ignore_rest_of_line(); ! 2898: /* Input_line_pointer -> just after end-of-line. */ ! 2899: c = 0; /* Break out of loop. */ ! 2900: } ! 2901: else{ ! 2902: p = frag_more(length); ! 2903: memcpy(p, temp, length); ! 2904: SKIP_WHITESPACE(); ! 2905: c = *input_line_pointer ++; ! 2906: /* C contains 1st non-white character after number. */ ! 2907: /* input_line_pointer -> just after terminator (c). */ ! 2908: } ! 2909: } ! 2910: --input_line_pointer; /* -> terminator (is not ','). */ ! 2911: demand_empty_rest_of_line(); ! 2912: } ! 2913: ! 2914: /* ! 2915: * stringer() ! 2916: * ! 2917: * We read 0 or more ',' seperated, double-quoted strings. ! 2918: * ! 2919: * Worker function to do .ascii etc statements. ! 2920: * Checks end-of-line. ! 2921: */ ! 2922: void ! 2923: stringer( ! 2924: int append_zero) /* 0: don't append '\0', else 1 */ ! 2925: { ! 2926: int c; ! 2927: ! 2928: /* ! 2929: * The following awkward logic is to parse ZERO or more strings, ! 2930: * comma seperated. Recall a string expression includes spaces ! 2931: * before the opening '\"' and spaces after the closing '\"'. ! 2932: * We fake a leading ',' if there is (supposed to be) ! 2933: * a 1st, expression. We keep demanding expressions for each ! 2934: * ','. ! 2935: */ ! 2936: if(is_it_end_of_statement()){ ! 2937: c = 0; /* Skip loop. */ ! 2938: ++ input_line_pointer; /* Compensate for end of loop. */ ! 2939: } ! 2940: else{ ! 2941: c = ','; /* Do loop. */ ! 2942: } ! 2943: for( ; c == ','; c = *input_line_pointer++){ ! 2944: SKIP_WHITESPACE(); ! 2945: if(*input_line_pointer == '\"'){ ! 2946: ++input_line_pointer; /* -> 1st char of string. */ ! 2947: while((c = next_char_of_string()) >= 0){ ! 2948: FRAG_APPEND_1_CHAR(c); ! 2949: } ! 2950: if(append_zero){ ! 2951: FRAG_APPEND_1_CHAR(0); ! 2952: } ! 2953: know(input_line_pointer[-1] == '\"'); ! 2954: } ! 2955: else{ ! 2956: as_warn("Expected \"-ed string"); ! 2957: } ! 2958: SKIP_WHITESPACE(); ! 2959: } ! 2960: --input_line_pointer; ! 2961: demand_empty_rest_of_line(); ! 2962: } ! 2963: ! 2964: /* ! 2965: * next_char_of_string() is used by stringer() and demand_copy_string() and ! 2966: * returns the next character from input_line_pointer that is in the string or ! 2967: * -1 for the trailing " character. This routine handles escaped characters ! 2968: * like \b, \f, etc. ! 2969: */ ! 2970: static ! 2971: int ! 2972: next_char_of_string( ! 2973: void) ! 2974: { ! 2975: int c; ! 2976: long number, i; ! 2977: ! 2978: c = *input_line_pointer++; ! 2979: /* make sure the 0xff char is not returned as -1 */ ! 2980: c = (c & MASK_CHAR); ! 2981: switch(c){ ! 2982: case '\"': ! 2983: c = -1; ! 2984: break; ! 2985: ! 2986: case '\\': ! 2987: c = *input_line_pointer++; ! 2988: switch(c){ ! 2989: case 'b': ! 2990: c = '\b'; ! 2991: break; ! 2992: case 'f': ! 2993: c = '\f'; ! 2994: break; ! 2995: case 'n': ! 2996: c = '\n'; ! 2997: break; ! 2998: case 'r': ! 2999: c = '\r'; ! 3000: break; ! 3001: case 't': ! 3002: c = '\t'; ! 3003: break; ! 3004: case '\\': ! 3005: case '"': ! 3006: break; /* As itself. */ ! 3007: case '0': ! 3008: case '1': ! 3009: case '2': ! 3010: case '3': ! 3011: case '4': ! 3012: case '5': ! 3013: case '6': ! 3014: case '7': ! 3015: case '8': ! 3016: case '9': ! 3017: for(i = 0, number = 0; ! 3018: i < 3 && isdigit(c) && c < '8'; ! 3019: i++, c = *input_line_pointer++) ! 3020: number = number * 8 + c - '0'; ! 3021: c = number; ! 3022: --input_line_pointer; ! 3023: break; ! 3024: case '\n': ! 3025: /* To be compatible with BSD 4.2 as: give the user a linefeed */ ! 3026: c = '\n'; ! 3027: break; ! 3028: ! 3029: default: ! 3030: as_warn( "Bad escaped character in string, '?' assumed" ); ! 3031: c = '?'; ! 3032: break; ! 3033: } ! 3034: break; ! 3035: default: ! 3036: break; ! 3037: } ! 3038: return(c); ! 3039: } ! 3040: ! 3041: /* ! 3042: * get_segmented_expression() is passed an expression to fill in and return that ! 3043: * is anything except a bignum or a missing expression. ! 3044: */ ! 3045: static ! 3046: segT ! 3047: get_segmented_expression( ! 3048: expressionS *expP) ! 3049: { ! 3050: segT retval; ! 3051: ! 3052: retval = expression(expP); ! 3053: if(retval == SEG_NONE || retval == SEG_BIG){ ! 3054: as_warn("Expected address expression: absolute 0 assumed"); ! 3055: retval = expP->X_seg = SEG_ABSOLUTE; ! 3056: expP->X_add_number = 0; ! 3057: expP->X_add_symbol = NULL; ! 3058: expP->X_subtract_symbol = NULL; ! 3059: } ! 3060: return(retval); /* SEG_ ABSOLUTE,UNKNOWN,SECT */ ! 3061: } ! 3062: ! 3063: /* ! 3064: * get_known_segmented_expression() is passed an expression to fill in and ! 3065: * return that is anything except an unknown, bignum or a missing expression. ! 3066: */ ! 3067: segT ! 3068: get_known_segmented_expression( ! 3069: expressionS *expP) ! 3070: { ! 3071: segT retval; ! 3072: char *name1; ! 3073: char *name2; ! 3074: ! 3075: retval = get_segmented_expression(expP); ! 3076: if(retval == SEG_UNKNOWN){ ! 3077: name1 = expP->X_add_symbol ? ! 3078: expP->X_add_symbol->sy_name : ""; ! 3079: name2 = expP->X_subtract_symbol ? ! 3080: expP->X_subtract_symbol->sy_name : ""; ! 3081: if(name1 && name2){ ! 3082: as_warn("Symbols \"%s\" \"%s\" are undefined: absolute 0 " ! 3083: "assumed.", name1, name2); ! 3084: } ! 3085: else{ ! 3086: as_warn("Symbol \"%s\" undefined: absolute 0 assumed.", ! 3087: name1 ? name1 : name2); ! 3088: } ! 3089: retval = SEG_ABSOLUTE; ! 3090: expP->X_seg = SEG_ABSOLUTE; ! 3091: expP->X_add_number = 0; ! 3092: expP->X_add_symbol = NULL; ! 3093: expP->X_subtract_symbol = NULL; ! 3094: } ! 3095: know(retval == SEG_ABSOLUTE || ! 3096: retval == SEG_SECT || ! 3097: retval == SEG_DIFFSECT); ! 3098: return(retval); ! 3099: } ! 3100: ! 3101: /* ! 3102: * get_absolute_expression() gets an absolute expression and returns the value ! 3103: * of that expression. ! 3104: */ ! 3105: long ! 3106: get_absolute_expression( ! 3107: void) ! 3108: { ! 3109: expressionS exp; ! 3110: segT s; ! 3111: ! 3112: s = expression(&exp); ! 3113: if(s != SEG_ABSOLUTE){ ! 3114: /* is this right? if not absolute: no message and return 0 */ ! 3115: if(s != SEG_NONE){ ! 3116: as_warn("Bad Absolute Expression, absolute 0 assumed."); ! 3117: } ! 3118: exp.X_add_number = 0; ! 3119: } ! 3120: return(exp.X_add_number); ! 3121: } ! 3122: ! 3123: /* ! 3124: * get_absolute_expression_and_terminator() gets an absolute expression and ! 3125: * returning the value of that expression indirectly through val_pointer and ! 3126: * returns the terminator. ! 3127: */ ! 3128: static ! 3129: char /* return terminator */ ! 3130: get_absolute_expression_and_terminator( ! 3131: long *val_pointer) /* return value of expression */ ! 3132: { ! 3133: *val_pointer = get_absolute_expression(); ! 3134: return(*input_line_pointer++); ! 3135: } ! 3136: ! 3137: /* ! 3138: * demand_copy_C_string() ! 3139: * ! 3140: * Like demand_copy_string, but return NULL if the string contains any '\0's. ! 3141: * Give a warning if that happens. ! 3142: */ ! 3143: static ! 3144: char * ! 3145: demand_copy_C_string( ! 3146: int *len_pointer) ! 3147: { ! 3148: char *s; ! 3149: int len; ! 3150: ! 3151: if((s = demand_copy_string(len_pointer))){ ! 3152: for(len = *len_pointer; len > 0; len--){ ! 3153: if(*s == '\0'){ ! 3154: s = 0; ! 3155: len = 1; ! 3156: *len_pointer = 0; ! 3157: as_warn("This string may not contain \'\\0\'"); ! 3158: } ! 3159: } ! 3160: } ! 3161: return(s); ! 3162: } ! 3163: ! 3164: /* ! 3165: * demand_copy_string() ! 3166: * ! 3167: * Demand string, but return a safe (=private) copy of the string. ! 3168: * Return NULL if we can't read a string here. ! 3169: */ ! 3170: static ! 3171: char * ! 3172: demand_copy_string( ! 3173: int *lenP) ! 3174: { ! 3175: int c; ! 3176: int len; ! 3177: char *retval; ! 3178: ! 3179: len = 0; ! 3180: SKIP_WHITESPACE(); ! 3181: if(*input_line_pointer == '\"'){ ! 3182: input_line_pointer++; /* Skip opening quote. */ ! 3183: while((c = next_char_of_string()) >= 0){ ! 3184: obstack_1grow(¬es, c); ! 3185: len++; ! 3186: } ! 3187: /* ! 3188: * This next line is so demand_copy_C_string will return a null ! 3189: * termanated string. ! 3190: */ ! 3191: obstack_1grow(¬es, '\0'); ! 3192: retval = obstack_finish(¬es); ! 3193: } ! 3194: else{ ! 3195: as_warn("Missing string"); ! 3196: retval = NULL; ! 3197: ignore_rest_of_line(); ! 3198: } ! 3199: *lenP = len; ! 3200: return(retval); ! 3201: } ! 3202: ! 3203: /* ! 3204: * is_it_end_of_statement() ! 3205: * ! 3206: * In: Input_line_pointer -> next character. ! 3207: * ! 3208: * Do: Skip input_line_pointer over all whitespace. ! 3209: * ! 3210: * Out: TRUE if input_line_pointer -> end-of-line. ! 3211: */ ! 3212: static ! 3213: int ! 3214: is_it_end_of_statement( ! 3215: void) ! 3216: { ! 3217: SKIP_WHITESPACE(); ! 3218: return(is_end_of_line[(int)*input_line_pointer]); ! 3219: } ! 3220: ! 3221: /* ! 3222: * equals() implements the assembly statement: ! 3223: * x = expression ! 3224: */ ! 3225: static ! 3226: void ! 3227: equals( ! 3228: char *sym_name) ! 3229: { ! 3230: struct symbol *symbolP; ! 3231: segT segment; ! 3232: expressionS exp; ! 3233: char *p; ! 3234: ! 3235: /* Turn '. = mumble' into a .org mumble */ ! 3236: if(sym_name[0]=='.' && sym_name[1]=='\0'){ ! 3237: if(input_line_pointer[1] == '=') ! 3238: input_line_pointer += 2; ! 3239: else ! 3240: *input_line_pointer++ = '='; /* Put it back */ ! 3241: if(*input_line_pointer==' ' || *input_line_pointer=='\t') ! 3242: input_line_pointer++; ! 3243: segment = get_known_segmented_expression(&exp); ! 3244: if((segment != SEG_SECT || ! 3245: exp.X_add_symbol->sy_other != frchain_now->frch_nsect) && ! 3246: segment != SEG_ABSOLUTE) ! 3247: as_warn("Illegal expression. current section assumed."); ! 3248: p = frag_var(rs_org, ! 3249: 1, ! 3250: 1, ! 3251: (relax_substateT)0, ! 3252: exp.X_add_symbol, ! 3253: exp.X_add_number, ! 3254: (char *)0); ! 3255: *p = 0; ! 3256: return; ! 3257: } ! 3258: ! 3259: symbolP = symbol_find_or_make(sym_name); ! 3260: if(input_line_pointer[1] == '=') ! 3261: input_line_pointer += 2; ! 3262: else ! 3263: *input_line_pointer++ = '='; /* Put it back */ ! 3264: if(*input_line_pointer==' ' || *input_line_pointer=='\t') ! 3265: input_line_pointer++; ! 3266: pseudo_set(symbolP); ! 3267: } ! 3268: ! 3269: /* ! 3270: * s_if() implements the pseudo op: ! 3271: * .if expression ! 3272: * that does conditional assembly using assembler defined expressions. ! 3273: */ ! 3274: static ! 3275: void ! 3276: s_if( ! 3277: int value) ! 3278: { ! 3279: if(if_depth >= MAX_IF_DEPTH) ! 3280: as_fatal("You can't nest if's more than %d levels deep", ! 3281: MAX_IF_DEPTH); ! 3282: last_states[if_depth++] = the_cond_state; ! 3283: the_cond_state.the_cond = if_cond; ! 3284: if(the_cond_state.ignore) ! 3285: totally_ignore_line(); ! 3286: else{ ! 3287: the_cond_state.cond_met = get_absolute_expression(); ! 3288: the_cond_state.ignore = !the_cond_state.cond_met; ! 3289: demand_empty_rest_of_line(); ! 3290: } ! 3291: } ! 3292: ! 3293: /* ! 3294: * s_elseif() implements the pseudo op: ! 3295: * .elseif expression ! 3296: * that does conditional assembly using assembler defined expressions. ! 3297: */ ! 3298: static ! 3299: void ! 3300: s_elseif( ! 3301: int value) ! 3302: { ! 3303: int last_ignore_state; ! 3304: ! 3305: if(the_cond_state.the_cond != if_cond && ! 3306: the_cond_state.the_cond != elseif_cond) ! 3307: as_fatal("Encountered a .elseif that doesn't follow a .if or an " ! 3308: ".elseif"); ! 3309: the_cond_state.the_cond = elseif_cond; ! 3310: ! 3311: last_ignore_state = FALSE; ! 3312: if(if_depth) ! 3313: last_ignore_state = last_states[if_depth-1].ignore; ! 3314: if(last_ignore_state || the_cond_state.cond_met){ ! 3315: the_cond_state.ignore = TRUE; ! 3316: totally_ignore_line(); ! 3317: } ! 3318: else{ ! 3319: the_cond_state.cond_met = get_absolute_expression(); ! 3320: the_cond_state.ignore = !the_cond_state.cond_met; ! 3321: demand_empty_rest_of_line(); ! 3322: } ! 3323: } ! 3324: ! 3325: /* ! 3326: * s_else() implements the pseudo op: ! 3327: * .else ! 3328: * that does conditional assembly using assembler defined expressions. ! 3329: */ ! 3330: static ! 3331: void ! 3332: s_else( ! 3333: int value) ! 3334: { ! 3335: int last_ignore_state; ! 3336: ! 3337: if(the_cond_state.the_cond != if_cond && ! 3338: the_cond_state.the_cond != elseif_cond) ! 3339: as_fatal("Encountered a .else that doesn't follow a .if or an " ! 3340: ".elseif"); ! 3341: the_cond_state.the_cond = else_cond; ! 3342: last_ignore_state = FALSE; ! 3343: if(if_depth) ! 3344: last_ignore_state = last_states[if_depth-1].ignore; ! 3345: if(last_ignore_state || the_cond_state.cond_met) ! 3346: the_cond_state.ignore = TRUE; ! 3347: else ! 3348: the_cond_state.ignore = FALSE; ! 3349: demand_empty_rest_of_line(); ! 3350: } ! 3351: ! 3352: /* ! 3353: * s_endif() implements the pseudo op: ! 3354: * .endif ! 3355: * that does conditional assembly using assembler defined expressions. ! 3356: */ ! 3357: static ! 3358: void ! 3359: s_endif( ! 3360: int value) ! 3361: { ! 3362: if((the_cond_state.the_cond == no_cond) || (if_depth == 0)) ! 3363: as_fatal("Encountered a .endif that doesn't follow a .if or .else"); ! 3364: the_cond_state = last_states[--if_depth]; ! 3365: demand_empty_rest_of_line(); ! 3366: } ! 3367: ! 3368: /* ! 3369: * totally_ignore_line() ignores lines during conditional assembly. ! 3370: */ ! 3371: void ! 3372: totally_ignore_line( ! 3373: void) ! 3374: { ! 3375: if(!is_end_of_line[(int)*input_line_pointer]){ ! 3376: while(input_line_pointer < buffer_limit && ! 3377: !is_end_of_line[(int)*input_line_pointer]){ ! 3378: input_line_pointer ++; ! 3379: } ! 3380: } ! 3381: input_line_pointer++; /* Return pointing just after end-of-line. */ ! 3382: know(is_end_of_line[(int)(input_line_pointer[-1])]); ! 3383: } ! 3384: ! 3385: /* ! 3386: * s_macros_on() implements the pseudo op: ! 3387: * .macros_on ! 3388: */ ! 3389: static ! 3390: void ! 3391: s_macros_on( ! 3392: int value) ! 3393: { ! 3394: macros_on = TRUE; ! 3395: demand_empty_rest_of_line(); ! 3396: } ! 3397: ! 3398: /* ! 3399: * s_macros_off() implements the pseudo op: ! 3400: * .macros_off ! 3401: */ ! 3402: void ! 3403: s_macros_off( ! 3404: int value) ! 3405: { ! 3406: macros_on = FALSE; ! 3407: demand_empty_rest_of_line(); ! 3408: } ! 3409: ! 3410: /* ! 3411: * s_macro() implements the pseudo op: ! 3412: * .macro macro_name ! 3413: * that defines a macro. ! 3414: */ ! 3415: void ! 3416: s_macro( ! 3417: int value) ! 3418: { ! 3419: int c; ! 3420: pseudo_typeS *pop; ! 3421: ! 3422: if(macro_name) ! 3423: as_warn("Can't define a macro inside another macro definition"); ! 3424: else{ ! 3425: SKIP_WHITESPACE(); ! 3426: while(is_part_of_name(c = *input_line_pointer ++)) ! 3427: obstack_1grow (¯os, c); ! 3428: obstack_1grow(¯os, '\0'); ! 3429: --input_line_pointer; ! 3430: macro_name = obstack_finish(¯os); ! 3431: if(macro_name == "") ! 3432: as_warn("Missing name of macro"); ! 3433: if(*macro_name == '.'){ ! 3434: pop = (pseudo_typeS *)hash_find(po_hash, macro_name + 1); ! 3435: if(pop != NULL) ! 3436: as_warn("Pseudo-op name: %s can't be a macro name", ! 3437: macro_name); ! 3438: } ! 3439: } ! 3440: totally_ignore_line(); ! 3441: } ! 3442: ! 3443: /* ! 3444: * s_endmacro() implements the pseudo op: ! 3445: * .endmacro ! 3446: * which is the end of a macro definition. ! 3447: */ ! 3448: void ! 3449: s_endmacro( ! 3450: int value) ! 3451: { ! 3452: char *errorString; ! 3453: ! 3454: if(!macro_name){ ! 3455: as_warn ("This .endmacro does not match with a preceeding .macro"); ! 3456: ignore_rest_of_line(); ! 3457: } ! 3458: else{ ! 3459: obstack_1grow(¯os, '\0'); ! 3460: errorString = hash_insert(ma_hash, macro_name, ! 3461: obstack_finish(¯os)); ! 3462: if(*errorString) ! 3463: as_warn("The macro named \"%s\" is already defined", ! 3464: macro_name); ! 3465: macro_name = FALSE; ! 3466: } ! 3467: } ! 3468: ! 3469: /* ! 3470: * macro_begin() initializes macros. ! 3471: */ ! 3472: static ! 3473: void ! 3474: macro_begin( ! 3475: void) ! 3476: { ! 3477: ma_hash = hash_new(); ! 3478: obstack_begin(¯os, 5000); ! 3479: } ! 3480: ! 3481: /* ! 3482: * add_to_macro_definition() is called after a .macro to store the contents of ! 3483: * a macro into the obstack. ! 3484: */ ! 3485: void ! 3486: add_to_macro_definition( ! 3487: char *char_pointer) ! 3488: { ! 3489: char c; ! 3490: ! 3491: do{ ! 3492: c = *char_pointer ++; ! 3493: know(c != '\0'); ! 3494: obstack_1grow(¯os, c); ! 3495: }while((c != ':') && !(is_end_of_line[(int)c])); ! 3496: if(char_pointer > input_line_pointer) ! 3497: input_line_pointer = char_pointer; ! 3498: } ! 3499: ! 3500: /* ! 3501: * expand_macro() is called to expand macros. ! 3502: */ ! 3503: static ! 3504: void ! 3505: expand_macro( ! 3506: char *macro_contents) ! 3507: { ! 3508: char *buffer; ! 3509: char c; ! 3510: int index, nargs; ! 3511: char *last_buffer_limit; ! 3512: int last_count_lines; ! 3513: char *last_input_line_pointer; ! 3514: char *arguments [10]; /* at most 10 arguments, each is substituted */ ! 3515: ! 3516: if(macro_depth >= MAX_MACRO_DEPTH) ! 3517: as_fatal("You can't nest macro's more than %d levels deep", ! 3518: MAX_MACRO_DEPTH); ! 3519: macro_depth++; ! 3520: ! 3521: /* copy each argument to a object in the macro obstack */ ! 3522: nargs = 0; ! 3523: for(index = 0; index < 10; index ++){ ! 3524: if(*input_line_pointer == ' ') ! 3525: ++input_line_pointer; ! 3526: know(*input_line_pointer != ' '); ! 3527: c = *input_line_pointer; ! 3528: if(is_end_of_line[(int)c]) ! 3529: arguments[index] = NULL; ! 3530: else{ ! 3531: int parenthesis_depth = 0; ! 3532: do{ ! 3533: c = *input_line_pointer++; ! 3534: if(parenthesis_depth){ ! 3535: if(c == ')') ! 3536: parenthesis_depth --; ! 3537: } ! 3538: else{ ! 3539: if(c == '(') ! 3540: parenthesis_depth ++; ! 3541: else ! 3542: if(is_end_of_line[(int)c] || ! 3543: (c == ' ') || (c == ',')) ! 3544: break; ! 3545: } ! 3546: know(c != '\0'); ! 3547: if(is_end_of_line[(int)c]) ! 3548: as_warn("missmatched parenthesis"); ! 3549: obstack_1grow(¯os, c); ! 3550: }while(1); ! 3551: obstack_1grow(¯os, '\0'); ! 3552: arguments[index] = obstack_finish(¯os); ! 3553: nargs++; ! 3554: if(is_end_of_line[(int)c]) ! 3555: --input_line_pointer; ! 3556: else if(c == ' ') ! 3557: if(*input_line_pointer == ',') ! 3558: input_line_pointer++; ! 3559: } ! 3560: } ! 3561: if(!is_end_of_line[(int)c]){ ! 3562: as_warn("More than 10 arguments not allowed for macros"); ! 3563: ignore_rest_of_line(); ! 3564: } ! 3565: /* ! 3566: * Build a buffer containing the macro contents with arguments ! 3567: * substituted ! 3568: */ ! 3569: obstack_1grow(¯os, '\n'); ! 3570: while((c = *macro_contents++)){ ! 3571: if(c == '$'){ ! 3572: if((*macro_contents >= '0') && (*macro_contents <= '9')){ ! 3573: index = *macro_contents++ - '0'; ! 3574: last_input_line_pointer = macro_contents; ! 3575: macro_contents = arguments[index]; ! 3576: if(macro_contents){ ! 3577: while ((c = * macro_contents ++)) ! 3578: obstack_1grow (¯os, c); ! 3579: } ! 3580: macro_contents = last_input_line_pointer; ! 3581: continue; ! 3582: } ! 3583: else if (*macro_contents == 'n'){ ! 3584: macro_contents++ ; ! 3585: obstack_1grow(¯os, nargs + '0'); ! 3586: continue; ! 3587: } ! 3588: } ! 3589: obstack_1grow (¯os, c); ! 3590: } ! 3591: obstack_1grow (¯os, '\n'); ! 3592: obstack_1grow (¯os, '\0'); ! 3593: last_buffer_limit = buffer_limit; ! 3594: last_count_lines = count_lines; ! 3595: last_input_line_pointer = input_line_pointer; ! 3596: buffer_limit = obstack_next_free (¯os) - 1; ! 3597: buffer = obstack_finish (¯os); ! 3598: count_lines = FALSE; ! 3599: /* ! 3600: printf("expanded macro: %s", buffer + 1); ! 3601: */ ! 3602: parse_a_buffer(buffer + 1); ! 3603: obstack_free (¯os, buffer); ! 3604: for(index = 9; index >= 0; index --) ! 3605: if(arguments[index]) ! 3606: obstack_free(¯os, arguments[index]); ! 3607: buffer_limit = last_buffer_limit; ! 3608: count_lines = last_count_lines; ! 3609: input_line_pointer = last_input_line_pointer; ! 3610: macro_depth--; ! 3611: } ! 3612: ! 3613: /* ! 3614: * s_dump() implements the pseudo op: ! 3615: * .dump filename ! 3616: * that does a quick binary dump of symbol tables. ! 3617: */ ! 3618: static ! 3619: void ! 3620: s_dump( ! 3621: int value) ! 3622: { ! 3623: char *filename; ! 3624: int length; ! 3625: static char null_string[] = ""; ! 3626: ! 3627: if((filename = demand_copy_string(&length))){ ! 3628: demand_empty_rest_of_line(); ! 3629: if((dump_fp = fopen(filename, "w+"))){ ! 3630: hash_apply(ma_hash, write_macro); ! 3631: fwrite(null_string, 1, 1, dump_fp); ! 3632: hash_apply(sy_hash, write_symbol); ! 3633: fwrite(null_string, 1, 1, dump_fp); ! 3634: fclose(dump_fp); ! 3635: } ! 3636: else ! 3637: as_warn("couldn't write to dump file: \"%s\"", filename); ! 3638: } ! 3639: } ! 3640: ! 3641: /* ! 3642: * write_macro() used by hash_apply indirectly through s_dump() to write one ! 3643: * macro. ! 3644: */ ! 3645: static ! 3646: char * ! 3647: write_macro( ! 3648: char *string, ! 3649: char *value) ! 3650: { ! 3651: know(string); ! 3652: know(value); ! 3653: know(strlen(string)); ! 3654: fwrite(string, (strlen(string) + 1), 1, dump_fp); ! 3655: fwrite(value, (strlen(value) + 1), 1, dump_fp); ! 3656: return(NULL); ! 3657: } ! 3658: ! 3659: /* ! 3660: * write_symbol() used by hash_apply indirectly through s_dump() to write one ! 3661: * N_ABS symbol and its value. ! 3662: */ ! 3663: static ! 3664: char * ! 3665: write_symbol( ! 3666: char *string, ! 3667: char *value) ! 3668: { ! 3669: symbolS *symbolP; ! 3670: ! 3671: symbolP = (symbolS *)value; ! 3672: know(symbolP); ! 3673: if(((symbolP->sy_type) & N_TYPE) == N_ABS){ ! 3674: know(string); ! 3675: know(strlen(string)); ! 3676: fwrite(string, (strlen(string) + 1), 1, dump_fp); ! 3677: fwrite(&(symbolP -> sy_value), 4, 1, dump_fp); ! 3678: } ! 3679: return(NULL); ! 3680: } ! 3681: ! 3682: /* ! 3683: * s_load() implements the pseudo op: ! 3684: * .load filename ! 3685: * that does a quick binary load of symbol tables. ! 3686: */ ! 3687: static ! 3688: void ! 3689: s_load( ! 3690: int value) ! 3691: { ! 3692: char *char_pointer; ! 3693: char *filename; ! 3694: int length; ! 3695: char the_char; ! 3696: symbolS *the_symbol; ! 3697: symbolS *temp_symbol_lastP; ! 3698: static symbolS *dump_symbol_lastP; ! 3699: ! 3700: if((filename = demand_copy_string(&length))){ ! 3701: demand_empty_rest_of_line(); ! 3702: if((dump_fp = fopen(filename, "r+"))){ ! 3703: do{ ! 3704: do{ ! 3705: the_char = getc(dump_fp); ! 3706: obstack_1grow(¯os, the_char); ! 3707: }while(the_char); ! 3708: char_pointer = obstack_finish (¯os); ! 3709: if(!(*char_pointer)) ! 3710: break; ! 3711: do{ ! 3712: the_char = getc(dump_fp); ! 3713: obstack_1grow(¯os, the_char); ! 3714: }while(the_char); ! 3715: if(*hash_insert(ma_hash, char_pointer, ! 3716: obstack_finish(¯os))) ! 3717: as_warn("a macro named \"%s\" encountered in a .load " ! 3718: "is already defined", char_pointer); ! 3719: }while(1); ! 3720: /* ! 3721: * We don't want to link in symbols that were loaded so they ! 3722: * don't go out in the object file. Instead these symbols ! 3723: * should go out in the object file that did the .dump . ! 3724: */ ! 3725: temp_symbol_lastP = symbol_lastP; ! 3726: symbol_lastP = dump_symbol_lastP; ! 3727: do{ ! 3728: do{ ! 3729: the_char = getc(dump_fp); ! 3730: obstack_1grow(¯os, the_char); ! 3731: }while(the_char); ! 3732: char_pointer = obstack_base(¯os); ! 3733: obstack_next_free(¯os) = char_pointer; ! 3734: if(!(*char_pointer)) ! 3735: break; ! 3736: the_symbol = symbol_find_or_make(char_pointer); ! 3737: the_symbol->sy_type = N_ABS; ! 3738: char_pointer = (char *)&the_symbol->sy_value; ! 3739: *char_pointer++ = getc(dump_fp); ! 3740: *char_pointer++ = getc(dump_fp); ! 3741: *char_pointer++ = getc(dump_fp); ! 3742: *char_pointer++ = getc(dump_fp); ! 3743: the_symbol->sy_frag = &zero_address_frag; ! 3744: }while(1); ! 3745: dump_symbol_lastP = symbol_lastP; ! 3746: symbol_lastP = temp_symbol_lastP; ! 3747: fclose(dump_fp); ! 3748: } ! 3749: else ! 3750: as_fatal("Couldn't find the dump file: \"%s\"", filename); ! 3751: } ! 3752: } ! 3753: ! 3754: #ifdef SPARC ! 3755: ! 3756: /* Special stuff to allow assembly of Sun assembler sources ! 3757: This unfortunatley needs to be here instead of sparc.c because it ! 3758: uses the hash tables defined here. ! 3759: see also sparc.c for pseudo_table entries ! 3760: */ ! 3761: ! 3762: /* Handle the SUN sparc assembler .seg directive. .seg should only occur with ! 3763: either a ".text" or ".data" argument. Call .text or .data accordingly ! 3764: */ ! 3765: void ! 3766: s_seg (ignore) ! 3767: int ignore; ! 3768: { ! 3769: pseudo_typeS *ps_t; ! 3770: char s[32]; ! 3771: ! 3772: printf("S_SEG\n"); ! 3773: ! 3774: if (strncmp (input_line_pointer, "\"text\"", 6) == 0) ! 3775: { ! 3776: input_line_pointer += 6; ! 3777: /* relies on .text being first section */ ! 3778: (void)s_builtin_section(builtin_sections); ! 3779: demand_empty_rest_of_line(); ! 3780: return; ! 3781: } ! 3782: if (strncmp (input_line_pointer, "\"data\"", 6) == 0) ! 3783: { ! 3784: /* copy the argument */ ! 3785: input_line_pointer++; ! 3786: strncpy(s, input_line_pointer, 4); ! 3787: input_line_pointer += 5; ! 3788: /* find the section table index for .data */ ! 3789: ps_t = (pseudo_typeS *) hash_find(po_hash, s); ! 3790: ! 3791: if (ps_t == 0) ! 3792: as_bad ("invalid .seg argument"); ! 3793: ! 3794: printf("INDEX %s, %d\n", s, ps_t->poc_val); ! 3795: ! 3796: s_builtin_section ((const struct builtin_section *)ps_t->poc_val); ! 3797: demand_empty_rest_of_line(); ! 3798: return; ! 3799: } ! 3800: as_bad ("Unknown segment type"); ! 3801: demand_empty_rest_of_line (); ! 3802: } ! 3803: ! 3804: #endif /* SPARC */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.