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