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