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