|
|
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.