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