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