1*49403Sbostic /*-
2*49403Sbostic * This code is derived from software copyrighted by the Free Software
3*49403Sbostic * Foundation.
4*49403Sbostic *
5*49403Sbostic * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
6*49403Sbostic */
747445Sdonn
8*49403Sbostic #ifndef lint
9*49403Sbostic static char sccsid[] = "@(#)read.c 6.4 (Berkeley) 05/08/91";
10*49403Sbostic #endif /* not lint */
1147445Sdonn
1247406Sdonn /* read.c - read a source file -
1347406Sdonn Copyright (C) 1986,1987 Free Software Foundation, Inc.
1447406Sdonn
1547406Sdonn This file is part of GAS, the GNU Assembler.
1647406Sdonn
1747406Sdonn GAS is free software; you can redistribute it and/or modify
1847406Sdonn it under the terms of the GNU General Public License as published by
1947406Sdonn the Free Software Foundation; either version 1, or (at your option)
2047406Sdonn any later version.
2147406Sdonn
2247406Sdonn GAS is distributed in the hope that it will be useful,
2347406Sdonn but WITHOUT ANY WARRANTY; without even the implied warranty of
2447406Sdonn MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2547406Sdonn GNU General Public License for more details.
2647406Sdonn
2747406Sdonn You should have received a copy of the GNU General Public License
2847406Sdonn along with GAS; see the file COPYING. If not, write to
2947406Sdonn the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
3047406Sdonn
3147406Sdonn #define MASK_CHAR (0xFF) /* If your chars aren't 8 bits, you will
3247406Sdonn change this a bit. But then, GNU isn't
3347406Sdonn spozed to run on your machine anyway.
3447406Sdonn (RMS is so shortsighted sometimes.)
3547406Sdonn */
3647406Sdonn
3747406Sdonn #define MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT (16)
3847406Sdonn /* This is the largest known floating point */
3947406Sdonn /* format (for now). It will grow when we */
4047406Sdonn /* do 4361 style flonums. */
4147406Sdonn
4247406Sdonn
4347406Sdonn /* Routines that read assembler source text to build spagetti in memory. */
4447406Sdonn /* Another group of these functions is in the as-expr.c module */
4547406Sdonn
4647406Sdonn #include <ctype.h>
4747406Sdonn #include <sys/types.h>
4847406Sdonn #include <sys/stat.h>
4947406Sdonn #include "as.h"
5047406Sdonn #include "read.h"
5147406Sdonn #include "md.h"
5247406Sdonn #include "hash.h"
5347406Sdonn #include "obstack.h"
5447406Sdonn #include "frags.h"
5547406Sdonn #include "flonum.h"
5647406Sdonn #include "struc-symbol.h"
5747406Sdonn #include "expr.h"
5847406Sdonn #include "symbols.h"
5947406Sdonn
6047406Sdonn #ifdef SPARC
6147406Sdonn #include "sparc.h"
6247406Sdonn #define OTHER_ALIGN
6347406Sdonn #endif
6447406Sdonn #ifdef I860
6547406Sdonn #include "i860.h"
6647406Sdonn #endif
6747406Sdonn
6847406Sdonn char * input_line_pointer; /* -> next char of source file to parse. */
6947406Sdonn
7047406Sdonn
7147406Sdonn #if BITS_PER_CHAR != 8
7247406Sdonn The following table is indexed by [ (char) ] and will break if
7347406Sdonn a char does not have exactly 256 states (hopefully 0:255!) !
7447406Sdonn #endif
7547406Sdonn
7647406Sdonn const char /* used by is_... macros. our ctype[] */
7747406Sdonn lex_type [256] = {
7847406Sdonn 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* @ABCDEFGHIJKLMNO */
7947406Sdonn 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* PQRSTUVWXYZ[\]^_ */
8047406Sdonn 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, /* _!"#$%&'()*+,-./ */
8147406Sdonn 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 0123456789:;<=>? */
8247406Sdonn 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* @ABCDEFGHIJKLMNO */
8347406Sdonn 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 3, /* PQRSTUVWXYZ[\]^_ */
8447406Sdonn 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* `abcdefghijklmno */
8547406Sdonn 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, /* pqrstuvwxyz{|}~. */
8647406Sdonn 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8747406Sdonn 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8847406Sdonn 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8947406Sdonn 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9047406Sdonn 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9147406Sdonn 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9247406Sdonn 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
9347406Sdonn };
9447406Sdonn
9547406Sdonn
9647406Sdonn /*
9747406Sdonn * In: a character.
9847406Sdonn * Out: TRUE if this character ends a line.
9947406Sdonn */
10047406Sdonn #define _ (0)
10147406Sdonn const char is_end_of_line [256] = {
10247406Sdonn _, _, _, _, _, _, _, _, _, _,99, _, _, _, _, _, /* @abcdefghijklmno */
10347406Sdonn _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
10447406Sdonn _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
10547406Sdonn _, _, _, _, _, _, _, _, _, _, _,99, _, _, _, _, /* 0123456789:;<=>? */
10647406Sdonn _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
10747406Sdonn _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
10847406Sdonn _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
10947406Sdonn _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
11047406Sdonn _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
11147406Sdonn _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
11247406Sdonn _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
11347406Sdonn _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
11447406Sdonn _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ /* */
11547406Sdonn };
11647406Sdonn #undef _
11747406Sdonn
11847406Sdonn /* Functions private to this file. */
11947406Sdonn void equals();
12047406Sdonn void big_cons();
12147406Sdonn void cons();
12247406Sdonn static char* demand_copy_C_string();
12347406Sdonn static char* demand_copy_string();
12447406Sdonn void demand_empty_rest_of_line();
12547406Sdonn void float_cons();
12647406Sdonn long int get_absolute_expression();
12747406Sdonn static char get_absolute_expression_and_terminator();
12847406Sdonn static segT get_known_segmented_expression();
12947406Sdonn void ignore_rest_of_line();
13047406Sdonn static int is_it_end_of_statement();
13147406Sdonn static void pobegin();
13247406Sdonn static void pseudo_set();
13347406Sdonn static void stab();
13447406Sdonn static void stringer();
13547406Sdonn
13647406Sdonn extern char line_comment_chars[];
13747406Sdonn
13847406Sdonn static char * buffer_limit; /* -> 1 + last char in buffer. */
13947406Sdonn
14047406Sdonn static char * bignum_low; /* Lowest char of bignum. */
14147406Sdonn static char * bignum_limit; /* 1st illegal address of bignum. */
14247406Sdonn static char * bignum_high; /* Highest char of bignum. */
14347406Sdonn /* May point to (bignum_start-1). */
14447406Sdonn /* Never >= bignum_limit. */
14547406Sdonn static char *old_buffer = 0; /* JF a hack */
14647406Sdonn static char *old_input;
14747406Sdonn static char *old_limit;
14847406Sdonn
14947406Sdonn #ifndef WORKING_DOT_WORD
15047406Sdonn struct broken_word *broken_words;
15147406Sdonn int new_broken_words = 0;
15247406Sdonn #endif
15347406Sdonn
15447406Sdonn static void grow_bignum ();
15547406Sdonn static int next_char_of_string ();
15647406Sdonn
15747406Sdonn void
read_begin()15847406Sdonn read_begin()
15947406Sdonn {
16047406Sdonn pobegin();
16147406Sdonn obstack_begin( ¬es, 5000 );
16247406Sdonn #define BIGNUM_BEGIN_SIZE (16)
16347406Sdonn bignum_low = xmalloc((long)BIGNUM_BEGIN_SIZE);
16447406Sdonn bignum_limit = bignum_low + BIGNUM_BEGIN_SIZE;
16547406Sdonn }
16647406Sdonn
16747406Sdonn /* set up pseudo-op tables */
16847406Sdonn
16947406Sdonn static struct hash_control *
17047406Sdonn po_hash = NULL; /* use before set up: NULL-> address error */
17147406Sdonn
17247406Sdonn
17347406Sdonn void s_abort(), s_align(), s_comm(), s_data();
17447406Sdonn void s_desc(), s_even(), s_file(), s_fill();
17547406Sdonn void s_globl(), s_lcomm(), s_line(), s_lsym();
17647406Sdonn void s_org(), s_set(), s_space(), s_text();
17747406Sdonn #ifdef VMS
17847406Sdonn char const_flag = 0;
17947406Sdonn void s_const();
18047406Sdonn #endif
18147406Sdonn
18247406Sdonn #ifdef DONTDEF
18347406Sdonn void s_gdbline(), s_gdblinetab();
18447406Sdonn void s_gdbbeg(), s_gdbblock(), s_gdbend(), s_gdbsym();
18547406Sdonn #endif
18647406Sdonn
18747406Sdonn void stringer();
18847406Sdonn void cons();
18947406Sdonn void float_cons();
19047406Sdonn void big_cons();
19147406Sdonn void stab();
19247406Sdonn
19347406Sdonn static const pseudo_typeS
19447406Sdonn potable[] =
19547406Sdonn {
19647406Sdonn { "abort", s_abort, 0 },
19747406Sdonn { "align", s_align, 0 },
19847406Sdonn { "ascii", stringer, 0 },
19947406Sdonn { "asciz", stringer, 1 },
20047406Sdonn { "byte", cons, 1 },
20147406Sdonn { "comm", s_comm, 0 },
20247406Sdonn #ifdef VMS
20347406Sdonn { "const", s_const, 0 },
20447406Sdonn #endif
20547406Sdonn { "data", s_data, 0 },
20647406Sdonn { "desc", s_desc, 0 },
20747406Sdonn { "double", float_cons, 'd' },
20847406Sdonn { "file", s_file, 0 },
20947406Sdonn { "fill", s_fill, 0 },
21047406Sdonn { "float", float_cons, 'f' },
21147406Sdonn #ifdef DONTDEF
21247406Sdonn { "gdbbeg", s_gdbbeg, 0 },
21347406Sdonn { "gdbblock", s_gdbblock, 0 },
21447406Sdonn { "gdbend", s_gdbend, 0 },
21547406Sdonn { "gdbsym", s_gdbsym, 0 },
21647406Sdonn { "gdbline", s_gdbline, 0 },
21747406Sdonn { "gdblinetab",s_gdblinetab, 0 },
21847406Sdonn #endif
21947406Sdonn { "globl", s_globl, 0 },
22047406Sdonn { "int", cons, 4 },
22147406Sdonn { "lcomm", s_lcomm, 0 },
22247406Sdonn { "line", s_line, 0 },
22347406Sdonn { "long", cons, 4 },
22447406Sdonn { "lsym", s_lsym, 0 },
22547406Sdonn { "octa", big_cons, 16 },
22647406Sdonn { "org", s_org, 0 },
22747406Sdonn { "quad", big_cons, 8 },
22847406Sdonn { "set", s_set, 0 },
22947406Sdonn { "short", cons, 2 },
23047406Sdonn { "single", float_cons, 'f' },
23147406Sdonn { "space", s_space, 0 },
23247406Sdonn { "stabd", stab, 'd' },
23347406Sdonn { "stabn", stab, 'n' },
23447406Sdonn { "stabs", stab, 's' },
23547406Sdonn { "text", s_text, 0 },
23647406Sdonn #ifndef SPARC
23747406Sdonn { "word", cons, 2 },
23847406Sdonn #endif
23947406Sdonn { NULL} /* end sentinel */
24047406Sdonn };
24147406Sdonn
24247406Sdonn static void
pobegin()24347406Sdonn pobegin()
24447406Sdonn {
24547406Sdonn char * errtxt; /* error text */
24647406Sdonn const pseudo_typeS * pop;
24747406Sdonn
24847406Sdonn po_hash = hash_new();
24947406Sdonn errtxt = ""; /* OK so far */
25047406Sdonn for (pop=potable; pop->poc_name && !*errtxt; pop++)
25147406Sdonn {
25247406Sdonn errtxt = hash_insert (po_hash, pop->poc_name, (char *)pop);
25347406Sdonn }
25447406Sdonn
25547406Sdonn for(pop=md_pseudo_table; pop->poc_name && !*errtxt; pop++)
25647406Sdonn errtxt = hash_insert (po_hash, pop->poc_name, (char *)pop);
25747406Sdonn
25847406Sdonn if (*errtxt)
25947406Sdonn {
26047406Sdonn as_fatal ("error constructing pseudo-op table");
26147406Sdonn }
26247406Sdonn } /* pobegin() */
26347406Sdonn
26447406Sdonn /* read_a_source_file()
26547406Sdonn *
26647406Sdonn * File has already been opened, and will be closed by our caller.
26747406Sdonn *
26847406Sdonn * We read the file, putting things into a web that
26947406Sdonn * represents what we have been reading.
27047406Sdonn */
27147406Sdonn void
read_a_source_file(buffer)27247406Sdonn read_a_source_file (buffer)
27347406Sdonn char * buffer; /* 1st character of each buffer of lines is here. */
27447406Sdonn {
27547406Sdonn register char c;
27647406Sdonn register char * s; /* string of symbol, '\0' appended */
27747406Sdonn register int temp;
27847406Sdonn /* register struct frag * fragP; JF unused */ /* a frag we just made */
27947406Sdonn pseudo_typeS *pop;
28047406Sdonn #ifdef DONTDEF
28147406Sdonn void gdb_block_beg();
28247406Sdonn void gdb_block_position();
28347406Sdonn void gdb_block_end();
28447406Sdonn void gdb_symbols_fixup();
28547406Sdonn #endif
28647406Sdonn
28747406Sdonn subseg_new (SEG_TEXT, 0);
28847406Sdonn while ( buffer_limit = input_scrub_next_buffer (&buffer) )
28947406Sdonn { /* We have another line to parse. */
29047406Sdonn know( buffer_limit [-1] == '\n' ); /* Must have a sentinel. */
29147406Sdonn input_line_pointer = buffer;
29247406Sdonn contin: /* JF this goto is my fault I admit it. Someone brave please re-write
29347406Sdonn the whole input section here? Pleeze??? */
29447406Sdonn while ( input_line_pointer < buffer_limit )
29547406Sdonn { /* We have more of this buffer to parse. */
29647406Sdonn /*
29747406Sdonn * We now have input_line_pointer -> 1st char of next line.
29847406Sdonn * If input_line_pointer [-1] == '\n' then we just
29947406Sdonn * scanned another line: so bump line counters.
30047406Sdonn */
30147406Sdonn if (input_line_pointer [-1] == '\n')
30247406Sdonn {
30347406Sdonn bump_line_counters ();
30447406Sdonn }
30547406Sdonn /*
30647406Sdonn * We are at the begining of a line, or similar place.
30747406Sdonn * We expect a well-formed assembler statement.
30847406Sdonn * A "symbol-name:" is a statement.
30947406Sdonn *
31047406Sdonn * Depending on what compiler is used, the order of these tests
31147406Sdonn * may vary to catch most common case 1st.
31247406Sdonn * Each test is independent of all other tests at the (top) level.
31347406Sdonn * PLEASE make a compiler that doesn't use this assembler.
31447406Sdonn * It is crufty to waste a compiler's time encoding things for this
31547406Sdonn * assembler, which then wastes more time decoding it.
31647406Sdonn * (And communicating via (linear) files is silly!
31747406Sdonn * If you must pass stuff, please pass a tree!)
31847406Sdonn */
31947406Sdonn if ( (c= * input_line_pointer ++) == '\t' || c == ' ' || c=='\f')
32047406Sdonn {
32147406Sdonn c = * input_line_pointer ++;
32247406Sdonn }
32347406Sdonn know( c != ' ' ); /* No further leading whitespace. */
32447406Sdonn /*
32547406Sdonn * C is the 1st significant character.
32647406Sdonn * Input_line_pointer points after that character.
32747406Sdonn */
32847406Sdonn if ( is_name_beginner(c) )
32947406Sdonn { /* want user-defined label or pseudo/opcode */
33047406Sdonn s = -- input_line_pointer;
33147406Sdonn c = get_symbol_end(); /* name's delimiter */
33247406Sdonn /*
33347406Sdonn * C is character after symbol.
33447406Sdonn * That character's place in the input line is now '\0'.
33547406Sdonn * S points to the beginning of the symbol.
33647406Sdonn * [In case of pseudo-op, s -> '.'.]
33747406Sdonn * Input_line_pointer -> '\0' where c was.
33847406Sdonn */
33947406Sdonn if ( c == ':' )
34047406Sdonn {
34147447Sdonn if (flagseen['g'])
34247447Sdonn /* set line number for function definition */
34347447Sdonn funcstab(s);
34447406Sdonn colon(s); /* user-defined label */
34547406Sdonn * input_line_pointer ++ = ':'; /* Put ':' back for error messages' sake. */
34647406Sdonn /* Input_line_pointer -> after ':'. */
34747406Sdonn SKIP_WHITESPACE();
34847406Sdonn }
34947406Sdonn else if(c=='=' || input_line_pointer[1]=='=') /* JF deal with FOO=BAR */
35047406Sdonn {
35147406Sdonn equals(s);
35247406Sdonn demand_empty_rest_of_line();
35347406Sdonn }
35447406Sdonn else
35547406Sdonn { /* expect pseudo-op or machine instruction */
35647406Sdonn if ( *s=='.' )
35747406Sdonn {
35847406Sdonn /*
35947406Sdonn * PSEUDO - OP.
36047406Sdonn *
36147406Sdonn * WARNING: c has next char, which may be end-of-line.
36247406Sdonn * We lookup the pseudo-op table with s+1 because we
36347406Sdonn * already know that the pseudo-op begins with a '.'.
36447406Sdonn */
36547406Sdonn
36647406Sdonn pop= (pseudo_typeS *) hash_find (po_hash, s+1);
36747406Sdonn
36847406Sdonn /* Print the error msg now, while we still can */
36947406Sdonn if(!pop)
37047406Sdonn as_bad("Unknown pseudo-op: '%s'",s);
37147406Sdonn
37247406Sdonn /* Put it back for error messages etc. */
37347406Sdonn * input_line_pointer = c;
37447406Sdonn /* The following skip of whitespace is compulsory. */
37547406Sdonn /* A well shaped space is sometimes all that seperates keyword from operands. */
37647406Sdonn if ( c == ' ' || c == '\t' )
37747406Sdonn { /* Skip seperator after keyword. */
37847406Sdonn input_line_pointer ++;
37947406Sdonn }
38047406Sdonn /*
38147406Sdonn * Input_line is restored.
38247406Sdonn * Input_line_pointer -> 1st non-blank char
38347406Sdonn * after pseudo-operation.
38447406Sdonn */
38547406Sdonn if(!pop) {
38647406Sdonn ignore_rest_of_line();
38747406Sdonn break;
38847406Sdonn }
38947406Sdonn else
39047406Sdonn (*pop->poc_handler)(pop->poc_val);
39147406Sdonn }
39247406Sdonn else
39347406Sdonn { /* machine instruction */
39447445Sdonn /* If source file debugging, emit a stab. */
39547445Sdonn if (flagseen['g'])
39647445Sdonn linestab();
39747445Sdonn
39847406Sdonn /* WARNING: c has char, which may be end-of-line. */
39947406Sdonn /* Also: input_line_pointer -> `\0` where c was. */
40047406Sdonn * input_line_pointer = c;
40147406Sdonn while ( ! is_end_of_line [* input_line_pointer] )
40247406Sdonn {
40347406Sdonn input_line_pointer ++;
40447406Sdonn }
40547406Sdonn c = * input_line_pointer;
40647406Sdonn * input_line_pointer = '\0';
40747406Sdonn md_assemble (s); /* Assemble 1 instruction. */
40847406Sdonn * input_line_pointer ++ = c;
40947406Sdonn /* We resume loop AFTER the end-of-line from this instruction */
41047406Sdonn } /* if (*s=='.') */
41147406Sdonn } /* if c==':' */
41247406Sdonn continue;
41347406Sdonn } /* if (is_name_beginner(c) */
41447406Sdonn
41547406Sdonn
41647406Sdonn if ( is_end_of_line [c] )
41747406Sdonn { /* empty statement */
41847406Sdonn continue;
41947406Sdonn }
42047406Sdonn
42147406Sdonn if ( isdigit(c) )
42247406Sdonn { /* local label ("4:") */
42347406Sdonn temp = c - '0';
42447406Sdonn #ifdef SUN_ASM_SYNTAX
42547406Sdonn if( *input_line_pointer=='$')
42647406Sdonn input_line_pointer++;
42747406Sdonn #endif
42847406Sdonn if ( * input_line_pointer ++ == ':' )
42947406Sdonn {
43047406Sdonn local_colon (temp);
43147406Sdonn }
43247406Sdonn else
43347406Sdonn {
43447406Sdonn as_bad( "Spurious digit %d.", temp);
43547406Sdonn input_line_pointer -- ;
43647406Sdonn ignore_rest_of_line();
43747406Sdonn }
43847406Sdonn continue;
43947406Sdonn }
44047406Sdonn if(c && index(line_comment_chars,c)) { /* Its a comment. Better say APP or NO_APP */
44147406Sdonn char *ends;
44247406Sdonn char *strstr();
44347406Sdonn char *new_buf;
44447406Sdonn char *new_tmp;
44547406Sdonn int new_length;
44647406Sdonn char *tmp_buf = 0;
44747406Sdonn extern char *scrub_string,*scrub_last_string;
44847406Sdonn int scrub_from_string();
44947406Sdonn void scrub_to_string();
45047406Sdonn
45147406Sdonn bump_line_counters();
45247406Sdonn s=input_line_pointer;
45347406Sdonn if(strncmp(s,"APP\n",4))
45447406Sdonn continue; /* We ignore it */
45547406Sdonn s+=4;
45647406Sdonn
45747406Sdonn ends=strstr(s,"#NO_APP\n");
45847406Sdonn
45947406Sdonn if(!ends) {
46047406Sdonn int tmp_len;
46147406Sdonn int num;
46247406Sdonn
46347406Sdonn /* The end of the #APP wasn't in this buffer. We
46447406Sdonn keep reading in buffers until we find the #NO_APP
46547406Sdonn that goes with this #APP There is one. The specs
46647406Sdonn guarentee it. . .*/
46747406Sdonn tmp_len=buffer_limit-s;
46847406Sdonn tmp_buf=xmalloc(tmp_len);
46947406Sdonn bcopy(s,tmp_buf,tmp_len);
47047406Sdonn do {
47147406Sdonn new_tmp = input_scrub_next_buffer(&buffer);
47247406Sdonn if(!new_tmp)
47347406Sdonn break;
47447406Sdonn else
47547406Sdonn buffer_limit = new_tmp;
47647406Sdonn input_line_pointer = buffer;
47747406Sdonn ends = strstr(buffer,"#NO_APP\n");
47847406Sdonn if(ends)
47947406Sdonn num=ends-buffer;
48047406Sdonn else
48147406Sdonn num=buffer_limit-buffer;
48247406Sdonn
48347406Sdonn tmp_buf=xrealloc(tmp_buf,tmp_len+num);
48447406Sdonn bcopy(buffer,tmp_buf+tmp_len,num);
48547406Sdonn tmp_len+=num;
48647406Sdonn } while(!ends);
48747406Sdonn
48847406Sdonn input_line_pointer= ends ? ends+8 : NULL;
48947406Sdonn
49047406Sdonn s=tmp_buf;
49147406Sdonn ends=s+tmp_len;
49247406Sdonn
49347406Sdonn } else {
49447406Sdonn input_line_pointer=ends+8;
49547406Sdonn }
49647406Sdonn new_buf=xmalloc(100);
49747406Sdonn new_length=100;
49847406Sdonn new_tmp=new_buf;
49947406Sdonn
50047406Sdonn scrub_string=s;
50147406Sdonn scrub_last_string = ends;
50247406Sdonn for(;;) {
50347406Sdonn int ch;
50447406Sdonn
50547406Sdonn ch=do_scrub_next_char(scrub_from_string,scrub_to_string);
50647406Sdonn if(ch==EOF) break;
50747406Sdonn *new_tmp++=ch;
50847406Sdonn if(new_tmp==new_buf+new_length) {
50947406Sdonn new_buf=xrealloc(new_buf,new_length+100);
51047406Sdonn new_tmp=new_buf+new_length;
51147406Sdonn new_length+=100;
51247406Sdonn }
51347406Sdonn }
51447406Sdonn
51547406Sdonn if(tmp_buf)
51647406Sdonn free(tmp_buf);
51747406Sdonn old_buffer=buffer;
51847406Sdonn old_input=input_line_pointer;
51947406Sdonn old_limit=buffer_limit;
52047406Sdonn buffer=new_buf;
52147406Sdonn input_line_pointer=new_buf;
52247406Sdonn buffer_limit=new_tmp;
52347406Sdonn continue;
52447406Sdonn }
52547406Sdonn
52647406Sdonn as_bad("Junk character %d.",c);
52747406Sdonn ignore_rest_of_line();
52847406Sdonn } /* while (input_line_pointer<buffer_limit )*/
52947406Sdonn if(old_buffer) {
53047406Sdonn bump_line_counters();
53147406Sdonn if(old_input == 0)
53247406Sdonn return;
53347406Sdonn buffer=old_buffer;
53447406Sdonn input_line_pointer=old_input;
53547406Sdonn buffer_limit=old_limit;
53647406Sdonn old_buffer = 0;
53747406Sdonn goto contin;
53847406Sdonn }
53947406Sdonn } /* while (more bufrers to scan) */
54047406Sdonn } /* read_a_source_file() */
54147406Sdonn
54247406Sdonn void
s_abort()54347406Sdonn s_abort()
54447406Sdonn {
54547406Sdonn as_fatal(".abort detected. Abandoning ship.");
54647406Sdonn }
54747406Sdonn
54847406Sdonn #ifdef OTHER_ALIGN
54947406Sdonn static void
s_align()55047406Sdonn s_align()
55147406Sdonn {
55247406Sdonn register unsigned int temp;
55347406Sdonn register long int temp_fill;
55447406Sdonn unsigned int i;
55547406Sdonn
55647406Sdonn temp = get_absolute_expression ();
55747406Sdonn #define MAX_ALIGNMENT (1 << 15)
55847406Sdonn if ( temp > MAX_ALIGNMENT ) {
55947406Sdonn as_bad("Alignment too large: %d. assumed.", temp = MAX_ALIGNMENT);
56047406Sdonn }
56147406Sdonn
56247406Sdonn /*
56347406Sdonn * For the sparc, `.align (1<<n)' actually means `.align n'
56447406Sdonn * so we have to convert it.
56547406Sdonn */
56647406Sdonn if (temp != 0) {
56747406Sdonn for (i = 0; (temp & 1) == 0; temp >>= 1, ++i)
56847406Sdonn ;
56947406Sdonn }
57047406Sdonn if (temp != 1)
57147406Sdonn as_bad("Alignment not a power of 2");
57247406Sdonn
57347406Sdonn temp = i;
57447406Sdonn if (*input_line_pointer == ',') {
57547406Sdonn input_line_pointer ++;
57647406Sdonn temp_fill = get_absolute_expression ();
57747406Sdonn } else {
57847406Sdonn temp_fill = 0;
57947406Sdonn }
58047406Sdonn /* Only make a frag if we HAVE to. . . */
58147406Sdonn if (temp && ! need_pass_2)
58247406Sdonn frag_align (temp, (int)temp_fill);
58347406Sdonn
58447406Sdonn demand_empty_rest_of_line();
58547406Sdonn }
58647406Sdonn #else
58747406Sdonn
58847406Sdonn void
s_align()58947406Sdonn s_align()
59047406Sdonn {
59147406Sdonn register int temp;
59247406Sdonn register long int temp_fill;
59347406Sdonn
59447406Sdonn temp = get_absolute_expression ();
59547406Sdonn #define MAX_ALIGNMENT (15)
59647406Sdonn if ( temp > MAX_ALIGNMENT )
59747406Sdonn as_bad("Alignment too large: %d. assumed.", temp = MAX_ALIGNMENT);
59847406Sdonn else if ( temp < 0 ) {
59947406Sdonn as_bad("Alignment negative. 0 assumed.");
60047406Sdonn temp = 0;
60147406Sdonn }
60247406Sdonn if ( *input_line_pointer == ',' ) {
60347406Sdonn input_line_pointer ++;
60447406Sdonn temp_fill = get_absolute_expression ();
60547406Sdonn } else
60647406Sdonn temp_fill = 0;
60747406Sdonn /* Only make a frag if we HAVE to. . . */
60847406Sdonn if ( temp && ! need_pass_2 )
60947406Sdonn frag_align (temp, (int)temp_fill);
61047406Sdonn demand_empty_rest_of_line();
61147406Sdonn }
61247406Sdonn #endif
61347406Sdonn
61447406Sdonn void
s_comm()61547406Sdonn s_comm()
61647406Sdonn {
61747406Sdonn register char *name;
61847406Sdonn register char c;
61947406Sdonn register char *p;
62047406Sdonn register int temp;
62147406Sdonn register symbolS * symbolP;
62247406Sdonn
62347406Sdonn name = input_line_pointer;
62447406Sdonn c = get_symbol_end();
62547406Sdonn /* just after name is now '\0' */
62647406Sdonn p = input_line_pointer;
62747406Sdonn *p = c;
62847406Sdonn SKIP_WHITESPACE();
62947406Sdonn if ( * input_line_pointer != ',' ) {
63047406Sdonn as_bad("Expected comma after symbol-name");
63147406Sdonn ignore_rest_of_line();
63247406Sdonn return;
63347406Sdonn }
63447406Sdonn input_line_pointer ++; /* skip ',' */
63547406Sdonn if ( (temp = get_absolute_expression ()) < 0 ) {
63647406Sdonn as_warn(".COMMon length (%d.) <0! Ignored.", temp);
63747406Sdonn ignore_rest_of_line();
63847406Sdonn return;
63947406Sdonn }
64047406Sdonn *p = 0;
64147406Sdonn symbolP = symbol_find_or_make (name);
64247406Sdonn *p = c;
64347406Sdonn if ( (symbolP -> sy_type & N_TYPE) != N_UNDF ||
64447406Sdonn symbolP -> sy_other != 0 || symbolP -> sy_desc != 0) {
64547406Sdonn as_warn( "Ignoring attempt to re-define symbol");
64647406Sdonn ignore_rest_of_line();
64747406Sdonn return;
64847406Sdonn }
64947406Sdonn if (symbolP -> sy_value) {
65047406Sdonn if (symbolP -> sy_value != temp)
65147406Sdonn as_warn( "Length of .comm \"%s\" is already %d. Not changed to %d.",
65247406Sdonn symbolP -> sy_name, symbolP -> sy_value, temp);
65347406Sdonn } else {
65447406Sdonn symbolP -> sy_value = temp;
65547406Sdonn symbolP -> sy_type |= N_EXT;
65647406Sdonn }
65747406Sdonn #ifdef VMS
65847406Sdonn if(!temp)
65947406Sdonn symbolP->sy_other = const_flag;
66047406Sdonn #endif
66147406Sdonn know( symbolP -> sy_frag == &zero_address_frag );
66247406Sdonn demand_empty_rest_of_line();
66347406Sdonn }
66447406Sdonn
66547406Sdonn #ifdef VMS
66647406Sdonn void
s_const()66747406Sdonn s_const()
66847406Sdonn {
66947406Sdonn register int temp;
67047406Sdonn
67147406Sdonn temp = get_absolute_expression ();
67247406Sdonn subseg_new (SEG_DATA, (subsegT)temp);
67347406Sdonn const_flag = 1;
67447406Sdonn demand_empty_rest_of_line();
67547406Sdonn }
67647406Sdonn #endif
67747406Sdonn
67847406Sdonn void
s_data()67947406Sdonn s_data()
68047406Sdonn {
68147406Sdonn register int temp;
68247406Sdonn
68347406Sdonn temp = get_absolute_expression ();
68447406Sdonn subseg_new (SEG_DATA, (subsegT)temp);
68547406Sdonn #ifdef VMS
68647406Sdonn const_flag = 0;
68747406Sdonn #endif
68847406Sdonn demand_empty_rest_of_line();
68947406Sdonn }
69047406Sdonn
69147406Sdonn void
s_desc()69247406Sdonn s_desc()
69347406Sdonn {
69447406Sdonn register char *name;
69547406Sdonn register char c;
69647406Sdonn register char *p;
69747406Sdonn register symbolS * symbolP;
69847406Sdonn register int temp;
69947406Sdonn
70047406Sdonn /*
70147406Sdonn * Frob invented at RMS' request. Set the n_desc of a symbol.
70247406Sdonn */
70347406Sdonn name = input_line_pointer;
70447406Sdonn c = get_symbol_end();
70547406Sdonn p = input_line_pointer;
70647406Sdonn symbolP = symbol_table_lookup (name);
70747406Sdonn * p = c;
70847406Sdonn SKIP_WHITESPACE();
70947406Sdonn if ( * input_line_pointer != ',' ) {
71047406Sdonn *p = 0;
71147406Sdonn as_bad("Expected comma after name \"%s\"", name);
71247406Sdonn *p = c;
71347406Sdonn ignore_rest_of_line();
71447406Sdonn } else {
71547406Sdonn input_line_pointer ++;
71647406Sdonn temp = get_absolute_expression ();
71747406Sdonn *p = 0;
71847406Sdonn symbolP = symbol_find_or_make (name);
71947406Sdonn *p = c;
72047406Sdonn symbolP -> sy_desc = temp;
72147406Sdonn }
72247406Sdonn demand_empty_rest_of_line();
72347406Sdonn }
72447406Sdonn
72547406Sdonn void
s_file()72647406Sdonn s_file()
72747406Sdonn {
72847406Sdonn register char *s;
72947406Sdonn int length;
73047406Sdonn
73147406Sdonn /* Some assemblers tolerate immediately following '"' */
73247406Sdonn if ( s = demand_copy_string( & length ) ) {
73347406Sdonn new_logical_line (s, -1);
73447406Sdonn demand_empty_rest_of_line();
73547406Sdonn }
73647406Sdonn }
73747406Sdonn
73847406Sdonn void
s_fill()73947406Sdonn s_fill()
74047406Sdonn {
74147406Sdonn long int temp_repeat;
74247406Sdonn long int temp_size;
74347406Sdonn register long int temp_fill;
74447406Sdonn char *p;
74547406Sdonn
74647406Sdonn if ( get_absolute_expression_and_terminator(& temp_repeat) != ',' ) {
74747406Sdonn input_line_pointer --; /* Backup over what was not a ','. */
74847406Sdonn as_warn("Expect comma after rep-size in .fill");
74947406Sdonn ignore_rest_of_line();
75047406Sdonn return;
75147406Sdonn }
75247406Sdonn if ( get_absolute_expression_and_terminator( & temp_size) != ',' ) {
75347406Sdonn input_line_pointer --; /* Backup over what was not a ','. */
75447406Sdonn as_warn("Expected comma after size in .fill");
75547406Sdonn ignore_rest_of_line();
75647406Sdonn return;
75747406Sdonn }
75847406Sdonn /*
75947406Sdonn * This is to be compatible with BSD 4.2 AS, not for any rational reason.
76047406Sdonn */
76147406Sdonn #define BSD_FILL_SIZE_CROCK_8 (8)
76247406Sdonn if ( temp_size > BSD_FILL_SIZE_CROCK_8 ) {
76347406Sdonn as_bad(".fill size clamped to %d.", BSD_FILL_SIZE_CROCK_8);
76447406Sdonn temp_size = BSD_FILL_SIZE_CROCK_8 ;
76547406Sdonn } if ( temp_size < 0 ) {
76647406Sdonn as_warn("Size negative: .fill ignored.");
76747406Sdonn temp_size = 0;
76847406Sdonn } else if ( temp_repeat <= 0 ) {
76947406Sdonn as_warn("Repeat < 0, .fill ignored");
77047406Sdonn temp_size = 0;
77147406Sdonn }
77247406Sdonn temp_fill = get_absolute_expression ();
77347406Sdonn if ( temp_size && !need_pass_2 ) {
77447406Sdonn p = frag_var (rs_fill, (int)temp_size, (int)temp_size, (relax_substateT)0, (symbolS *)0, temp_repeat, (char *)0);
77547406Sdonn bzero (p, (int)temp_size);
77647406Sdonn /*
77747406Sdonn * The magic number BSD_FILL_SIZE_CROCK_4 is from BSD 4.2 VAX flavoured AS.
77847406Sdonn * The following bizzare behaviour is to be compatible with above.
77947406Sdonn * I guess they tried to take up to 8 bytes from a 4-byte expression
78047406Sdonn * and they forgot to sign extend. Un*x Sux.
78147406Sdonn */
78247406Sdonn #define BSD_FILL_SIZE_CROCK_4 (4)
78347406Sdonn md_number_to_chars (p, temp_fill, temp_size > BSD_FILL_SIZE_CROCK_4 ? BSD_FILL_SIZE_CROCK_4 : (int)temp_size);
78447406Sdonn /*
78547406Sdonn * Note: .fill (),0 emits no frag (since we are asked to .fill 0 bytes)
78647406Sdonn * but emits no error message because it seems a legal thing to do.
78747406Sdonn * It is a degenerate case of .fill but could be emitted by a compiler.
78847406Sdonn */
78947406Sdonn }
79047406Sdonn demand_empty_rest_of_line();
79147406Sdonn }
79247406Sdonn
79347406Sdonn #ifdef DONTDEF
79447406Sdonn void
s_gdbbeg()79547406Sdonn s_gdbbeg()
79647406Sdonn {
79747406Sdonn register int temp;
79847406Sdonn
79947406Sdonn temp = get_absolute_expression ();
80047406Sdonn if (temp < 0)
80147406Sdonn as_warn( "Block number <0. Ignored." );
80247406Sdonn else if (flagseen ['G'])
80347406Sdonn gdb_block_beg ( (long int) temp, frag_now, (long int)(obstack_next_free(& frags) - frag_now -> fr_literal));
80447406Sdonn demand_empty_rest_of_line ();
80547406Sdonn }
80647406Sdonn
80747406Sdonn void
s_gdbblock()80847406Sdonn s_gdbblock()
80947406Sdonn {
81047406Sdonn register int position;
81147406Sdonn int temp;
81247406Sdonn
81347406Sdonn if (get_absolute_expression_and_terminator (&temp) != ',') {
81447406Sdonn as_warn( "expected comma before position in .gdbblock");
81547406Sdonn --input_line_pointer;
81647406Sdonn ignore_rest_of_line ();
81747406Sdonn return;
81847406Sdonn }
81947406Sdonn position = get_absolute_expression ();
82047406Sdonn if (flagseen ['G'])
82147406Sdonn gdb_block_position ((long int) temp, (long int) position);
82247406Sdonn demand_empty_rest_of_line ();
82347406Sdonn }
82447406Sdonn
82547406Sdonn void
s_gdbend()82647406Sdonn s_gdbend()
82747406Sdonn {
82847406Sdonn register int temp;
82947406Sdonn
83047406Sdonn temp = get_absolute_expression ();
83147406Sdonn if (temp < 0)
83247406Sdonn as_warn( "Block number <0. Ignored." );
83347406Sdonn else if (flagseen ['G'])
83447406Sdonn gdb_block_end ( (long int) temp, frag_now, (long int)(obstack_next_free(& frags) - frag_now -> fr_literal));
83547406Sdonn demand_empty_rest_of_line ();
83647406Sdonn }
83747406Sdonn
83847406Sdonn void
s_gdbsym()83947406Sdonn s_gdbsym()
84047406Sdonn {
84147406Sdonn register char *name,
84247406Sdonn *p;
84347406Sdonn register char c;
84447406Sdonn register symbolS * symbolP;
84547406Sdonn register int temp;
84647406Sdonn
84747406Sdonn name = input_line_pointer;
84847406Sdonn c = get_symbol_end();
84947406Sdonn p = input_line_pointer;
85047406Sdonn symbolP = symbol_find_or_make (name);
85147406Sdonn *p = c;
85247406Sdonn SKIP_WHITESPACE();
85347406Sdonn if ( * input_line_pointer != ',' ) {
85447406Sdonn as_warn("Expected comma after name");
85547406Sdonn ignore_rest_of_line();
85647406Sdonn return;
85747406Sdonn }
85847406Sdonn input_line_pointer ++;
85947406Sdonn if ( (temp = get_absolute_expression ()) < 0 ) {
86047406Sdonn as_warn("Bad GDB symbol file offset (%d.) <0! Ignored.", temp);
86147406Sdonn ignore_rest_of_line();
86247406Sdonn return;
86347406Sdonn }
86447406Sdonn if (flagseen ['G'])
86547406Sdonn gdb_symbols_fixup (symbolP, (long int)temp);
86647406Sdonn demand_empty_rest_of_line ();
86747406Sdonn }
86847406Sdonn
86947406Sdonn void
s_gdbline()87047406Sdonn s_gdbline()
87147406Sdonn {
87247406Sdonn int file_number,
87347406Sdonn lineno;
87447406Sdonn
87547406Sdonn if(get_absolute_expression_and_terminator(&file_number) != ',') {
87647406Sdonn as_warn("expected comman after filenum in .gdbline");
87747406Sdonn ignore_rest_of_line();
87847406Sdonn return;
87947406Sdonn }
88047406Sdonn lineno=get_absolute_expression();
88147406Sdonn if(flagseen['G'])
88247406Sdonn gdb_line(file_number,lineno);
88347406Sdonn demand_empty_rest_of_line();
88447406Sdonn }
88547406Sdonn
88647406Sdonn
88747406Sdonn void
s_gdblinetab()88847406Sdonn s_gdblinetab()
88947406Sdonn {
89047406Sdonn int file_number,
89147406Sdonn offset;
89247406Sdonn
89347406Sdonn if(get_absolute_expression_and_terminator(&file_number) != ',') {
89447406Sdonn as_warn("expected comman after filenum in .gdblinetab");
89547406Sdonn ignore_rest_of_line();
89647406Sdonn return;
89747406Sdonn }
89847406Sdonn offset=get_absolute_expression();
89947406Sdonn if(flagseen['G'])
90047406Sdonn gdb_line_tab(file_number,offset);
90147406Sdonn demand_empty_rest_of_line();
90247406Sdonn }
90347406Sdonn #endif
90447406Sdonn
90547406Sdonn void
s_globl()90647406Sdonn s_globl()
90747406Sdonn {
90847406Sdonn register char *name;
90947406Sdonn register int c;
91047406Sdonn register symbolS * symbolP;
91147406Sdonn
91247406Sdonn do {
91347406Sdonn name = input_line_pointer;
91447406Sdonn c = get_symbol_end();
91547406Sdonn symbolP = symbol_find_or_make (name);
91647406Sdonn * input_line_pointer = c;
91747406Sdonn SKIP_WHITESPACE();
91847406Sdonn symbolP -> sy_type |= N_EXT;
91947406Sdonn if(c==',') {
92047406Sdonn input_line_pointer++;
92147406Sdonn SKIP_WHITESPACE();
92247406Sdonn if(*input_line_pointer=='\n')
92347406Sdonn c='\n';
92447406Sdonn }
92547406Sdonn } while(c==',');
92647406Sdonn demand_empty_rest_of_line();
92747406Sdonn }
92847406Sdonn
92947406Sdonn void
s_lcomm()93047406Sdonn s_lcomm()
93147406Sdonn {
93247406Sdonn register char *name;
93347406Sdonn register char c;
93447406Sdonn register char *p;
93547406Sdonn register int temp;
93647406Sdonn register symbolS * symbolP;
93747406Sdonn
93847406Sdonn name = input_line_pointer;
93947406Sdonn c = get_symbol_end();
94047406Sdonn p = input_line_pointer;
94147406Sdonn *p = c;
94247406Sdonn SKIP_WHITESPACE();
94347406Sdonn if ( * input_line_pointer != ',' ) {
94447406Sdonn as_warn("Expected comma after name");
94547406Sdonn ignore_rest_of_line();
94647406Sdonn return;
94747406Sdonn }
94847406Sdonn input_line_pointer ++;
94947406Sdonn if ( (temp = get_absolute_expression ()) < 0 ) {
95047406Sdonn as_warn("BSS length (%d.) <0! Ignored.", temp);
95147406Sdonn ignore_rest_of_line();
95247406Sdonn return;
95347406Sdonn }
95447406Sdonn *p = 0;
95547406Sdonn symbolP = symbol_find_or_make (name);
95647406Sdonn *p = c;
95747406Sdonn if ( symbolP -> sy_other == 0
95847406Sdonn && symbolP -> sy_desc == 0
95947406Sdonn && ( ( symbolP -> sy_type == N_BSS
96047406Sdonn && symbolP -> sy_value == local_bss_counter)
96147406Sdonn || ( (symbolP -> sy_type & N_TYPE) == N_UNDF
96247406Sdonn && symbolP -> sy_value == 0))) {
96347406Sdonn symbolP -> sy_value = local_bss_counter;
96447406Sdonn symbolP -> sy_type = N_BSS;
96547406Sdonn symbolP -> sy_frag = & bss_address_frag;
96647406Sdonn local_bss_counter += temp;
96747406Sdonn } else
96847406Sdonn as_warn( "Ignoring attempt to re-define symbol from %d. to %d.",
96947406Sdonn symbolP -> sy_value, local_bss_counter );
97047406Sdonn demand_empty_rest_of_line();
97147406Sdonn }
97247406Sdonn
97347406Sdonn void
s_line()97447406Sdonn s_line()
97547406Sdonn {
97647406Sdonn /* Assume delimiter is part of expression. */
97747406Sdonn /* BSD4.2 as fails with delightful bug, so we */
97847406Sdonn /* are not being incompatible here. */
97947406Sdonn new_logical_line ((char *)NULL, (int)(get_absolute_expression ()));
98047406Sdonn demand_empty_rest_of_line();
98147406Sdonn }
98247406Sdonn
98347406Sdonn void
s_long()98447406Sdonn s_long()
98547406Sdonn {
98647406Sdonn cons(4);
98747406Sdonn }
98847406Sdonn
98947406Sdonn void
s_int()99047406Sdonn s_int()
99147406Sdonn {
99247406Sdonn cons(4);
99347406Sdonn }
99447406Sdonn
99547406Sdonn void
s_lsym()99647406Sdonn s_lsym()
99747406Sdonn {
99847406Sdonn register char *name;
99947406Sdonn register char c;
100047406Sdonn register char *p;
100147406Sdonn register segT segment;
100247406Sdonn expressionS exp;
100347406Sdonn register symbolS *symbolP;
100447406Sdonn
100547406Sdonn /* we permit ANY expression: BSD4.2 demands constants */
100647406Sdonn name = input_line_pointer;
100747406Sdonn c = get_symbol_end();
100847406Sdonn p = input_line_pointer;
100947406Sdonn *p = c;
101047406Sdonn SKIP_WHITESPACE();
101147406Sdonn if ( * input_line_pointer != ',' ) {
101247406Sdonn *p = 0;
101347406Sdonn as_warn("Expected comma after name \"%s\"", name);
101447406Sdonn *p = c;
101547406Sdonn ignore_rest_of_line();
101647406Sdonn return;
101747406Sdonn }
101847406Sdonn input_line_pointer ++;
101947406Sdonn segment = expression (& exp);
102047406Sdonn if ( segment != SEG_ABSOLUTE && segment != SEG_DATA &&
102147406Sdonn segment != SEG_TEXT && segment != SEG_BSS) {
102247406Sdonn as_bad("Bad expression: %s", seg_name [(int)segment]);
102347406Sdonn ignore_rest_of_line();
102447406Sdonn return;
102547406Sdonn }
102647406Sdonn know( segment == SEG_ABSOLUTE || segment == SEG_DATA || segment == SEG_TEXT || segment == SEG_BSS );
102747406Sdonn *p = 0;
102847406Sdonn symbolP = symbol_new (name,(unsigned char)(seg_N_TYPE [(int) segment]),
102947406Sdonn 0, 0, (valueT)(exp . X_add_number), & zero_address_frag);
103047406Sdonn *p = c;
103147406Sdonn demand_empty_rest_of_line();
103247406Sdonn }
103347406Sdonn
103447406Sdonn void
s_org()103547406Sdonn s_org()
103647406Sdonn {
103747406Sdonn register segT segment;
103847406Sdonn expressionS exp;
103947406Sdonn register long int temp_fill;
104047406Sdonn register char *p;
104147406Sdonn /*
104247406Sdonn * Don't believe the documentation of BSD 4.2 AS.
104347406Sdonn * There is no such thing as a sub-segment-relative origin.
104447406Sdonn * Any absolute origin is given a warning, then assumed to be segment-relative.
104547406Sdonn * Any segmented origin expression ("foo+42") had better be in the right
104647406Sdonn * segment or the .org is ignored.
104747406Sdonn *
104847406Sdonn * BSD 4.2 AS warns if you try to .org backwards. We cannot because we
104947406Sdonn * never know sub-segment sizes when we are reading code.
105047406Sdonn * BSD will crash trying to emit -ve numbers of filler bytes in certain
105147406Sdonn * .orgs. We don't crash, but see as-write for that code.
105247406Sdonn */
105347406Sdonn /*
105447406Sdonn * Don't make frag if need_pass_2==TRUE.
105547406Sdonn */
105647406Sdonn segment = get_known_segmented_expression(& exp);
105747406Sdonn if ( *input_line_pointer == ',' ) {
105847406Sdonn input_line_pointer ++;
105947406Sdonn temp_fill = get_absolute_expression ();
106047406Sdonn } else
106147406Sdonn temp_fill = 0;
106247406Sdonn if ( ! need_pass_2 ) {
106347406Sdonn if (segment != now_seg && segment != SEG_ABSOLUTE)
106447406Sdonn as_warn("Illegal segment \"%s\". Segment \"%s\" assumed.",
106547406Sdonn seg_name [(int) segment], seg_name [(int) now_seg]);
106647406Sdonn p = frag_var (rs_org, 1, 1, (relax_substateT)0, exp . X_add_symbol,
106747406Sdonn exp . X_add_number, (char *)0);
106847406Sdonn * p = temp_fill;
106947406Sdonn } /* if (ok to make frag) */
107047406Sdonn demand_empty_rest_of_line();
107147406Sdonn }
107247406Sdonn
107347406Sdonn void
s_set()107447406Sdonn s_set()
107547406Sdonn {
107647406Sdonn register char *name;
107747406Sdonn register char delim;
107847406Sdonn register char *end_name;
107947406Sdonn register symbolS *symbolP;
108047406Sdonn
108147406Sdonn /*
108247406Sdonn * Especial apologies for the random logic:
108347406Sdonn * this just grew, and could be parsed much more simply!
108447406Sdonn * Dean in haste.
108547406Sdonn */
108647406Sdonn name = input_line_pointer;
108747406Sdonn delim = get_symbol_end();
108847406Sdonn end_name = input_line_pointer;
108947406Sdonn *end_name = delim;
109047406Sdonn SKIP_WHITESPACE();
109147406Sdonn if ( * input_line_pointer != ',' ) {
109247406Sdonn *end_name = 0;
109347406Sdonn as_warn("Expected comma after name \"%s\"", name);
109447406Sdonn *end_name = delim;
109547406Sdonn ignore_rest_of_line();
109647406Sdonn return;
109747406Sdonn }
109847406Sdonn input_line_pointer ++;
109947406Sdonn *end_name = 0;
110047406Sdonn if(name[0]=='.' && name[1]=='\0') {
110147406Sdonn /* Turn '. = mumble' into a .org mumble */
110247406Sdonn register segT segment;
110347406Sdonn expressionS exp;
110447406Sdonn register char *ptr;
110547406Sdonn
110647406Sdonn segment = get_known_segmented_expression(& exp);
110747406Sdonn if ( ! need_pass_2 ) {
110847406Sdonn if (segment != now_seg && segment != SEG_ABSOLUTE)
110947406Sdonn as_warn("Illegal segment \"%s\". Segment \"%s\" assumed.",
111047406Sdonn seg_name [(int) segment], seg_name [(int) now_seg]);
111147406Sdonn ptr = frag_var (rs_org, 1, 1, (relax_substateT)0, exp.X_add_symbol,
111247406Sdonn exp.X_add_number, (char *)0);
111347406Sdonn *ptr= 0;
111447406Sdonn } /* if (ok to make frag) */
111547406Sdonn *end_name = delim;
111647406Sdonn return;
111747406Sdonn }
111847406Sdonn symbolP = symbol_find_or_make (name);
111947406Sdonn *end_name = delim;
112047406Sdonn pseudo_set (symbolP);
112147406Sdonn demand_empty_rest_of_line ();
112247406Sdonn }
112347406Sdonn
112447406Sdonn void
s_space()112547406Sdonn s_space()
112647406Sdonn {
112747406Sdonn long int temp_repeat;
112847406Sdonn register long int temp_fill;
112947406Sdonn register char *p;
113047406Sdonn
113147406Sdonn /* Just like .fill, but temp_size = 1 */
113247406Sdonn if ( get_absolute_expression_and_terminator( & temp_repeat) == ',' ) {
113347406Sdonn temp_fill = get_absolute_expression ();
113447406Sdonn } else {
113547406Sdonn input_line_pointer --; /* Backup over what was not a ','. */
113647406Sdonn temp_fill = 0;
113747406Sdonn }
113847406Sdonn if ( temp_repeat <= 0 ) {
113947406Sdonn as_warn("Repeat < 0, .space ignored");
114047406Sdonn ignore_rest_of_line();
114147406Sdonn return;
114247406Sdonn }
114347406Sdonn if ( ! need_pass_2 ) {
114447406Sdonn p = frag_var (rs_fill, 1, 1, (relax_substateT)0, (symbolS *)0,
114547406Sdonn temp_repeat, (char *)0);
114647406Sdonn * p = temp_fill;
114747406Sdonn }
114847406Sdonn demand_empty_rest_of_line();
114947406Sdonn }
115047406Sdonn
115147406Sdonn void
s_text()115247406Sdonn s_text()
115347406Sdonn {
115447406Sdonn register int temp;
115547406Sdonn
115647406Sdonn temp = get_absolute_expression ();
115747406Sdonn subseg_new (SEG_TEXT, (subsegT)temp);
115847406Sdonn demand_empty_rest_of_line();
115947406Sdonn }
116047406Sdonn
116147406Sdonn
116247406Sdonn /*( JF was static, but can't be if machine dependent pseudo-ops are to use it */
116347406Sdonn
116447406Sdonn void
demand_empty_rest_of_line()116547406Sdonn demand_empty_rest_of_line()
116647406Sdonn {
116747406Sdonn SKIP_WHITESPACE();
116847406Sdonn if ( is_end_of_line [* input_line_pointer] )
116947406Sdonn {
117047406Sdonn input_line_pointer ++;
117147406Sdonn }
117247406Sdonn else
117347406Sdonn {
117447406Sdonn ignore_rest_of_line();
117547406Sdonn }
117647406Sdonn /* Return having already swallowed end-of-line. */
117747406Sdonn } /* Return pointing just after end-of-line. */
117847406Sdonn
117947406Sdonn
118047406Sdonn void
ignore_rest_of_line()118147406Sdonn ignore_rest_of_line() /* For suspect lines: gives warning. */
118247406Sdonn {
118347406Sdonn if ( ! is_end_of_line [* input_line_pointer])
118447406Sdonn {
118547406Sdonn as_warn("Rest of line ignored. 1st junk character valued %d (%c)."
118647406Sdonn , * input_line_pointer, *input_line_pointer);
118747406Sdonn while ( input_line_pointer < buffer_limit
118847406Sdonn && ! is_end_of_line [* input_line_pointer] )
118947406Sdonn {
119047406Sdonn input_line_pointer ++;
119147406Sdonn }
119247406Sdonn }
119347406Sdonn input_line_pointer ++; /* Return pointing just after end-of-line. */
119447406Sdonn know( is_end_of_line [input_line_pointer [-1]] );
119547406Sdonn }
119647406Sdonn
119747406Sdonn /*
119847406Sdonn * stab()
119947406Sdonn *
120047406Sdonn * Handle .stabX directives, which used to be open-coded.
120147406Sdonn * So much creeping featurism overloaded the semantics that we decided
120247406Sdonn * to put all .stabX thinking in one place. Here.
120347406Sdonn *
120447406Sdonn * We try to make any .stabX directive legal. Other people's AS will often
120547406Sdonn * do assembly-time consistency checks: eg assigning meaning to n_type bits
120647406Sdonn * and "protecting" you from setting them to certain values. (They also zero
120747406Sdonn * certain bits before emitting symbols. Tut tut.)
120847406Sdonn *
120947406Sdonn * If an expression is not absolute we either gripe or use the relocation
121047406Sdonn * information. Other people's assemblers silently forget information they
121147406Sdonn * don't need and invent information they need that you didn't supply.
121247406Sdonn *
121347406Sdonn * .stabX directives always make a symbol table entry. It may be junk if
121447406Sdonn * the rest of your .stabX directive is malformed.
121547406Sdonn */
121647406Sdonn static void
stab(what)121747406Sdonn stab (what)
121847406Sdonn int what;
121947406Sdonn {
122047406Sdonn register symbolS * symbolP;
122147406Sdonn register char * string;
122247406Sdonn int saved_type;
122347406Sdonn int length;
122447406Sdonn int goof; /* TRUE if we have aborted. */
122547406Sdonn long int longint;
122647406Sdonn
122747406Sdonn /*
122847406Sdonn * Enter with input_line_pointer pointing past .stabX and any following
122947406Sdonn * whitespace.
123047406Sdonn */
123147406Sdonn goof = FALSE; /* JF who forgot this?? */
123247406Sdonn if (what == 's') {
123347406Sdonn string = demand_copy_C_string (& length);
123447406Sdonn SKIP_WHITESPACE();
123547406Sdonn if (* input_line_pointer == ',')
123647406Sdonn input_line_pointer ++;
123747406Sdonn else {
123847406Sdonn as_warn( "I need a comma after symbol's name" );
123947406Sdonn goof = TRUE;
124047406Sdonn }
124147406Sdonn } else
124247406Sdonn string = "";
124347406Sdonn
124447406Sdonn /*
124547406Sdonn * Input_line_pointer->after ','. String -> symbol name.
124647406Sdonn */
124747406Sdonn if (! goof) {
124847406Sdonn symbolP = symbol_new (string, 0,0,0,0,(struct frag *)0);
124947406Sdonn switch (what) {
125047406Sdonn case 'd':
125147406Sdonn symbolP->sy_name = NULL; /* .stabd feature. */
125247406Sdonn symbolP->sy_value = obstack_next_free(& frags) - frag_now->fr_literal;
125347406Sdonn symbolP->sy_frag = frag_now;
125447406Sdonn break;
125547406Sdonn
125647406Sdonn case 'n':
125747406Sdonn symbolP->sy_frag = &zero_address_frag;
125847406Sdonn break;
125947406Sdonn
126047406Sdonn case 's':
126147406Sdonn symbolP->sy_frag = & zero_address_frag;
126247406Sdonn break;
126347406Sdonn
126447406Sdonn default:
126547406Sdonn BAD_CASE( what );
126647406Sdonn break;
126747406Sdonn }
126847406Sdonn if (get_absolute_expression_and_terminator (& longint) == ',')
126947406Sdonn symbolP->sy_type = saved_type = longint;
127047406Sdonn else {
127147406Sdonn as_warn( "I want a comma after the n_type expression" );
127247406Sdonn goof = TRUE;
127347406Sdonn input_line_pointer --; /* Backup over a non-',' char. */
127447406Sdonn }
127547406Sdonn }
127647406Sdonn if (! goof) {
127747406Sdonn if (get_absolute_expression_and_terminator (& longint) == ',')
127847406Sdonn symbolP->sy_other = longint;
127947406Sdonn else {
128047406Sdonn as_warn( "I want a comma after the n_other expression" );
128147406Sdonn goof = TRUE;
128247406Sdonn input_line_pointer --; /* Backup over a non-',' char. */
128347406Sdonn }
128447406Sdonn }
128547406Sdonn if (! goof) {
128647406Sdonn symbolP->sy_desc = get_absolute_expression ();
128747406Sdonn if (what == 's' || what == 'n') {
128847406Sdonn if (* input_line_pointer != ',') {
128947406Sdonn as_warn( "I want a comma after the n_desc expression" );
129047406Sdonn goof = TRUE;
129147406Sdonn } else {
129247406Sdonn input_line_pointer ++;
129347406Sdonn }
129447406Sdonn }
129547406Sdonn }
129647406Sdonn if ((! goof) && (what=='s' || what=='n')) {
129747406Sdonn pseudo_set (symbolP);
129847406Sdonn symbolP->sy_type = saved_type;
129947406Sdonn }
130047406Sdonn if (goof)
130147406Sdonn ignore_rest_of_line ();
130247406Sdonn else
130347406Sdonn demand_empty_rest_of_line ();
130447406Sdonn }
130547406Sdonn
130647406Sdonn /*
130747406Sdonn * pseudo_set()
130847406Sdonn *
130947406Sdonn * In: Pointer to a symbol.
131047406Sdonn * Input_line_pointer -> expression.
131147406Sdonn *
131247406Sdonn * Out: Input_line_pointer -> just after any whitespace after expression.
131347406Sdonn * Tried to set symbol to value of expression.
131447406Sdonn * Will change sy_type, sy_value, sy_frag;
131547406Sdonn * May set need_pass_2 == TRUE.
131647406Sdonn */
131747406Sdonn static void
pseudo_set(symbolP)131847406Sdonn pseudo_set (symbolP)
131947406Sdonn symbolS * symbolP;
132047406Sdonn {
132147406Sdonn expressionS exp;
132247406Sdonn register segT segment;
132347406Sdonn int ext;
132447406Sdonn
132547406Sdonn know( symbolP ); /* NULL pointer is logic error. */
132647406Sdonn ext=(symbolP->sy_type&N_EXT);
132747406Sdonn if ((segment = expression( & exp )) == SEG_NONE)
132847406Sdonn {
132947406Sdonn as_warn( "Missing expression: absolute 0 assumed" );
133047406Sdonn exp . X_seg = SEG_ABSOLUTE;
133147406Sdonn exp . X_add_number = 0;
133247406Sdonn }
133347406Sdonn switch (segment)
133447406Sdonn {
133547406Sdonn case SEG_BIG:
133647406Sdonn as_warn( "%s number illegal. Absolute 0 assumed.",
133747406Sdonn exp . X_add_number > 0 ? "Bignum" : "Floating-Point" );
133847406Sdonn symbolP -> sy_type = N_ABS | ext;
133947406Sdonn symbolP -> sy_value = 0;
134047406Sdonn symbolP -> sy_frag = & zero_address_frag;
134147406Sdonn break;
134247406Sdonn
134347406Sdonn case SEG_NONE:
134447406Sdonn as_warn("No expression: Using absolute 0");
134547406Sdonn symbolP -> sy_type = N_ABS | ext;
134647406Sdonn symbolP -> sy_value = 0;
134747406Sdonn symbolP -> sy_frag = & zero_address_frag;
134847406Sdonn break;
134947406Sdonn
135047406Sdonn case SEG_DIFFERENCE:
135147406Sdonn if (exp.X_add_symbol && exp.X_subtract_symbol
135247406Sdonn && (exp.X_add_symbol->sy_type & N_TYPE)
135347406Sdonn == (exp.X_subtract_symbol->sy_type & N_TYPE)) {
135447406Sdonn if(exp.X_add_symbol->sy_frag != exp.X_subtract_symbol->sy_frag) {
135547406Sdonn as_bad("Unknown expression: symbols %s and %s are in different frags.",exp.X_add_symbol->sy_name, exp.X_subtract_symbol->sy_name);
135647406Sdonn need_pass_2++;
135747406Sdonn }
135847406Sdonn exp.X_add_number+=exp.X_add_symbol->sy_value - exp.X_subtract_symbol->sy_value;
135947406Sdonn } else
136047406Sdonn as_warn( "Complex expression. Absolute segment assumed." );
136147406Sdonn case SEG_ABSOLUTE:
136247406Sdonn symbolP -> sy_type = N_ABS | ext;
136347406Sdonn symbolP -> sy_value = exp . X_add_number;
136447406Sdonn symbolP -> sy_frag = & zero_address_frag;
136547406Sdonn break;
136647406Sdonn
136747406Sdonn case SEG_DATA:
136847406Sdonn case SEG_TEXT:
136947406Sdonn case SEG_BSS:
137047406Sdonn symbolP -> sy_type = seg_N_TYPE [(int) segment] | ext;
137147406Sdonn symbolP -> sy_value= exp . X_add_number + exp . X_add_symbol -> sy_value;
137247406Sdonn symbolP -> sy_frag = exp . X_add_symbol -> sy_frag;
137347406Sdonn break;
137447406Sdonn
137547406Sdonn case SEG_PASS1: /* Not an error. Just try another pass. */
137647406Sdonn symbolP->sy_forward=exp.X_add_symbol;
137747406Sdonn as_warn("Unknown expression");
137847406Sdonn know( need_pass_2 == TRUE );
137947406Sdonn break;
138047406Sdonn
138147406Sdonn case SEG_UNKNOWN:
138247406Sdonn symbolP->sy_forward=exp.X_add_symbol;
138347406Sdonn /* as_warn("unknown symbol"); */
138447406Sdonn /* need_pass_2 = TRUE; */
138547406Sdonn break;
138647406Sdonn
138747406Sdonn default:
138847406Sdonn BAD_CASE( segment );
138947406Sdonn break;
139047406Sdonn }
139147406Sdonn }
139247406Sdonn
139347406Sdonn /*
139447445Sdonn * stabs(file), stabf(func) and stabd(line) -- for the purpose of
139547445Sdonn * source file debugging of assembly files, generate file,
139647445Sdonn * function and line number stabs, respectively.
139747447Sdonn * These functions have corresponding functions named
139847447Sdonn * filestab(), funcstab() and linestab() in input-scrub.c,
139947447Sdonn * where logical files and logical line numbers are handled.
140047445Sdonn */
140147445Sdonn
140247445Sdonn #include <stab.h>
140347445Sdonn
stabs(file)140447445Sdonn stabs(file)
140547445Sdonn char *file;
140647445Sdonn {
140747445Sdonn /* .stabs "file",100,0,0,. */
140847445Sdonn (void) symbol_new(file,
140947445Sdonn N_SO,
141047445Sdonn 0,
141147445Sdonn 0,
141247445Sdonn obstack_next_free(& frags) - frag_now->fr_literal,
141347445Sdonn frag_now);
141447445Sdonn }
141547445Sdonn
stabf(func)141647445Sdonn stabf(func)
141747445Sdonn char *func;
141847445Sdonn {
141947445Sdonn symbolS *symbolP;
142047445Sdonn static int void_undefined = 1;
142147445Sdonn
142247445Sdonn /* crudely filter uninteresting labels: require an initial '_' */
142347447Sdonn if (*func++ != '_')
142447445Sdonn return;
142547445Sdonn
142647445Sdonn /* assembly functions are assumed to have void type */
142747445Sdonn if (void_undefined)
142847445Sdonn {
142947445Sdonn /* .stabs "void:t15=15",128,0,0,0 */
143047445Sdonn (void) symbol_new("void:t1=1",
143147445Sdonn N_LSYM,
143247445Sdonn 0,
143347445Sdonn 0,
143447445Sdonn 0,
143547445Sdonn &zero_address_frag);
143647445Sdonn void_undefined = 0;
143747445Sdonn }
143847445Sdonn
143947445Sdonn /* .stabs "func:F1",36,0,0,. */
144047445Sdonn symbolP = symbol_new((char *) 0,
144147445Sdonn N_FUN,
144247445Sdonn 0,
144347445Sdonn 0,
144447445Sdonn obstack_next_free(& frags) - frag_now->fr_literal,
144547445Sdonn frag_now);
144647445Sdonn obstack_grow(¬es, func, strlen(func));
144747445Sdonn obstack_1grow(¬es, ':');
144847445Sdonn obstack_1grow(¬es, 'F');
144947445Sdonn obstack_1grow(¬es, '1');
145047445Sdonn obstack_1grow(¬es, '\0');
145147445Sdonn symbolP->sy_name = obstack_finish(¬es);
145247445Sdonn }
145347445Sdonn
stabd(line)145447445Sdonn stabd(line)
145547445Sdonn unsigned line;
145647445Sdonn {
145747445Sdonn /* .stabd 68,0,line */
145847445Sdonn (void) symbol_new((char *)0,
145947445Sdonn N_SLINE,
146047445Sdonn 0,
146147445Sdonn line,
146247445Sdonn obstack_next_free(& frags) - frag_now->fr_literal,
146347445Sdonn frag_now);
146447445Sdonn }
146547445Sdonn
146647445Sdonn /*
146747406Sdonn * cons()
146847406Sdonn *
146947406Sdonn * CONStruct more frag of .bytes, or .words etc.
147047406Sdonn * Should need_pass_2 be TRUE then emit no frag(s).
147147406Sdonn * This understands EXPRESSIONS, as opposed to big_cons().
147247406Sdonn *
147347406Sdonn * Bug (?)
147447406Sdonn *
147547406Sdonn * This has a split personality. We use expression() to read the
147647406Sdonn * value. We can detect if the value won't fit in a byte or word.
147747406Sdonn * But we can't detect if expression() discarded significant digits
147847406Sdonn * in the case of a long. Not worth the crocks required to fix it.
147947406Sdonn */
148047406Sdonn void
cons(nbytes)148147406Sdonn cons(nbytes) /* worker to do .byte etc statements */
148247406Sdonn /* clobbers input_line_pointer, checks */
148347406Sdonn /* end-of-line. */
148447406Sdonn register int nbytes; /* 1=.byte, 2=.word, 4=.long */
148547406Sdonn {
148647406Sdonn register char c;
148747406Sdonn register long int mask; /* High-order bits we will left-truncate, */
148847406Sdonn /* but includes sign bit also. */
148947406Sdonn register long int get; /* what we get */
149047406Sdonn register long int use; /* get after truncation. */
149147406Sdonn register long int unmask; /* what bits we will store */
149247406Sdonn register char * p;
149347406Sdonn register segT segment;
149447406Sdonn expressionS exp;
149547406Sdonn #ifdef NS32K
149647406Sdonn void fix_new_ns32k();
149747406Sdonn #else
149847406Sdonn void fix_new();
149947406Sdonn #endif
150047406Sdonn
150147406Sdonn /*
150247406Sdonn * Input_line_pointer -> 1st char after pseudo-op-code and could legally
150347406Sdonn * be a end-of-line. (Or, less legally an eof - which we cope with.)
150447406Sdonn */
150547406Sdonn /* JF << of >= number of bits in the object is undefined. In particular
150647406Sdonn SPARC (Sun 4) has problems */
150747406Sdonn if(nbytes>=sizeof(long int))
150847406Sdonn mask = 0;
150947406Sdonn else
151047406Sdonn mask = ~0 << (BITS_PER_CHAR * nbytes); /* Don't store these bits. */
151147406Sdonn unmask = ~ mask; /* Do store these bits. */
151247406Sdonn #ifdef NEVER
151347406Sdonn "Do this mod if you want every overflow check to assume SIGNED 2's complement data.";
151447406Sdonn mask = ~ (unmask >> 1); /* Includes sign bit now. */
151547406Sdonn #endif
151647406Sdonn /*
151747406Sdonn * The following awkward logic is to parse ZERO or more expressions,
151847406Sdonn * comma seperated. Recall an expression includes its leading &
151947406Sdonn * trailing blanks. We fake a leading ',' if there is (supposed to
152047406Sdonn * be) a 1st expression, and keep demanding 1 expression for each ','.
152147406Sdonn */
152247406Sdonn if (is_it_end_of_statement())
152347406Sdonn {
152447406Sdonn c = 0; /* Skip loop. */
152547406Sdonn input_line_pointer ++; /* Matches end-of-loop 'correction'. */
152647406Sdonn }
152747406Sdonn else
152847406Sdonn c = ','; /* Do loop. */
152947406Sdonn while ( c == ',' )
153047406Sdonn {
153147406Sdonn segment = expression( &exp ); /* At least scan over the expression. */
153247406Sdonn if ( ! need_pass_2 )
153347406Sdonn { /* Still worthwhile making frags. */
153447406Sdonn
153547406Sdonn /* Don't call this if we are going to junk this pass anyway! */
153647406Sdonn know( segment != SEG_PASS1 );
153747406Sdonn
153847406Sdonn if ( segment == SEG_DIFFERENCE && exp . X_add_symbol == NULL )
153947406Sdonn {
154047406Sdonn as_warn( "Subtracting symbol \"%s\"(segment\"%s\") is too hard. Absolute segment assumed.",
154147406Sdonn exp . X_subtract_symbol -> sy_name,
154247406Sdonn seg_name [(int) N_TYPE_seg [exp . X_subtract_symbol -> sy_type & N_TYPE]]);
154347406Sdonn segment = SEG_ABSOLUTE;
154447406Sdonn /* Leave exp . X_add_number alone. */
154547406Sdonn }
154647406Sdonn p = frag_more (nbytes);
154747406Sdonn switch (segment)
154847406Sdonn {
154947406Sdonn case SEG_BIG:
155047406Sdonn as_warn( "%s number illegal. Absolute 0 assumed.",
155147406Sdonn exp . X_add_number > 0 ? "Bignum" : "Floating-Point");
155247406Sdonn md_number_to_chars (p, (long)0, nbytes);
155347406Sdonn break;
155447406Sdonn
155547406Sdonn case SEG_NONE:
155647406Sdonn as_warn( "0 assumed for missing expression" );
155747406Sdonn exp . X_add_number = 0;
155847406Sdonn know( exp . X_add_symbol == NULL );
155947406Sdonn /* fall into SEG_ABSOLUTE */
156047406Sdonn case SEG_ABSOLUTE:
156147406Sdonn get = exp . X_add_number;
156247406Sdonn use = get & unmask;
156347406Sdonn if ( (get & mask) && (get & mask) != mask )
156447406Sdonn { /* Leading bits contain both 0s & 1s. */
156547406Sdonn as_warn("Value x%x truncated to x%x.", get, use);
156647406Sdonn }
156747406Sdonn md_number_to_chars (p, use, nbytes); /* put bytes in right order. */
156847406Sdonn break;
156947406Sdonn
157047406Sdonn case SEG_DIFFERENCE:
157147406Sdonn #ifndef WORKING_DOT_WORD
157247406Sdonn if(nbytes==2) {
157347406Sdonn struct broken_word *x;
157447406Sdonn
157547406Sdonn x=(struct broken_word *)xmalloc(sizeof(struct broken_word));
157647406Sdonn x->next_broken_word=broken_words;
157747406Sdonn broken_words=x;
157847406Sdonn x->frag=frag_now;
157947406Sdonn x->word_goes_here=p;
158047406Sdonn x->dispfrag=0;
158147406Sdonn x->add=exp.X_add_symbol;
158247406Sdonn x->sub=exp.X_subtract_symbol;
158347406Sdonn x->addnum=exp.X_add_number;
158447406Sdonn x->added=0;
158547406Sdonn new_broken_words++;
158647406Sdonn break;
158747406Sdonn }
158847406Sdonn /* Else Fall through into. . . */
158947406Sdonn #endif
159047406Sdonn case SEG_BSS:
159147406Sdonn case SEG_UNKNOWN:
159247406Sdonn case SEG_TEXT:
159347406Sdonn case SEG_DATA:
159447406Sdonn #if defined(SPARC) || defined(I860)
159547406Sdonn fix_new (frag_now, p - frag_now -> fr_literal, nbytes,
159647406Sdonn exp . X_add_symbol, exp . X_subtract_symbol,
159747406Sdonn exp . X_add_number, 0, RELOC_32);
159847406Sdonn #endif
159947406Sdonn #ifdef NS32K
160047406Sdonn fix_new_ns32k (frag_now, p - frag_now -> fr_literal, nbytes,
160147406Sdonn exp . X_add_symbol, exp . X_subtract_symbol,
160247406Sdonn exp . X_add_number, 0, 0, 2, 0, 0);
160347406Sdonn #endif
160447406Sdonn #if !defined(SPARC) && !defined(NS32K) && !defined(I860)
160547406Sdonn fix_new (frag_now, p - frag_now -> fr_literal, nbytes,
160647406Sdonn exp . X_add_symbol, exp . X_subtract_symbol,
160747406Sdonn exp . X_add_number, 0);
160847406Sdonn #endif
160947406Sdonn break;
161047406Sdonn
161147406Sdonn default:
161247406Sdonn BAD_CASE( segment );
161347406Sdonn break;
161447406Sdonn } /* switch(segment) */
161547406Sdonn } /* if(!need_pass_2) */
161647406Sdonn c = * input_line_pointer ++;
161747406Sdonn } /* while(c==',') */
161847406Sdonn input_line_pointer --; /* Put terminator back into stream. */
161947406Sdonn demand_empty_rest_of_line();
162047406Sdonn } /* cons() */
162147406Sdonn
162247406Sdonn /*
162347406Sdonn * big_cons()
162447406Sdonn *
162547406Sdonn * CONStruct more frag(s) of .quads, or .octa etc.
162647406Sdonn * Makes 0 or more new frags.
162747406Sdonn * If need_pass_2 == TRUE, generate no frag.
162847406Sdonn * This understands only bignums, not expressions. Cons() understands
162947406Sdonn * expressions.
163047406Sdonn *
163147406Sdonn * Constants recognised are '0...'(octal) '0x...'(hex) '...'(decimal).
163247406Sdonn *
163347406Sdonn * This creates objects with struct obstack_control objs, destroying
163447406Sdonn * any context objs held about a partially completed object. Beware!
163547406Sdonn *
163647406Sdonn *
163747406Sdonn * I think it sucks to have 2 different types of integers, with 2
163847406Sdonn * routines to read them, store them etc.
163947406Sdonn * It would be nicer to permit bignums in expressions and only
164047406Sdonn * complain if the result overflowed. However, due to "efficiency"...
164147406Sdonn */
164247406Sdonn void
big_cons(nbytes)164347406Sdonn big_cons(nbytes) /* worker to do .quad etc statements */
164447406Sdonn /* clobbers input_line_pointer, checks */
164547406Sdonn /* end-of-line. */
164647406Sdonn register int nbytes; /* 8=.quad 16=.octa ... */
164747406Sdonn {
164847406Sdonn register char c; /* input_line_pointer -> c. */
164947406Sdonn register int radix;
165047406Sdonn register long int length; /* Number of chars in an object. */
165147406Sdonn register int digit; /* Value of 1 digit. */
165247406Sdonn register int carry; /* For multi-precision arithmetic. */
165347406Sdonn register int work; /* For multi-precision arithmetic. */
165447406Sdonn register char * p; /* For multi-precision arithmetic. */
165547406Sdonn
165647406Sdonn extern char hex_value[]; /* In hex_value.c. */
165747406Sdonn
165847406Sdonn /*
165947406Sdonn * The following awkward logic is to parse ZERO or more strings,
166047406Sdonn * comma seperated. Recall an expression includes its leading &
166147406Sdonn * trailing blanks. We fake a leading ',' if there is (supposed to
166247406Sdonn * be) a 1st expression, and keep demanding 1 expression for each ','.
166347406Sdonn */
166447406Sdonn if (is_it_end_of_statement())
166547406Sdonn {
166647406Sdonn c = 0; /* Skip loop. */
166747406Sdonn }
166847406Sdonn else
166947406Sdonn {
167047406Sdonn c = ','; /* Do loop. */
167147406Sdonn -- input_line_pointer;
167247406Sdonn }
167347406Sdonn while (c == ',')
167447406Sdonn {
167547406Sdonn ++ input_line_pointer;
167647406Sdonn SKIP_WHITESPACE();
167747406Sdonn c = * input_line_pointer;
167847406Sdonn /* C contains 1st non-blank character of what we hope is a number. */
167947406Sdonn if (c == '0')
168047406Sdonn {
168147406Sdonn c = * ++ input_line_pointer;
168247406Sdonn if (c == 'x' || c=='X')
168347406Sdonn {
168447406Sdonn c = * ++ input_line_pointer;
168547406Sdonn radix = 16;
168647406Sdonn }
168747406Sdonn else
168847406Sdonn {
168947406Sdonn radix = 8;
169047406Sdonn }
169147406Sdonn }
169247406Sdonn else
169347406Sdonn {
169447406Sdonn radix = 10;
169547406Sdonn }
169647406Sdonn /*
169747406Sdonn * This feature (?) is here to stop people worrying about
169847406Sdonn * mysterious zero constants: which is what they get when
169947406Sdonn * they completely omit digits.
170047406Sdonn */
170147406Sdonn if (hex_value[c] >= radix)
170247406Sdonn {
170347406Sdonn as_warn( "Missing digits. 0 assumed." );
170447406Sdonn }
170547406Sdonn bignum_high = bignum_low - 1; /* Start constant with 0 chars. */
170647406Sdonn for( ; (digit = hex_value [c]) < radix; c = * ++ input_line_pointer)
170747406Sdonn {
170847406Sdonn /* Multiply existing number by radix, then add digit. */
170947406Sdonn carry = digit;
171047406Sdonn for (p=bignum_low; p <= bignum_high; p++)
171147406Sdonn {
171247406Sdonn work = (*p & MASK_CHAR) * radix + carry;
171347406Sdonn *p = work & MASK_CHAR;
171447406Sdonn carry = work >> BITS_PER_CHAR;
171547406Sdonn }
171647406Sdonn if (carry)
171747406Sdonn {
171847406Sdonn grow_bignum();
171947406Sdonn * bignum_high = carry & MASK_CHAR;
172047406Sdonn know( (carry & ~ MASK_CHAR) == 0);
172147406Sdonn }
172247406Sdonn }
172347406Sdonn length = bignum_high - bignum_low + 1;
172447406Sdonn if (length > nbytes)
172547406Sdonn {
172647406Sdonn as_warn( "Most significant bits truncated in integer constant." );
172747406Sdonn }
172847406Sdonn else
172947406Sdonn {
173047406Sdonn register long int leading_zeroes;
173147406Sdonn
173247406Sdonn for(leading_zeroes = nbytes - length;
173347406Sdonn leading_zeroes;
173447406Sdonn leading_zeroes --)
173547406Sdonn {
173647406Sdonn grow_bignum();
173747406Sdonn * bignum_high = 0;
173847406Sdonn }
173947406Sdonn }
174047406Sdonn if (! need_pass_2)
174147406Sdonn {
174247406Sdonn p = frag_more (nbytes);
174347406Sdonn bcopy (bignum_low, p, (int)nbytes);
174447406Sdonn }
174547406Sdonn /* C contains character after number. */
174647406Sdonn SKIP_WHITESPACE();
174747406Sdonn c = * input_line_pointer;
174847406Sdonn /* C contains 1st non-blank character after number. */
174947406Sdonn }
175047406Sdonn demand_empty_rest_of_line();
175147406Sdonn } /* big_cons() */
175247406Sdonn
175347406Sdonn static void
grow_bignum()175447406Sdonn grow_bignum() /* Extend bignum by 1 char. */
175547406Sdonn {
175647406Sdonn register long int length;
175747406Sdonn
175847406Sdonn bignum_high ++;
175947406Sdonn if (bignum_high >= bignum_limit)
176047406Sdonn {
176147406Sdonn length = bignum_limit - bignum_low;
176247406Sdonn bignum_low = xrealloc (bignum_low, length + length);
176347406Sdonn bignum_high = bignum_low + length;
176447406Sdonn bignum_limit = bignum_low + length + length;
176547406Sdonn }
176647406Sdonn } /* grow_bignum(); */
176747406Sdonn
176847406Sdonn /*
176947406Sdonn * float_cons()
177047406Sdonn *
177147406Sdonn * CONStruct some more frag chars of .floats .ffloats etc.
177247406Sdonn * Makes 0 or more new frags.
177347406Sdonn * If need_pass_2 == TRUE, no frags are emitted.
177447406Sdonn * This understands only floating literals, not expressions. Sorry.
177547406Sdonn *
177647406Sdonn * A floating constant is defined by atof_generic(), except it is preceded
177747406Sdonn * by 0d 0f 0g or 0h. After observing the STRANGE way my BSD AS does its
177847406Sdonn * reading, I decided to be incompatible. This always tries to give you
177947406Sdonn * rounded bits to the precision of the pseudo-op. Former AS did premature
178047406Sdonn * truncatation, restored noisy bits instead of trailing 0s AND gave you
178147406Sdonn * a choice of 2 flavours of noise according to which of 2 floating-point
178247406Sdonn * scanners you directed AS to use.
178347406Sdonn *
178447406Sdonn * In: input_line_pointer -> whitespace before, or '0' of flonum.
178547406Sdonn *
178647406Sdonn */
178747406Sdonn
178847406Sdonn void /* JF was static, but can't be if VAX.C is goning to use it */
float_cons(float_type)178947406Sdonn float_cons(float_type) /* Worker to do .float etc statements. */
179047406Sdonn /* Clobbers input_line-pointer, checks end-of-line. */
179147406Sdonn register float_type; /* 'f':.ffloat ... 'F':.float ... */
179247406Sdonn {
179347406Sdonn register char * p;
179447406Sdonn register char c;
179547406Sdonn int length; /* Number of chars in an object. */
179647406Sdonn register char * err; /* Error from scanning floating literal. */
179747406Sdonn char temp [MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT];
179847406Sdonn
179947406Sdonn /*
180047406Sdonn * The following awkward logic is to parse ZERO or more strings,
180147406Sdonn * comma seperated. Recall an expression includes its leading &
180247406Sdonn * trailing blanks. We fake a leading ',' if there is (supposed to
180347406Sdonn * be) a 1st expression, and keep demanding 1 expression for each ','.
180447406Sdonn */
180547406Sdonn if (is_it_end_of_statement())
180647406Sdonn {
180747406Sdonn c = 0; /* Skip loop. */
180847406Sdonn ++ input_line_pointer; /* -> past termintor. */
180947406Sdonn }
181047406Sdonn else
181147406Sdonn {
181247406Sdonn c = ','; /* Do loop. */
181347406Sdonn }
181447406Sdonn while (c == ',')
181547406Sdonn {
181647406Sdonn /* input_line_pointer -> 1st char of a flonum (we hope!). */
181747406Sdonn SKIP_WHITESPACE();
181847406Sdonn /* Skip any 0{letter} that may be present. Don't even check if the
181947406Sdonn * letter is legal. Someone may invent a "z" format and this routine
182047406Sdonn * has no use for such information. Lusers beware: you get
182147406Sdonn * diagnostics if your input is ill-conditioned.
182247406Sdonn */
182347406Sdonn
182447406Sdonn if(input_line_pointer[0]=='0' && isalpha(input_line_pointer[1]))
182547406Sdonn input_line_pointer+=2;
182647406Sdonn
182747406Sdonn err = md_atof (float_type, temp, &length);
182847406Sdonn know( length <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT);
182947406Sdonn know( length > 0 );
183047406Sdonn if (* err)
183147406Sdonn {
183247406Sdonn as_warn( "Bad floating literal: %s", err);
183347406Sdonn ignore_rest_of_line();
183447406Sdonn /* Input_line_pointer -> just after end-of-line. */
183547406Sdonn c = 0; /* Break out of loop. */
183647406Sdonn }
183747406Sdonn else
183847406Sdonn {
183947406Sdonn if ( ! need_pass_2)
184047406Sdonn {
184147406Sdonn p = frag_more (length);
184247406Sdonn bcopy (temp, p, length);
184347406Sdonn }
184447406Sdonn SKIP_WHITESPACE();
184547406Sdonn c = * input_line_pointer ++;
184647406Sdonn /* C contains 1st non-white character after number. */
184747406Sdonn /* input_line_pointer -> just after terminator (c). */
184847406Sdonn }
184947406Sdonn }
185047406Sdonn -- input_line_pointer; /* -> terminator (is not ','). */
185147406Sdonn demand_empty_rest_of_line();
185247406Sdonn } /* float_cons() */
185347406Sdonn
185447406Sdonn /*
185547406Sdonn * stringer()
185647406Sdonn *
185747406Sdonn * We read 0 or more ',' seperated, double-quoted strings.
185847406Sdonn *
185947406Sdonn * Caller should have checked need_pass_2 is FALSE because we don't check it.
186047406Sdonn */
186147406Sdonn static void
stringer(append_zero)186247406Sdonn stringer(append_zero) /* Worker to do .ascii etc statements. */
186347406Sdonn /* Checks end-of-line. */
186447406Sdonn register int append_zero; /* 0: don't append '\0', else 1 */
186547406Sdonn {
186647406Sdonn /* register char * p; JF unused */
186747406Sdonn /* register int length; JF unused */ /* Length of string we read, excluding */
186847406Sdonn /* trailing '\0' implied by closing quote. */
186947406Sdonn /* register char * where; JF unused */
187047406Sdonn /* register fragS * fragP; JF unused */
187147406Sdonn register int c;
187247406Sdonn
187347406Sdonn /*
187447406Sdonn * The following awkward logic is to parse ZERO or more strings,
187547406Sdonn * comma seperated. Recall a string expression includes spaces
187647406Sdonn * before the opening '\"' and spaces after the closing '\"'.
187747406Sdonn * We fake a leading ',' if there is (supposed to be)
187847406Sdonn * a 1st, expression. We keep demanding expressions for each
187947406Sdonn * ','.
188047406Sdonn */
188147406Sdonn if (is_it_end_of_statement())
188247406Sdonn {
188347406Sdonn c = 0; /* Skip loop. */
188447406Sdonn ++ input_line_pointer; /* Compensate for end of loop. */
188547406Sdonn }
188647406Sdonn else
188747406Sdonn {
188847406Sdonn c = ','; /* Do loop. */
188947406Sdonn }
189047406Sdonn for ( ; c == ','; c = *input_line_pointer ++)
189147406Sdonn {
189247406Sdonn SKIP_WHITESPACE();
189347406Sdonn if (* input_line_pointer == '\"')
189447406Sdonn {
189547406Sdonn ++ input_line_pointer; /* -> 1st char of string. */
189647406Sdonn while ( (c = next_char_of_string()) >= 0)
189747406Sdonn {
189847406Sdonn FRAG_APPEND_1_CHAR( c );
189947406Sdonn }
190047406Sdonn if (append_zero)
190147406Sdonn {
190247406Sdonn FRAG_APPEND_1_CHAR( 0 );
190347406Sdonn }
190447406Sdonn know( input_line_pointer [-1] == '\"' );
190547406Sdonn }
190647406Sdonn else
190747406Sdonn {
190847406Sdonn as_warn( "Expected \"-ed string" );
190947406Sdonn }
191047406Sdonn SKIP_WHITESPACE();
191147406Sdonn }
191247406Sdonn -- input_line_pointer;
191347406Sdonn demand_empty_rest_of_line();
191447406Sdonn } /* stringer() */
191547406Sdonn
191647406Sdonn static int
next_char_of_string()191747406Sdonn next_char_of_string ()
191847406Sdonn {
191947406Sdonn register int c;
192047406Sdonn
192147406Sdonn c = * input_line_pointer ++;
192247406Sdonn switch (c)
192347406Sdonn {
192447406Sdonn case '\"':
192547406Sdonn c = -1;
192647406Sdonn break;
192747406Sdonn
192847406Sdonn case '\\':
192947406Sdonn switch (c = * input_line_pointer ++)
193047406Sdonn {
193147406Sdonn case 'b':
193247406Sdonn c = '\b';
193347406Sdonn break;
193447406Sdonn
193547406Sdonn case 'f':
193647406Sdonn c = '\f';
193747406Sdonn break;
193847406Sdonn
193947406Sdonn case 'n':
194047406Sdonn c = '\n';
194147406Sdonn break;
194247406Sdonn
194347406Sdonn case 'r':
194447406Sdonn c = '\r';
194547406Sdonn break;
194647406Sdonn
194747406Sdonn case 't':
194847406Sdonn c = '\t';
194947406Sdonn break;
195047406Sdonn
195147406Sdonn case '\\':
195247406Sdonn case '"':
195347406Sdonn break; /* As itself. */
195447406Sdonn
195547406Sdonn case '0':
195647406Sdonn case '1':
195747406Sdonn case '2':
195847406Sdonn case '3':
195947406Sdonn case '4':
196047406Sdonn case '5':
196147406Sdonn case '6':
196247406Sdonn case '7':
196347406Sdonn case '8':
196447406Sdonn case '9':
196547406Sdonn {
196647406Sdonn long int number;
196747406Sdonn
196847406Sdonn for (number = 0; isdigit(c); c = * input_line_pointer ++)
196947406Sdonn {
197047406Sdonn number = number * 8 + c - '0';
197147406Sdonn }
197247406Sdonn c = number;
197347406Sdonn }
197447406Sdonn -- input_line_pointer;
197547406Sdonn break;
197647406Sdonn
197747406Sdonn case '\n':
197847406Sdonn /* as_fatal( "Unterminated string - use app!" ); */
197947406Sdonn /* To be compatible with BSD 4.2 as: give the luser a linefeed!! */
198047406Sdonn c = '\n';
198147406Sdonn break;
198247406Sdonn
198347406Sdonn default:
198447406Sdonn as_warn( "Bad escaped character in string, '?' assumed" );
198547406Sdonn c = '?';
198647406Sdonn break;
198747406Sdonn }
198847406Sdonn break;
198947406Sdonn
199047406Sdonn default:
199147406Sdonn break;
199247406Sdonn }
199347406Sdonn return (c);
199447406Sdonn }
199547406Sdonn
199647406Sdonn static segT
get_segmented_expression(expP)199747406Sdonn get_segmented_expression ( expP )
199847406Sdonn register expressionS * expP;
199947406Sdonn {
200047406Sdonn register segT retval;
200147406Sdonn
200247406Sdonn if ( (retval = expression( expP )) == SEG_PASS1 || retval == SEG_NONE || retval == SEG_BIG )
200347406Sdonn {
200447406Sdonn as_warn("Expected address expression: absolute 0 assumed");
200547406Sdonn retval = expP -> X_seg = SEG_ABSOLUTE;
200647406Sdonn expP -> X_add_number = 0;
200747406Sdonn expP -> X_add_symbol = expP -> X_subtract_symbol = 0;
200847406Sdonn }
200947406Sdonn return (retval); /* SEG_ ABSOLUTE,UNKNOWN,DATA,TEXT,BSS */
201047406Sdonn }
201147406Sdonn
201247406Sdonn static segT
get_known_segmented_expression(expP)201347406Sdonn get_known_segmented_expression ( expP )
201447406Sdonn register expressionS * expP;
201547406Sdonn {
201647406Sdonn register segT retval;
201747406Sdonn register char * name1;
201847406Sdonn register char * name2;
201947406Sdonn
202047406Sdonn if ( (retval = get_segmented_expression (expP)) == SEG_UNKNOWN
202147406Sdonn )
202247406Sdonn {
202347406Sdonn name1 = expP -> X_add_symbol ? expP -> X_add_symbol -> sy_name : "";
202447406Sdonn name2 = expP -> X_subtract_symbol ? expP -> X_subtract_symbol -> sy_name : "";
202547406Sdonn if ( name1 && name2 )
202647406Sdonn {
202747406Sdonn as_warn("Symbols \"%s\" \"%s\" are undefined: absolute 0 assumed.",
202847406Sdonn name1, name2);
202947406Sdonn }
203047406Sdonn else
203147406Sdonn {
203247406Sdonn as_warn("Symbol \"%s\" undefined: absolute 0 assumed.",
203347406Sdonn name1 ? name1 : name2);
203447406Sdonn }
203547406Sdonn retval = expP -> X_seg = SEG_ABSOLUTE;
203647406Sdonn expP -> X_add_number = 0;
203747406Sdonn expP -> X_add_symbol = expP -> X_subtract_symbol = NULL;
203847406Sdonn }
203947406Sdonn know( retval == SEG_ABSOLUTE || retval == SEG_DATA || retval == SEG_TEXT || retval == SEG_BSS || retval == SEG_DIFFERENCE );
204047406Sdonn return (retval);
204147406Sdonn } /* get_known_segmented_expression() */
204247406Sdonn
204347406Sdonn
204447406Sdonn
204547406Sdonn /* static */ long int /* JF was static, but can't be if the MD pseudos are to use it */
get_absolute_expression()204647406Sdonn get_absolute_expression ()
204747406Sdonn {
204847406Sdonn expressionS exp;
204947406Sdonn register segT s;
205047406Sdonn
205147406Sdonn if ( (s = expression(& exp)) != SEG_ABSOLUTE )
205247406Sdonn {
205347406Sdonn if ( s != SEG_NONE )
205447406Sdonn {
205547406Sdonn as_warn( "Bad Absolute Expression, absolute 0 assumed.");
205647406Sdonn }
205747406Sdonn exp . X_add_number = 0;
205847406Sdonn }
205947406Sdonn return (exp . X_add_number);
206047406Sdonn }
206147406Sdonn
206247406Sdonn static char /* return terminator */
get_absolute_expression_and_terminator(val_pointer)206347406Sdonn get_absolute_expression_and_terminator( val_pointer)
206447406Sdonn long int * val_pointer; /* return value of expression */
206547406Sdonn {
206647406Sdonn * val_pointer = get_absolute_expression ();
206747406Sdonn return ( * input_line_pointer ++ );
206847406Sdonn }
206947406Sdonn
207047406Sdonn /*
207147406Sdonn * demand_copy_C_string()
207247406Sdonn *
207347406Sdonn * Like demand_copy_string, but return NULL if the string contains any '\0's.
207447406Sdonn * Give a warning if that happens.
207547406Sdonn */
207647406Sdonn static char *
demand_copy_C_string(len_pointer)207747406Sdonn demand_copy_C_string (len_pointer)
207847406Sdonn int * len_pointer;
207947406Sdonn {
208047406Sdonn register char * s;
208147406Sdonn
208247406Sdonn if (s = demand_copy_string (len_pointer))
208347406Sdonn {
208447406Sdonn register int len;
208547406Sdonn
208647406Sdonn for (len = * len_pointer;
208747406Sdonn len > 0;
208847406Sdonn len--)
208947406Sdonn {
209047406Sdonn if (* s == 0)
209147406Sdonn {
209247406Sdonn s = 0;
209347406Sdonn len = 1;
209447406Sdonn * len_pointer = 0;
209547406Sdonn as_warn( "This string may not contain \'\\0\'" );
209647406Sdonn }
209747406Sdonn }
209847406Sdonn }
209947406Sdonn return (s);
210047406Sdonn }
210147406Sdonn
210247406Sdonn /*
210347406Sdonn * demand_copy_string()
210447406Sdonn *
210547406Sdonn * Demand string, but return a safe (=private) copy of the string.
210647406Sdonn * Return NULL if we can't read a string here.
210747406Sdonn */
210847406Sdonn static char *
demand_copy_string(lenP)210947406Sdonn demand_copy_string (lenP)
211047406Sdonn int * lenP;
211147406Sdonn {
211247406Sdonn register int c;
211347406Sdonn register int len;
211447406Sdonn char * retval;
211547406Sdonn
211647406Sdonn len = 0;
211747406Sdonn SKIP_WHITESPACE();
211847406Sdonn if (* input_line_pointer == '\"')
211947406Sdonn {
212047406Sdonn input_line_pointer ++; /* Skip opening quote. */
212147406Sdonn while ( (c = next_char_of_string()) >= 0 ) {
212247406Sdonn obstack_1grow ( ¬es, c );
212347406Sdonn len ++;
212447406Sdonn }
212547406Sdonn /* JF this next line is so demand_copy_C_string will return a null
212647406Sdonn termanated string. */
212747406Sdonn obstack_1grow(¬es,'\0');
212847406Sdonn retval=obstack_finish( ¬es);
212947406Sdonn } else {
213047406Sdonn as_warn( "Missing string" );
213147406Sdonn retval = NULL;
213247406Sdonn ignore_rest_of_line ();
213347406Sdonn }
213447406Sdonn * lenP = len;
213547406Sdonn return (retval);
213647406Sdonn }
213747406Sdonn
213847406Sdonn /*
213947406Sdonn * is_it_end_of_statement()
214047406Sdonn *
214147406Sdonn * In: Input_line_pointer -> next character.
214247406Sdonn *
214347406Sdonn * Do: Skip input_line_pointer over all whitespace.
214447406Sdonn *
214547406Sdonn * Out: TRUE if input_line_pointer -> end-of-line.
214647406Sdonn */
214747406Sdonn static int
is_it_end_of_statement()214847406Sdonn is_it_end_of_statement()
214947406Sdonn {
215047406Sdonn SKIP_WHITESPACE();
215147406Sdonn return (is_end_of_line [* input_line_pointer]);
215247406Sdonn }
215347406Sdonn
215447406Sdonn void
equals(sym_name)215547406Sdonn equals(sym_name)
215647406Sdonn char *sym_name;
215747406Sdonn {
215847406Sdonn register struct symbol * symbolP; /* symbol we are working with */
215947406Sdonn
216047406Sdonn input_line_pointer++;
216147406Sdonn if(*input_line_pointer=='=')
216247406Sdonn input_line_pointer++;
216347406Sdonn
216447406Sdonn while(*input_line_pointer==' ' || *input_line_pointer=='\t')
216547406Sdonn input_line_pointer++;
216647406Sdonn
216747406Sdonn if(sym_name[0]=='.' && sym_name[1]=='\0') {
216847406Sdonn /* Turn '. = mumble' into a .org mumble */
216947406Sdonn register segT segment;
217047406Sdonn expressionS exp;
217147406Sdonn register char *p;
217247406Sdonn
217347406Sdonn segment = get_known_segmented_expression(& exp);
217447406Sdonn if ( ! need_pass_2 ) {
217547406Sdonn if (segment != now_seg && segment != SEG_ABSOLUTE)
217647406Sdonn as_warn("Illegal segment \"%s\". Segment \"%s\" assumed.",
217747406Sdonn seg_name [(int) segment], seg_name [(int) now_seg]);
217847406Sdonn p = frag_var (rs_org, 1, 1, (relax_substateT)0, exp.X_add_symbol,
217947406Sdonn exp.X_add_number, (char *)0);
218047406Sdonn * p = 0;
218147406Sdonn } /* if (ok to make frag) */
218247406Sdonn } else {
218347406Sdonn symbolP=symbol_find_or_make(sym_name);
218447406Sdonn pseudo_set(symbolP);
218547406Sdonn }
218647406Sdonn }
218747406Sdonn
218847406Sdonn /* end: read.c */
2189