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