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