home *** CD-ROM | disk | FTP | other *** search
/ NeXTSTEP 3.2 (Developer) / NS_dev_3.2.iso / NextDeveloper / Source / GNU / cctools / as / read.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-04  |  93.2 KB  |  3,442 lines

  1. /* read.c - read a source file -
  2.    Copyright (C) 1986,1987 Free Software Foundation, Inc.
  3.  
  4. This file is part of GAS, the GNU Assembler.
  5.  
  6. GAS is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 1, or (at your option)
  9. any later version.
  10.  
  11. GAS is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GAS; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. #define MASK_CHAR (0xFF)    /* If your chars aren't 8 bits, you will
  21.                    change this a bit.  But then, GNU isn't
  22.                    spozed to run on your machine anyway.
  23.                    (RMS is so shortsighted sometimes.)
  24.                  */
  25.  
  26. #define MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT (16)
  27.                 /* This is the largest known floating point */
  28.                 /* format (for now). It will grow when we */
  29.                 /* do 4361 style flonums. */
  30.  
  31.  
  32. /* Routines that read assembler source text to build spagetti in memory. */
  33. /* Another group of these functions is in the as-expr.c module */
  34.  
  35. #include <ctype.h>
  36. #include <sys/types.h>
  37. #include <sys/stat.h>
  38. #include "as.h"
  39. #include "read.h"
  40. #include "md.h"
  41. #include "hash.h"
  42. #include "obstack.h"
  43. #include "frags.h"
  44. #include "flonum.h"
  45. #include "struc-symbol.h"
  46. #include "expr.h"
  47. #include "symbols.h"
  48.  
  49. #ifdef SPARC
  50. #include "sparc.h"
  51. #endif
  52.  
  53. #ifdef M88K
  54. #include "m88k.h"
  55. #endif
  56.  
  57. #ifdef M98K
  58. #include "m98k.h"
  59. #endif
  60.  
  61. #ifdef I860
  62. #include "i860.h"
  63. #endif I860
  64.  
  65. char *    input_line_pointer;    /* -> next char of source file to parse. */
  66.  
  67.  
  68. #if BITS_PER_CHAR != 8
  69. The following table is indexed by [ (char) ] and will break if
  70. a char does not have exactly 256 states (hopefully 0:255!) !
  71. #endif
  72.  
  73. const
  74. char                /* used by is_... macros. our ctype[] */
  75. lex_type [256] = {
  76.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,       /* @ABCDEFGHIJKLMNO */
  77.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,       /* PQRSTUVWXYZ[\]^_ */
  78.   0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,       /* _!"#$%&'()*+,-./ */
  79.   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,       /* 0123456789:;<=>? */
  80.   0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,       /* @ABCDEFGHIJKLMNO */
  81. #ifdef NeXT
  82.   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 3,       /* PQRSTUVWXYZ[\]^_ */
  83. #else !defined(NeXT)
  84.   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 3,       /* PQRSTUVWXYZ[\]^_ */
  85. #endif NeXT
  86.   0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,       /* `abcdefghijklmno */
  87.   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0,       /* pqrstuvwxyz{|}~. */
  88. #ifdef NeXT
  89.   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,    /* allow all chars  */
  90.   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,    /* with the high bit */
  91.   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,    /* set in names */
  92.   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  93.   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  94.   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  95.   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 
  96. #else !defined(NeXT)
  97.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  98.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  99.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  100.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  101.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  102.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  103.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 
  104. #endif NeXT
  105. };
  106.  
  107.  
  108. /*
  109.  * In: a character.
  110.  * Out: TRUE if this character ends a line.
  111.  */
  112. #define _ (0)
  113. const
  114. char is_end_of_line [256] = {
  115.  _, _, _, _, _, _, _, _, _, _,99, _, _, _, _, _, /* @abcdefghijklmno */
  116.  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /*                  */
  117.  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /*                  */
  118.  _, _, _, _, _, _, _, _, _, _, _,99, _, _, _, _, /* 0123456789:;<=>? */
  119. #if defined(M88K) || defined(M98K)
  120. 99, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* @ABCDEFGHIJKLMNO */
  121. #else
  122.  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /*                  */
  123. #endif
  124.  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /*                  */
  125.  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /*                  */
  126.  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /*                  */
  127.  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /*                  */
  128.  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /*                  */
  129.  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /*                  */
  130.  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /*                  */
  131.  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _  /*                  */
  132. };
  133. #undef _
  134.  
  135. #ifdef NeXT    /* the conditional assembly feature (.if, .else, and .endif) */
  136. /* DJA -- added conditionals.  cond_state tells us what we are in
  137.  * the middle of processing.  ignore can be either TRUE or FALSE.  When
  138.  * TRUE we are ignoring the block of code in the middle of a conditional.
  139.  * MAX_IF_DEPTH is the maximum depth that if's can be nested.
  140.  */
  141.  
  142. #define MAX_IF_DEPTH 20
  143. typedef enum
  144. {
  145.     no_cond,    /* no conditional is being processed */
  146.     if_cond,    /* inside if conditional */
  147.     elseif_cond,    /* inside elseif conditional */
  148.     else_cond    /* inside else conditional */
  149. }        cond_type;
  150. struct cond_state
  151. {
  152.   cond_type    the_cond;
  153.   int        cond_met;
  154.   int        ignore;
  155. };
  156. typedef struct cond_state cond_stateS;
  157. static cond_stateS the_cond_state = {no_cond, FALSE, FALSE};
  158. static cond_stateS last_states[MAX_IF_DEPTH];
  159. static int if_depth = 0;
  160. void totally_ignore_line();
  161. #endif NeXT    /* the conditional assembly feature (.if, .else, and .endif) */
  162.  
  163. #ifdef NeXT    /* the .macro feature */
  164. static struct hash_control
  165.     *ma_hash = NULL;    /* use before set up: NULL-> address error */
  166. static struct obstack macros;    /* obstack for macro text */
  167. static char *macro_name = NULL;    /* name of macro we are defining */
  168. static int count_lines = TRUE;    /* turns line number counting on and off */
  169. extern void add_to_macro_definition();
  170. static void expand_macro();
  171. static void ma_begin();
  172. static int macros_on = TRUE;    /* .macros_on and .macros_off toggles this to
  173.                    allow macros to be turned off, which allows
  174.                    macros to override a machine instruction and
  175.                    still use it. */
  176. #define MAX_MACRO_DEPTH 20
  177. static int macro_depth = 0;
  178. #endif NeXT    /* the .macro feature */
  179.  
  180. #ifdef NeXT    /* the .dump/.load feature */
  181. /*
  182.  * DJA -- Used for .dump and .load
  183.  */
  184. static FILE            * dump_fp;
  185. extern struct hash_control    * sy_hash;
  186. #endif NeXT    /* the .dump/.load feature */
  187.  
  188.                 /* Functions private to this file. */
  189. #ifdef NeXT
  190. static void        parse_a_buffer();
  191. static void        parse_line_comment();
  192. #endif NeXT
  193. void            equals();
  194. void            big_cons();
  195. void            cons();
  196. static char*        demand_copy_C_string();
  197. static char*        demand_copy_string();
  198. void            demand_empty_rest_of_line();
  199. void            float_cons();
  200. long int        get_absolute_expression();
  201. static char        get_absolute_expression_and_terminator();
  202. #ifdef I860
  203.        segT        get_known_segmented_expression();
  204. #else !defined(I860)
  205. static segT        get_known_segmented_expression();
  206. #endif I860
  207. void            ignore_rest_of_line();
  208. static int        is_it_end_of_statement();
  209. static void        pobegin();
  210. static void        pseudo_set();
  211. static void        stab();
  212. #ifdef I860
  213.        void        stringer();
  214. #else !defined(I860)
  215. static void        stringer();
  216. #endif I860
  217.  
  218. extern char line_comment_chars[];
  219.  
  220. #ifdef NeXT    /* .include feature */
  221. extern int    doing_include;
  222. /*
  223.  * DJA -- This variable is not static so read_an_include_file can save
  224.  * and restore it.
  225.  */
  226.        char *    buffer_limit;    /* -> 1 + last char in buffer. */
  227. #else NeXT    /* .include feature */
  228. static char *    buffer_limit;    /* -> 1 + last char in buffer. */
  229. #endif NeXT    /* .include feature */
  230.  
  231. static char *    bignum_low;    /* Lowest char of bignum. */
  232. static char *    bignum_limit;    /* 1st illegal address of bignum. */
  233. static char *    bignum_high;    /* Highest char of bignum. */
  234.                 /* May point to (bignum_start-1). */
  235.                 /* Never >= bignum_limit. */
  236. #ifndef NeXT    /* hack cleaned up see parse_line_comment() */
  237. static char *old_buffer = 0;    /* JF a hack */
  238. static char *old_input;
  239. static char *old_limit;
  240. #endif NeXT    /* hack cleaned up see parse_line_comment() */
  241.  
  242. #ifndef WORKING_DOT_WORD
  243. struct broken_word *broken_words;
  244. int new_broken_words = 0;
  245. #endif
  246.  
  247. static void grow_bignum ();
  248. static int next_char_of_string ();
  249.  
  250. void
  251. read_begin()
  252. {
  253.   pobegin();
  254. #ifdef NeXT    /* the .macro feature */
  255.   ma_begin();
  256. #endif NeXT    /* the .macro feature */
  257.   obstack_begin( ¬es, 5000 );
  258. #define BIGNUM_BEGIN_SIZE (16)
  259.   bignum_low = xmalloc((long)BIGNUM_BEGIN_SIZE);
  260.   bignum_limit = bignum_low + BIGNUM_BEGIN_SIZE;
  261. }
  262.  
  263. /* set up pseudo-op tables */
  264.  
  265. static struct hash_control *
  266. po_hash = NULL;            /* use before set up: NULL-> address error */
  267.  
  268.  
  269. void    s_abort(),    s_align(),    s_comm(),    s_data();
  270. void    s_desc(),    s_even(),    s_file(),    s_fill();
  271. void    s_globl(),    s_lcomm(),    s_line(),    s_lsym();
  272. void    s_org(),    s_set(),    s_space(),    s_text();
  273. #ifdef NeXT
  274. void    s_reference(),    s_include(),    s_dump(),    s_load();
  275. void    s_if(),        s_elseif(),    s_else(),    s_endif();
  276. void    s_macro(),    s_endmacro(),    s_macros_on(),    s_macros_off();
  277. void    s_abs();
  278. #endif NeXT
  279.  
  280. #ifdef DONTDEF
  281. void    s_gdbline(),    s_gdblinetab();
  282. void    s_gdbbeg(),    s_gdbblock(),    s_gdbend(),    s_gdbsym();
  283. #endif
  284.  
  285. void    stringer();
  286. void    cons();
  287. void    float_cons();
  288. void    big_cons();
  289. void    stab();
  290.  
  291. #ifdef Mach_O
  292. void    s_text_Mach_O(),s_data_Mach_O();
  293. #endif Mach_O
  294.  
  295. const
  296. static pseudo_typeS
  297. potable[] =
  298. {
  299.   { "abort",    s_abort,    0    },
  300. #if !defined(I860) /* i860 has it's own align syntax */
  301.   { "align",    s_align,    0    },
  302. #endif !defined(I860)
  303.   { "ascii",    stringer,    0    },
  304.   { "asciz",    stringer,    1    },
  305.   { "byte",    cons,        1    },
  306.   { "comm",    s_comm,        0    },
  307.   { "data",    s_data,        0    },
  308.   { "desc",    s_desc,        0    },
  309.   { "double",    float_cons,    'd'    },
  310.   { "file",    s_file,        0    },
  311.   { "fill",    s_fill,        0    },
  312. #ifdef NeXT
  313.   /* At NeXT we allow .float only on the 68k machines and the i860 */
  314. #if defined(M68K) || defined(I860)
  315.   { "float",    float_cons,    'f'    },
  316. #endif defined(M68K) || defined(I860)
  317. #endif NeXT
  318. #ifdef DONTDEF
  319.   { "gdbbeg",    s_gdbbeg,    0    },
  320.   { "gdbblock",    s_gdbblock,    0    },
  321.   { "gdbend",    s_gdbend,    0    },
  322.   { "gdbsym",    s_gdbsym,    0    },
  323.   { "gdbline",    s_gdbline,    0    },
  324.   { "gdblinetab",s_gdblinetab,    0    },
  325. #endif
  326.   { "globl",    s_globl,    0    },
  327. #ifdef NeXT
  328.   /* At NeXT we allow .int only on the 68k and i860 machines */
  329. #if defined(M68K) || defined(I860)
  330.   { "int",    cons,        4    },
  331. #endif defined(M68K) || defined(I860)
  332. #endif NeXT
  333.   { "lcomm",    s_lcomm,    0    },
  334.   { "line",    s_line,        0    },
  335.   { "long",    cons,        4    },
  336. #ifdef NeXT
  337.   /* At NeXT we allow .quad and .octa only on the 68k machines */
  338. #ifdef M68K
  339.   { "quad",    big_cons,    8    },
  340.   { "octa",    big_cons,    16    },
  341. #endif M68K
  342. #endif NeXT
  343.   { "lsym",    s_lsym,        0    },
  344. #if !defined(I860)
  345.   { "org",    s_org,        0    },
  346. #endif !defined(I860)
  347.   { "set",    s_set,        0    },
  348.   { "short",    cons,        2    },
  349.   { "single",    float_cons,    'f'    },
  350.   { "space",    s_space,    0    },
  351.   { "stabd",    stab,        'd'    },
  352.   { "stabn",    stab,        'n'    },
  353.   { "stabs",    stab,        's'    },
  354.   { "text",    s_text,        0    },
  355. #ifdef NeXT
  356.   /* At NeXT we allow .word only on the 68k machines, i386 machines, and the
  357.      i860 where we don't ship the assembler */
  358. #if defined(M68K) || defined(I386)
  359. #ifndef RISC
  360.   /* A "word" according to 386, 68k, and 32k is just 16 bits.
  361.      On 88k and sparc it's 32 bits.  */
  362.   { "word",    cons,        2    },
  363. #endif RISC
  364. #endif defined(M68K) || defined(I386)
  365. #endif NeXT
  366.  
  367. #ifdef NeXT
  368.   { "reference",s_reference,    0    },
  369.   { "include",    s_include,    0    },
  370.   { "macro",    s_macro,    0    },
  371.   { "endmacro",    s_endmacro,    0    },
  372.   { "if",    s_if,        0    },
  373.   { "elseif",    s_elseif,    0    },
  374.   { "else",    s_else,        0    },
  375.   { "endif",    s_endif,    0    },
  376.   { "dump",    s_dump,        0    },
  377.   { "load",    s_load,        0    },
  378. #ifndef M88K
  379.   { "abs",    s_abs,        0    },
  380. #endif !defined(M88K)
  381.   { "macros_on",    s_macros_on,    0    },
  382.   { "macros_off",    s_macros_off,    0    },
  383. #endif NeXT
  384. #ifdef Mach_O
  385.   /*
  386.    * The sub-segment numbers here must agree with what is in Mach-O.c .
  387.    * I see no easy way to avoid this and of course I would rather have
  388.    * arbitrary Mach-O sections.
  389.    */
  390.   /* text sub-segments */
  391.   { "const",            s_text_Mach_O,    1    },
  392.   { "static_const",        s_text_Mach_O,    2    },
  393.   { "cstring",            s_text_Mach_O,    3    },
  394.   { "literal4",            s_text_Mach_O,    4    },
  395.   { "literal8",            s_text_Mach_O,    5    },
  396.   { "constructor",        s_text_Mach_O,    6    },
  397.   { "destructor",        s_text_Mach_O,    7    },
  398.   { "fvmlib_init0",        s_text_Mach_O,    8    },
  399.   { "fvmlib_init1",        s_text_Mach_O,    9    },
  400.   /* data sub-segments */
  401.   { "static_data",        s_data_Mach_O,    1    },
  402.   { "objc_class",        s_data_Mach_O,    2    },
  403.   { "objc_meta_class",        s_data_Mach_O,    3    },
  404.   { "objc_string_object",    s_data_Mach_O,    4    },
  405.   { "objc_protocol",        s_data_Mach_O,    5    },
  406.   { "objc_cat_cls_meth",    s_data_Mach_O,    6    },
  407.   { "objc_cat_inst_meth",    s_data_Mach_O,    7    },
  408.   { "objc_cls_meth",        s_data_Mach_O,    8    },
  409.   { "objc_inst_meth",        s_data_Mach_O,    9    },
  410.   { "objc_message_refs",    s_data_Mach_O,    10    },
  411.   { "objc_selector_refs",    s_data_Mach_O,    10    },
  412.   { "objc_cls_refs",        s_data_Mach_O,    11    },
  413.   { "objc_class_names",        s_data_Mach_O,    12    },
  414.   { "objc_module_info",        s_data_Mach_O,    13    },
  415.   { "objc_symbols",        s_data_Mach_O,    14    },
  416.   { "objc_category",        s_data_Mach_O,    15    },
  417.   { "objc_meth_var_types",    s_data_Mach_O,    16    },
  418.   { "objc_class_vars",        s_data_Mach_O,    17    },
  419.   { "objc_instance_vars",    s_data_Mach_O,    18    },
  420.   { "objc_meth_var_names",    s_data_Mach_O,    19    },
  421.   { "objc_selector_strs",    s_data_Mach_O,    20    },
  422. #endif
  423.   { NULL}    /* end sentinel */
  424. };
  425.  
  426. static void
  427. pobegin()
  428. {
  429.   char *    errtxt;        /* error text */
  430.   const pseudo_typeS * pop;
  431.  
  432.   po_hash = hash_new();
  433.   errtxt = "";            /* OK so far */
  434.   for (pop=(pseudo_typeS *)potable; pop->poc_name && !*errtxt; pop++)
  435.     {
  436.       errtxt = hash_insert (po_hash, pop->poc_name, (char *)pop);
  437.     }
  438.  
  439.   for(pop=md_pseudo_table; pop->poc_name && !*errtxt; pop++)
  440.       errtxt = hash_insert (po_hash, pop->poc_name, (char *)pop);
  441.  
  442.   if (*errtxt)
  443.     {
  444. #ifdef NeXT
  445.       as_fatal ("error constructing pseudo-op table (%s)", errtxt);
  446. #else !defined(NeXT)
  447.       as_fatal ("error constructing pseudo-op table");
  448. #endif NeXT
  449.     }
  450. }                /* pobegin() */
  451.  
  452. /*
  453.  * The NeXT version of: read_a_source_file()
  454.  *
  455.  * This differs from the GNU version by taking the guts of the GNU
  456.  * read_a_source_file() (with the outer most loop removed) and renaming it
  457.  * parse_a_buffer().  With the NeXT version of read_a_source file simply
  458.  * containing that outer loop and a call to parse_a_buffer().  This is done
  459.  * So that expand_macro() and parse_line_comment() can call parse_a_buffer()
  460.  * with the buffers they create.
  461.  */
  462. void
  463. read_a_source_file (buffer)
  464. char *buffer;    /* 1st character of each buffer of lines is here. */
  465. {
  466.     cond_stateS    starting_cond_state;
  467.     short starting_if_depth;
  468.  
  469.     extern char *physical_input_file;
  470.     symbolS *symbolP;
  471.  
  472.     starting_cond_state = the_cond_state;
  473.     starting_if_depth = if_depth;
  474.  
  475.     /* Do not change segments or subsegments if this is a .include */
  476.     if(doing_include == FALSE){
  477.         subseg_new(SEG_TEXT, 0);
  478.         /*
  479.          * If the -g flag is present generate the lead stabs for this
  480.          * physical file that is not an include file.  Each physical file's
  481.          * stabs are enclosed by a pair of source name stabs, N_SO, (one at
  482.          * the begining of the file with the name of the file and one at the
  483.          * end with the name "").  This is seen by nm(1) as:
  484.          *     00000000 - 01 0000    SO {standard input}
  485.          *  ...
  486.          *    00000020 - 01 0000    SO
  487.          * To make the debugger work line numbers stabs, N_SLINE, must be
  488.          * contained "in a function" (after a function stab, N_FUN).  To
  489.          * make a function stab work it must have a type number.  Since type
  490.          * numbers 1 and 2 (the 1 in "int:t1=..." and the 2 in "char:t2=..."
  491.          * are "magic" to the debugger we use type 3 for the types of the
  492.          * function stabs we generate for each text label (see the routine
  493.          * make_stab_for_symbol() in symbols.c).  So at lead stabs at the
  494.          * begining of each physical file include three type stabs, L_LSYM
  495.          * with the correct symbol name.  The since we must have the types
  496.          * 1 and 2 they are just what the 'C' would produce but we don't
  497.          * use them.  Type 3 is the void type like the 'C' compiler would
  498.          * produce which we use for the function stabs' type.  These three
  499.          * look like this to nm(1):
  500.          *    00000000 - 00 0000  LSYM int:t1=r1;-2147483648;2147483647;
  501.          *    00000000 - 00 0000  LSYM char:t2=r2;0;127;
  502.          *    00000000 - 00 0000  LSYM void:t3=3
  503.          *
  504.          * Then for each text label we see, make_stab_for_symbol() will
  505.          * generate a stab like this (for the example lable _main):
  506.          *    00000000 - 01 0007   FUN _main:F3
  507.          * where the 'F' in F3 is an upper case 'F' for global labels and
  508.          * a lower case 'f' for non globals.
  509.          *
  510.          * Then for each instruction we assemble in the text we generate
  511.          * a line number, S_LINE, stab (see md_assembler in m68k.c, m88k.c
  512.          * etc).  These look like:
  513.          *    00000000 - 01 0008 SLINE
  514.          * where the 0008 is the line number.
  515.          */
  516.         if(flagseen['g']){
  517.         symbolP = symbol_new(
  518.             physical_input_file,
  519.             100 /* N_SO */,
  520.             seg_n_sect(now_seg, now_subseg),
  521.             0,
  522.             obstack_next_free(&frags) - frag_now->fr_literal,
  523.             frag_now);
  524.         symbolP = symbol_new(
  525.             "int:t1=r1;-2147483648;2147483647;",
  526.             128 /* N_LSYM */,
  527.             0,0,0,
  528.             &zero_address_frag);
  529.         symbolP = symbol_new(
  530.             "char:t2=r2;0;127;",
  531.             128 /* N_LSYM */,
  532.             0,0,0,
  533.             &zero_address_frag);
  534.         symbolP = symbol_new(
  535.             "void:t3=3",
  536.             128 /* N_LSYM */,
  537.             0,0,0,
  538.             &zero_address_frag);
  539.         }
  540.     }
  541.     else{
  542.         /*
  543.          * If we are now reading an include file we will bracket it's
  544.          * stabs with a pair of:
  545.          *    00000010 - 01 0000   SOL include_file
  546.          *    ...
  547.          *    0000001c - 01 0000   SOL previous_file
  548.          * We generate the first N_SOL here and the one for the
  549.          * previous_file in s_include() in read.c.
  550.          *
  551.          * CAVAT: This will only work if the include file starts off in the
  552.          * (__TEXT,__text) sections and ends in the (__TEXT,__text) section.
  553.          */
  554.         if(flagseen['g'] && now_seg == SEG_TEXT && now_subseg == 0){
  555.         symbolP = symbol_new(
  556.             physical_input_file,
  557.             132 /* N_SOL */,
  558.             seg_n_sect(now_seg, now_subseg),
  559.             0,
  560.             obstack_next_free(&frags) - frag_now->fr_literal,
  561.             frag_now);
  562.         }
  563.     }
  564.  
  565.     while((buffer_limit = input_scrub_next_buffer(&buffer)) != NULL)
  566.         parse_a_buffer(buffer);
  567.  
  568.     if(the_cond_state.the_cond != starting_cond_state.the_cond ||
  569.        the_cond_state.ignore != starting_cond_state.ignore||
  570.        if_depth != starting_if_depth)
  571.         as_warn("file contains unmatched .ifs or .elses");
  572.  
  573.     if(doing_include == FALSE){
  574.         /* See the comment at the top of this routine for a description of
  575.            what is going on here */
  576.         subseg_new(SEG_TEXT, 0);
  577.         if(flagseen['g']){
  578.         (void)symbol_new(
  579.             "",
  580.             100 /* N_SO */,
  581.             seg_n_sect(now_seg, now_subseg),
  582.             0,
  583.             obstack_next_free(&frags) - frag_now->fr_literal,
  584.             frag_now);
  585.         }
  586.     }
  587. }
  588.  
  589. /*
  590.  * NeXT verion of parse_a_buffer() operates on a buffer of lines.  It drives the
  591.  * parsing of lines of assembly code.  The lines are assumed to be "well formed"
  592.  * assembly so the syntax recognized in here is that produced by the output of
  593.  * the assembly preprocessor (app) or by the compiler when it produces a file
  594.  * that starts with "#NO_APP\n".  A "well formed" assembly is lines with exactly
  595.  * zero or one leading "well formed space character" (' ', '\t' or '\f')
  596.  * followed by lines of:
  597.  *    zero or more lables (a name or a digit followed by a colon)
  598.  *        each followed by zero or one "well formed space character"
  599.  *    exactly one of the following followed by a logicial end of line:
  600.  *            a pseudo opcode
  601.  *            followed by zero or one space (' ') characters and it's
  602.  *            arguments (the space is required when the first
  603.  *            character of the first argument could be part of a name)
  604.  *            a macro to be expanded
  605.  *            a machine opcode
  606.  *            a null statement
  607.  *        an assignment to a symbol
  608.  *            a full line comment (in the case of "well formed" assembly it
  609.  *                     must be "#APP\n" of a collection of lines
  610.  *                     wrapped in "#APP\n ... #NO_APP\n")
  611.  * 
  612.  * input:
  613.  *    buffer        pointer to the start of the buffer of lines
  614.  *            (passed as an argument)
  615.  *    buffer_limit    pointer to the end of the buffer of lines, that is the
  616.  *            the character it points to is NOT part of the buffer
  617.  *            (buffer_limit is declared as a static to this file)
  618.  *
  619.  * Assumptions about the buffer of lines:
  620.  *    buffer[-1] == '\n'    as done in input-scrub.c with the cpp macro
  621.  *                BEFORE_STRING ("\n")
  622.  *    buffer_limit[-1] == '\n' also as done in input-scrub.c which handles
  623.  *                partial lines internally to itself and always
  624.  *                passes back a buffer of complete lines.
  625.  *
  626.  * input/output: (for other parsing routines)
  627.  *    input_line_pointer    pointer to the next thing in the buffer after
  628.  *                 what has been recognized (a global)
  629.  */
  630. static
  631. void
  632. parse_a_buffer(buffer)
  633. char *buffer;
  634. {
  635.     char c;        /* contains the first non-space character the current
  636.                word used to figure out what it is */
  637.     char *s;        /* points to a name with character after the name
  638.                replaced with a '\0' so it is a 'C' string */
  639.     char after_name;    /* contains that first character after a name that
  640.                got replaced with a '\0' */
  641.     char *after_name_pointer;/* points to the end of the name where the '\0' is
  642.                for error use only */
  643.     char end_of_line;    /* contains an end of line character that got replaced
  644.                with a '\0' */
  645.     char *start_of_line;/* points to the locical start of line we're parsing,
  646.                used only for macro expansion */
  647.     pseudo_typeS *pop;    /* pointer to a pseudo op stucture returned by
  648.                hash_find(po_hash, s+1) to determine if it is one */
  649.     char *the_macro;    /* pointer to a macro name returned by
  650.                hash_find(ma_hash, s) to determine if it is one */
  651.     int digit_value;    /* the value of a digit label as an integer, 1: == 1 */
  652.  
  653.     /* since this is a buffer of full lines it must end in a new line */
  654.     know(buffer_limit[-1] == '\n');
  655.  
  656.     input_line_pointer = buffer;
  657.  
  658.     /* while we have more of this buffer to parse keep parsing */
  659.     while(input_line_pointer < buffer_limit){
  660.         /*
  661.          * At the top of this loop we know that we just parsed a label or we
  662.          * are at the beginning of a logical line (since their can be more
  663.          * than one label on a line).  start_of_line is only used by
  664.          * expand_macro()
  665.          */
  666.         start_of_line = input_line_pointer;
  667.  
  668.         /*
  669.          * If we are not counting lines (as in the case when called by
  670.          * expand_macro() ) and we just previously scaned over a newline
  671.          * (a physical end of line) bump the line counters (see the comments
  672.          * at the head of this routine about "assumptions about the buffer"
  673.          * and why it is safe to index input_line_pointer by -1.
  674.          */
  675.         if(count_lines == TRUE && input_line_pointer[-1] == '\n')
  676.         bump_line_counters ();
  677.  
  678.         /*
  679.          * We expect a "well-formed" assembler statement.  This means it was
  680.          * processed by app or produced by a compiler where the file started
  681.          * with a leading "#APP\n".  A "well-formed" statement allows zero
  682.          * or one leading white space characters.
  683.          */
  684.         c = *input_line_pointer;
  685.         input_line_pointer++;
  686.         if(c == '\t' || c == ' ' || c=='\f'){
  687.         c = *input_line_pointer;
  688.         input_line_pointer++;
  689.         }
  690.         know(c != ' ');    /* No further leading whitespace. */
  691.         /*
  692.          * c contains the 1st significant character, *input_line_pointer
  693.          * points after that character.
  694.          */
  695.  
  696.         /*
  697.          * look for the begining of a name which could be one of the
  698.          * following assembly statements:
  699.          *    A pseudo opcode and locical end of line
  700.          *    A macro to be expanded and locical end of line
  701.          *    A machine opcode and locical end of line
  702.          *    A user-defined label (name not digit)(no end of line needed)
  703.          * At NeXT labels can be enclosed in ""'s so that Objective-C like
  704.          * names (with spaces and colons) can be part of a name, the
  705.          * routine get_symbol_end() know about this.
  706.          */
  707.         if(is_name_beginner(c) || c == '"'){
  708.         if( c == '"')
  709.             s = input_line_pointer -- ;
  710.         else
  711.           s = -- input_line_pointer;
  712.         after_name = get_symbol_end(); /* name's delimiter */
  713.         after_name_pointer = input_line_pointer;
  714.         /*
  715.          * after_name is the character after symbol.  That character's
  716.          * place in the input line is now '\0',done by get_symbol_end().
  717.          * s points to the beginning of the symbol (in the case of a
  718.          * pseudo-op, *s == '.').  *input_line_pointer == '\0' where
  719.          * after_name was.  after_name_pointer is recorded so it their
  720.          * is an error after the line has been restored the '\0' can
  721.          * be reset and the name printed.
  722.          */
  723.  
  724.         /*
  725.          * Look for a name that should be a pseudo op.  That is it is
  726.          * not a user defined label or an assignment to a symbol name.
  727.          * This must be done so such thing as ".foo:" and ".bar=1" are
  728.          * not mistaken for illegal pseudo ops and that something like
  729.          * ".long: .long 1" creates a symbol named ".long".
  730.          */
  731.         if(*s == '.' &&
  732.            (after_name != ':' &&
  733.            (after_name != '=' && input_line_pointer[1] != '=') ) ){
  734.             /*
  735.              * Lookup what should be a pseudo op and then restore the
  736.              * line.
  737.              */
  738.             pop = (pseudo_typeS *)hash_find(po_hash, s+1);
  739.             *input_line_pointer = after_name;
  740.  
  741.             /*
  742.              * A pseudo op must be followed by character that is not
  743.              * part of a name so it can be parsed.  If their is a first
  744.              * argument that could start with a character in a name then
  745.              * one "well formed space" (space or a tab) must follow the
  746.              * pseudo op (otherwise the space is optional).
  747.              */
  748.             if(after_name == ' ' || after_name == '\t')
  749.             input_line_pointer++;
  750.  
  751.             /*
  752.              * Now the current state of the line is the after_name has
  753.              * been placed back in the line (the line is restored) and
  754.              * input_line_pointer is at the start of the first argument
  755.              * of the pseudo op (if any).
  756.              */
  757.             if(the_cond_state.ignore){
  758.             /*
  759.              * When ignoring a block of code during conditional
  760.              * assembly we can't ignore .if, .else, and .endif
  761.              * pseudo ops.
  762.              */
  763.             if(pop != NULL &&
  764.                    ( ((int *)pop->poc_handler == (int *)s_if) ||
  765.                  ((int *)pop->poc_handler == (int *)s_elseif) ||
  766.                  ((int *)pop->poc_handler == (int *)s_else) ||
  767.                  ((int *)pop->poc_handler == (int *)s_endif) ) )
  768.                 (*pop->poc_handler)(pop->poc_val);
  769.             else
  770.                 totally_ignore_line();
  771.             }
  772.             else if(macro_name){
  773.             /*
  774.              * When defining a macro we can't ignore .endmacro
  775.              * pseudo ops.
  776.              */
  777.             if(pop != NULL &&
  778.                (int *)pop->poc_handler == (int *)s_endmacro)
  779.                 (*pop->poc_handler)(pop->poc_val);
  780.             else
  781.                 add_to_macro_definition(start_of_line);
  782.             }
  783.             else{
  784.             if(pop != NULL)
  785.                 (*pop->poc_handler)(pop->poc_val);
  786.             else{
  787.                 after_name = *after_name_pointer;
  788.                 *after_name_pointer = '\0';
  789.                 /*
  790.                  * If macros are on see if this is a use of a macro
  791.                  * otherwise it is an unknown pseudo op.
  792.                  */
  793.                 if(macros_on == TRUE &&
  794.                    (the_macro = hash_find(ma_hash, s)) != NULL){
  795.                 *after_name_pointer = after_name;
  796.                 expand_macro(the_macro);
  797.                 }
  798.                 else{
  799.                 as_warn ("Unknown pseudo-op: %s", s);
  800.                 *after_name_pointer = after_name;
  801.                 ignore_rest_of_line();
  802.                 }
  803.             }
  804.             }
  805.             continue;
  806.  
  807.         } /* if(*s == '.' && ... ) */
  808.  
  809.         /*
  810.          * If we are in a conditional and the state is that we are now
  811.          * not including lines to be assembled then ignore the line.
  812.          */
  813.         if(the_cond_state.ignore){
  814.             *input_line_pointer = after_name;
  815.             totally_ignore_line();
  816.         }
  817.         /*
  818.          * If we are in the state of defining a macro then take the line
  819.          * for the macro definition.
  820.          */
  821.         else if(macro_name != NULL){
  822.             *input_line_pointer = after_name;
  823.             add_to_macro_definition(start_of_line);
  824.             }
  825.         /*
  826.          * Look for a user defined label.
  827.          */
  828.         else if(after_name == ':'){
  829.             colon(s);
  830. #ifdef I860
  831.             /*
  832.              * Intel :: feature, which makes the label global if
  833.              * followed by two "::"'s  . This is ifdef'ed in so their
  834.              * is no else cause thus the slightly odd logic.
  835.              */
  836.             if(input_line_pointer[1] == ':'){
  837.             struct symbol *symbolP;
  838.  
  839.             symbolP = symbol_find_or_make(s);
  840.             symbolP->sy_type |= N_EXT; /* make symbol name global */
  841.             *input_line_pointer = ':'; /* Restore first ':' */
  842.             input_line_pointer++;     /* step over first ':' */
  843.             }
  844. #endif I860
  845.             /* put ':' back for error messages and step over it */
  846.             *input_line_pointer = ':';
  847.             input_line_pointer++;
  848.             SKIP_WHITESPACE();
  849.         }
  850.         /*
  851.          * Parse the assignment to a symbol.  The syntax for this is
  852.          * <symbol><equal><expression> where <equal> is either "=" or
  853.          * "?=" where '?' is any character that is not part of a symbol.
  854.          * This allows things like: "x=1" "x =1" "x==1" "x+=1" "x!=1"
  855.          * "x@=1" which all set x to one.  This should be cleaned up.
  856.          */
  857.         else if(after_name == '=' || input_line_pointer[1] == '='){
  858.             equals(s);
  859.             demand_empty_rest_of_line();
  860.         }
  861.         /*
  862.          * If macros are on see if this is a use of a macro.
  863.          */
  864.         else if(macros_on == TRUE &&
  865.             (the_macro = hash_find(ma_hash, s)) != NULL){
  866.             *input_line_pointer = after_name;
  867.             expand_macro(the_macro);
  868.         }
  869.         /*
  870.          * Now assume it is a machine instruction and if not it
  871.          * will be handled as an error.  Machine instructions must be
  872.          * one to a line.
  873.          */
  874.         else{
  875.             *input_line_pointer = after_name;
  876.             while(is_end_of_line[*input_line_pointer] == FALSE)
  877.             input_line_pointer ++;
  878.             end_of_line = *input_line_pointer;
  879.             *input_line_pointer = '\0';
  880.             md_assemble(s);
  881.             *input_line_pointer = end_of_line;
  882.             input_line_pointer++;
  883.         }
  884.         /*
  885.          * At this point we have parsed all things that could have
  886.          * started with a name.  Since one of these things (user defined
  887.          * lables could appear more than once on a line we do a continue
  888.          * here and start parsing as if at the begining of another
  889.          * logicial line.
  890.          */
  891.         continue;
  892.  
  893.         } /* if(is_name_beginner(c) || c == '"') */
  894.  
  895.         /* empty statement */
  896.         if(is_end_of_line[c])
  897.         continue;
  898.  
  899.         /*
  900.          * If we are in a conditional and the state is that we are now
  901.          * not including lines to be assembled then ignore the line.
  902.          */
  903.         if(the_cond_state.ignore){
  904.         totally_ignore_line();
  905.         continue;
  906.         }
  907.  
  908.         /*
  909.          * If we are in the state of defining a macro then take the line
  910.          * for the macro definition.
  911.          */
  912.         if(macro_name != NULL){
  913.         add_to_macro_definition(start_of_line);
  914.         continue;
  915.         }
  916.  
  917.         /* local label  ("4:") */
  918.         if(isdigit(c)){
  919.         digit_value = c - '0';
  920. #ifdef SUN_ASM_SYNTAX
  921.         if(*input_line_pointer == '$')
  922.             input_line_pointer++;
  923. #endif SUN_ASM_SYNTAX
  924.         if(*input_line_pointer++ == ':' ){
  925.             local_colon(digit_value);
  926.         }
  927.         else{
  928.             as_warn("Spurious digit %d.", digit_value);
  929.             input_line_pointer--;
  930.             ignore_rest_of_line();
  931.         }
  932.         continue;
  933.         }
  934.  
  935.         /*
  936.          * The only full line comment that should make it here is the first
  937.          * of the pair of "#APP\n ... #NO_APP\n" that the compiler uses to
  938.          * wrap around asm() statements.  If that is the case then
  939.          * parse_line_comment() creates a buffer with those lines in it and
  940.          * calls parse_a_buffer() with that buffer.  Then returns here
  941.          * skiping over that part of the current buffer.
  942.          */
  943.         if(c != '\0' && index(line_comment_chars, c) != NULL){
  944.         parse_line_comment(&buffer);
  945.         continue;
  946.         }
  947.  
  948.         as_warn("Junk character %d.",c);
  949.         ignore_rest_of_line();
  950.  
  951.     } /* while(input_line_pointer < buffer_limit) */
  952. }
  953.  
  954. /*
  955.  * parse_line_comment() parses a line comment for parse_a_buffer().  Since
  956.  * parse_a_buffer() only operates on "well formed" assembly the only legal
  957.  * line comment that should appear is a "#APP\n ... #NO_APP\n" pair which
  958.  * tells us to scrub the characters between them and then parse them.
  959.  */
  960. void
  961. parse_line_comment(buffer)
  962. char **buffer;
  963. {
  964.     char    *s;
  965.     char    *ends;
  966.  
  967.     char    *new_buf;
  968.     char    *new_tmp;
  969.     int        new_length;
  970.  
  971.     char    *tmp_buf;
  972.     char    *old_input_line_pointer;
  973.     char    *old_buffer_limit;
  974.  
  975.     extern char    *strstr();
  976.     extern char *scrub_string, *scrub_last_string;
  977.     extern int    scrub_from_string();
  978.     extern void    scrub_to_string();
  979.  
  980.     /* parse_a_buffer should never see any line comment if app is on */
  981.     know(preprocess == FALSE);
  982.  
  983.     s = input_line_pointer;
  984.     /* This must be a #APP\n line comment if not ignore it */
  985.     if(strncmp(s,"APP\n",4) != 0)
  986.         return;
  987.  
  988.     if(count_lines == TRUE)
  989.         bump_line_counters();
  990.     s += sizeof("APP\n") - 1;
  991.  
  992.     /*
  993.      * Search for the matching #NO_APP\n in this buffer, if it is found
  994.      * in this buffer the un-scrubed characters between the "#APP\n" and
  995.      * "#NO_APP\n" start where s is pointing to and end where ends is
  996.      * pointing to.
  997.      */
  998.     ends = strstr(s, "#NO_APP\n");
  999.  
  1000.     tmp_buf = NULL;
  1001.     if(ends == NULL){
  1002.         /* The matching #NO_APP\n for the #APP\n wasn't in this buffer. */
  1003.         int    tmp_len;
  1004.         int    num;
  1005.  
  1006.         /*
  1007.          * First create a temporary place (tmp_buf of size tmp_len) to
  1008.          * collect the un-scrubbed characters between the "#APP\n" and the
  1009.          * "#NO_APP\n" (or end of file) when we find it in some buffer.
  1010.          */
  1011.         tmp_len = buffer_limit - s;
  1012.         tmp_buf = xmalloc(tmp_len);
  1013.  
  1014.         /*
  1015.          * Copy the end of the buffer that contains the first part of
  1016.          * the un-scrubbed contents starting just after the "#APP\n".
  1017.          * This is so the the current buffer (buffer) can be used to
  1018.          * collect the the rest of the un-scrubbed contents and to find
  1019.          * the matching "#NO_APP\n".
  1020.          */
  1021.         bcopy(s, tmp_buf, tmp_len);
  1022.  
  1023.         /*
  1024.          * This loop collects the remaining un-scrubed contents between
  1025.          * "#APP\n" and the "#NO_APP\n" into tmp_buf (adjusting tmp_len)
  1026.          * and looks for the matching "#NO_APP\n".
  1027.          */
  1028.         do{
  1029.         buffer_limit = input_scrub_next_buffer(buffer);
  1030.         /*
  1031.          * We treat runing into the end of the file as if it was the
  1032.          * "#NO_APP" we were looking for.
  1033.          */
  1034.         if(buffer_limit == NULL)
  1035.             break;
  1036.  
  1037.         ends = strstr(*buffer, "#NO_APP\n");
  1038.         if(ends != NULL)
  1039.             num = ends - *buffer;
  1040.         else
  1041.             num = buffer_limit - *buffer;
  1042.  
  1043.         tmp_buf = xrealloc(tmp_buf, tmp_len + num);
  1044.         bcopy(*buffer, tmp_buf + tmp_len, num);
  1045.         tmp_len += num;
  1046.         }while(ends == NULL);
  1047.  
  1048.         /*
  1049.          * Now set up buffer, buffer_limit and input_line_pointer be past
  1050.          * all the characters of the "#APP\n ... #NO_APP\n" set so that
  1051.          * when we return parsing will be picked up from their.
  1052.          */
  1053.         if(ends != NULL)
  1054.         input_line_pointer = ends + sizeof("#NO_APP\n") - 1;
  1055.         else{
  1056.         input_line_pointer = *buffer;
  1057.         buffer_limit = *buffer;
  1058.         }
  1059.  
  1060.         /*
  1061.          * Now set s to the start, and ends to the end of the un-scrubed
  1062.          * contents of the collected characters between the "#APP\n" and
  1063.          * "#NO_APP\n" pair.
  1064.          */
  1065.         s = tmp_buf;
  1066.         ends = s + tmp_len;
  1067.     }
  1068.     else{
  1069.         /*
  1070.          * The matching "#NO_APP\n" was in the buffer as we were called so
  1071.          * s is the start, and ends is the end of the un-scrubed contents
  1072.          * of the characters between the "#APP\n" and "#NO_APP\n" pair.
  1073.          * Now to set up buffer, buffer_limit and input_line_pointer be past
  1074.          * all the characters of the "#APP\n ... #NO_APP\n" set so that
  1075.          * when we return parsing will be picked up from their all that has
  1076.          * to be done is move the input_line_pointer past the "#NO_APP\n".
  1077.          */
  1078.         input_line_pointer = ends + sizeof("#NO_APP\n") - 1;
  1079.     }
  1080.  
  1081.     /*
  1082.      * Now that we have the un-scrubed characters beween s and ends setup
  1083.      * to scrub them into a new buffer (new_buf of size new_length to
  1084.      * new_tmp).
  1085.      */
  1086.     new_length = 100;
  1087.     new_buf = xmalloc(new_length);
  1088.     new_tmp = new_buf;
  1089.     *new_tmp++ = '\n'; /* place leading \n in buffer for parse_a_buffer */
  1090.  
  1091.     scrub_string = s;
  1092.     scrub_last_string = ends;
  1093.     for(;;){
  1094.         int c;
  1095.  
  1096.         c = do_scrub_next_char(scrub_from_string, scrub_to_string);
  1097.         if(c == EOF)
  1098.         break;
  1099.         *new_tmp++ = c;
  1100.         if(new_tmp == new_buf + new_length){
  1101.         new_buf = xrealloc(new_buf, new_length + 100);
  1102.         new_tmp = new_buf + new_length;
  1103.         new_length += 100;
  1104.         }
  1105.     }
  1106.     *new_tmp = '\n'; /* place trailing \n in buffer for parse_a_buffer */
  1107.  
  1108.     /*
  1109.      * If we used a temporary buffer to collect the un-scrubbed characters
  1110.      * it is no longer needed and can be free()'ed.
  1111.      */
  1112.     if(tmp_buf != NULL)
  1113.         free(tmp_buf);
  1114.  
  1115.     /*
  1116.      * Now we are ready to recursively call parse_a_buffer() with our buffer
  1117.      * of scrubed characters.  So save the state of parse_a_buffer() and set
  1118.      * it up with our buffer of scrubed characters.
  1119.      */
  1120.     old_input_line_pointer = input_line_pointer;
  1121.     old_buffer_limit = buffer_limit;
  1122.  
  1123.     input_line_pointer = new_buf;
  1124.     buffer_limit = new_tmp;
  1125.     parse_a_buffer(new_buf);
  1126.  
  1127.     /*
  1128.      * Free the buffer that held the scrubbed characters
  1129.      */
  1130.     free(new_buf);
  1131.  
  1132.     /*
  1133.      * After coming back from our recursive call parse_a_buffer() we want 
  1134.      * resume parsing after the "#NO_APP\n".  So bump the line counters
  1135.      * for the "#NO_APP\n" and restore the state so we can return to
  1136.      * parse_a_buffer().
  1137.      */
  1138.     if(count_lines == TRUE)
  1139.         bump_line_counters();
  1140.     input_line_pointer = old_input_line_pointer;
  1141.     buffer_limit = old_buffer_limit;
  1142.  
  1143.     return;
  1144. }
  1145.  
  1146. void
  1147. s_abort()
  1148. {
  1149. #ifdef NeXT
  1150.     char *p;
  1151.  
  1152.     p = input_line_pointer;
  1153.     while(is_end_of_line[*p] == FALSE)
  1154.         p++;
  1155.     *p = '\0';
  1156.     
  1157.     as_fatal(".abort %s detected.  Assembly stopping.", input_line_pointer);
  1158. #else NeXT
  1159.     as_fatal(".abort detected.  Abandoning ship.");
  1160. #endif NeXT
  1161. }
  1162.  
  1163. void
  1164. s_align()
  1165. {
  1166.     register int temp;
  1167.     register long int temp_fill;
  1168. #ifdef xRISC
  1169.     char *thisfrag;
  1170.     int dot;
  1171. #endif
  1172.  
  1173.     temp = get_absolute_expression ();
  1174. #define MAX_ALIGNMENT (15)
  1175.     if ( temp > MAX_ALIGNMENT )
  1176.         as_warn("Alignment too large: %d. assumed.", temp = MAX_ALIGNMENT);
  1177.     else if ( temp < 0 ) {
  1178.         as_warn("Alignment negative. 0 assumed.");
  1179.         temp = 0;
  1180.     }
  1181.     if ( *input_line_pointer == ',' ) {
  1182.         input_line_pointer ++;
  1183.         temp_fill = get_absolute_expression ();
  1184.     } else
  1185.         temp_fill = 0;
  1186. #ifdef xRISC
  1187.     /* grow the current frag and plop in the fill as needed to the align */
  1188.     if(temp != 0){
  1189.         dot = obstack_next_free(&frags) - frag_now->fr_literal;
  1190.         while((dot & ((1 << temp) - 1)) != 0){
  1191.         thisfrag = frag_more(1);
  1192.         *thisfrag = temp_fill;
  1193.         dot = obstack_next_free(&frags) - frag_now->fr_literal;
  1194.         }
  1195.     }
  1196. #else
  1197.     /* Only make a frag if we HAVE to. . . */
  1198.     if ( temp && ! need_pass_2 )
  1199.         frag_align (temp, (int)temp_fill);
  1200. #endif
  1201. #ifdef Mach_O
  1202.     set_section_align(temp);
  1203. #endif
  1204.     demand_empty_rest_of_line();
  1205. }
  1206.  
  1207. void
  1208. s_comm()
  1209. {
  1210.     register char *name;
  1211.     register char c;
  1212.     register char *p;
  1213.     register int temp;
  1214.     register symbolS *    symbolP;
  1215.  
  1216. #ifdef NeXT
  1217.     if( * input_line_pointer == '"')
  1218.       name = input_line_pointer + 1;
  1219.     else
  1220.       name = input_line_pointer;
  1221. #else !defined(NeXT)
  1222.     name = input_line_pointer;
  1223. #endif NeXT
  1224.     c = get_symbol_end();
  1225.     /* just after name is now '\0' */
  1226.     p = input_line_pointer;
  1227.     *p = c;
  1228.     SKIP_WHITESPACE();
  1229.     if ( * input_line_pointer != ',' ) {
  1230.         as_warn("Expected comma after symbol-name");
  1231.         ignore_rest_of_line();
  1232.         return;
  1233.     }
  1234.     input_line_pointer ++; /* skip ',' */
  1235.     if ( (temp = get_absolute_expression ()) < 0 ) {
  1236.         as_warn(".COMMon length (%d.) <0! Ignored.", temp);
  1237.         ignore_rest_of_line();
  1238.         return;
  1239.     }
  1240.     *p = 0;
  1241.     symbolP = symbol_find_or_make (name);
  1242.     *p = c;
  1243.     if (   (symbolP -> sy_type & N_TYPE) != N_UNDF ||
  1244.  symbolP -> sy_other != 0 || symbolP -> sy_desc != 0) {
  1245.         as_warn( "Ignoring attempt to re-define symbol");
  1246.         ignore_rest_of_line();
  1247.         return;
  1248.     }
  1249.     if (symbolP -> sy_value) {
  1250.         if (symbolP -> sy_value != temp)
  1251.             as_warn( "Length of .comm \"%s\" is already %d. Not changed to %d.",
  1252.  symbolP -> sy_name, symbolP -> sy_value, temp);
  1253.     } else {
  1254.         symbolP -> sy_value = temp;
  1255.         symbolP -> sy_type |= N_EXT;
  1256.     }
  1257.     know( symbolP -> sy_frag == &zero_address_frag );
  1258.     demand_empty_rest_of_line();
  1259. }
  1260.  
  1261. void
  1262. s_data()
  1263. {
  1264.     register int temp;
  1265.  
  1266.     temp = get_absolute_expression ();
  1267.     subseg_new (SEG_DATA, (subsegT)temp);
  1268.     demand_empty_rest_of_line();
  1269. }
  1270.  
  1271. void
  1272. s_desc()
  1273. {
  1274.     register char *name;
  1275.     register char c;
  1276.     register char *p;
  1277.     register symbolS *    symbolP;
  1278.     register int temp;
  1279.  
  1280.     /*
  1281.      * Frob invented at RMS' request. Set the n_desc of a symbol.
  1282.      */
  1283. #ifdef NeXT
  1284.     if( * input_line_pointer == '"')
  1285.       name = input_line_pointer + 1;
  1286.     else
  1287.       name = input_line_pointer;
  1288. #else !defined(NeXT)
  1289.     name = input_line_pointer;
  1290. #endif NeXT
  1291.     c = get_symbol_end();
  1292.     p = input_line_pointer;
  1293.     symbolP = symbol_table_lookup (name);
  1294.     * p = c;
  1295.     SKIP_WHITESPACE();
  1296.     if ( * input_line_pointer != ',' ) {
  1297.         *p = 0;
  1298.         as_warn("Expected comma after name \"%s\"", name);
  1299.         *p = c;
  1300.         ignore_rest_of_line();
  1301.     } else {
  1302.         input_line_pointer ++;
  1303.         temp = get_absolute_expression ();
  1304.         *p = 0;
  1305.         symbolP = symbol_find_or_make (name);
  1306.         *p = c;
  1307.         symbolP -> sy_desc = temp;
  1308.     }
  1309.     demand_empty_rest_of_line();
  1310. }
  1311.  
  1312. void
  1313. s_file()
  1314. {
  1315.     register char *s;
  1316.     int    length;
  1317.  
  1318.     /* Some assemblers tolerate immediately following '"' */
  1319.     if ( s = demand_copy_string( & length ) ) {
  1320. #ifdef NeXT
  1321.         SKIP_WHITESPACE();
  1322.         if(*input_line_pointer >= '0' && *input_line_pointer <= '9'){
  1323.             while(*input_line_pointer >= '0' &&
  1324.                   *input_line_pointer <= '9')
  1325.                   input_line_pointer++;
  1326.         }
  1327. #endif NeXT
  1328.         new_logical_line (s, -1);
  1329.         demand_empty_rest_of_line();
  1330.  
  1331. #ifdef NeXT    /* generate stabs for debugging assembly code */
  1332.         /* See the comments about stabs in read_a_source_file()
  1333.            for a description of what is going on here */
  1334.         if(flagseen['g'] && now_seg == SEG_TEXT && now_subseg == 0){
  1335.               extern unsigned int logical_input_file;
  1336.           struct symbol *symbolP;
  1337.  
  1338.             symbolP = symbol_new(
  1339.                 logical_input_file,
  1340.                 132 /* N_SOL */,
  1341.                 seg_n_sect(now_seg, now_subseg),
  1342.                 0,
  1343.                 obstack_next_free(&frags) - frag_now->fr_literal,
  1344.                 frag_now);
  1345.         }
  1346. #endif NeXT    /* generate stabs for debugging assembly code */
  1347.     }
  1348. }
  1349.  
  1350. void
  1351. s_fill()
  1352. {
  1353.     long int temp_repeat;
  1354.     long int temp_size;
  1355.     register long int temp_fill;
  1356.     char    *p;
  1357.  
  1358.     if ( get_absolute_expression_and_terminator(& temp_repeat) != ',' ) {
  1359.         input_line_pointer --; /* Backup over what was not a ','. */
  1360.         as_warn("Expect comma after rep-size in .fill");
  1361.         ignore_rest_of_line();
  1362.         return;
  1363.     }
  1364.     if ( get_absolute_expression_and_terminator( & temp_size) != ',' ) {
  1365.           input_line_pointer --; /* Backup over what was not a ','. */
  1366.           as_warn("Expected comma after size in .fill");
  1367.           ignore_rest_of_line();
  1368.           return;
  1369.     }
  1370.     /*
  1371.      * This is to be compatible with BSD 4.2 AS, not for any rational reason.
  1372.      */
  1373. #define BSD_FILL_SIZE_CROCK_8 (8)
  1374.     if ( temp_size > BSD_FILL_SIZE_CROCK_8 ) {
  1375.         as_warn(".fill size clamped to %d.", BSD_FILL_SIZE_CROCK_8);
  1376.         temp_size = BSD_FILL_SIZE_CROCK_8 ;
  1377.     } if ( temp_size < 0 ) {
  1378.         as_warn("Size negative: .fill ignored.");
  1379.         temp_size = 0;
  1380. #ifdef NeXT
  1381.     /* bug fix, if md_number_to_chars() is called with something other than
  1382.      * 1,2 or 4 it calls abort().  So we don't let the size be something
  1383.      * like 3. Bug #13017.
  1384.      */
  1385.     } else if ( temp_size != 0 &&
  1386.             temp_size != 1 &&
  1387.             temp_size != 2 &&
  1388.             temp_size != 4 ) {
  1389.         as_warn("Repeat must be 0,1,2 or 4, .fill ignored");
  1390.         temp_size = 0;
  1391. #endif NeXT
  1392.     } else if ( temp_repeat <= 0 ) {
  1393.         as_warn("Repeat < 0, .fill ignored");
  1394.         temp_size = 0;
  1395.     }
  1396.     temp_fill = get_absolute_expression ();
  1397.     if ( temp_size && !need_pass_2 ) {
  1398.         p = frag_var (rs_fill, (int)temp_size, (int)temp_size, (relax_substateT)0, (symbolS *)0, temp_repeat, (char *)0);
  1399.         bzero (p, (int)temp_size);
  1400. /*
  1401.  * The magic number BSD_FILL_SIZE_CROCK_4 is from BSD 4.2 VAX flavoured AS.
  1402.  * The following bizzare behaviour is to be compatible with above.
  1403.  * I guess they tried to take up to 8 bytes from a 4-byte expression
  1404.  * and they forgot to sign extend. Un*x Sux.
  1405.  */
  1406. #define BSD_FILL_SIZE_CROCK_4 (4)
  1407.         md_number_to_chars (p, temp_fill, temp_size > BSD_FILL_SIZE_CROCK_4 ? BSD_FILL_SIZE_CROCK_4 : (int)temp_size);
  1408. /*
  1409.  * Note: .fill (),0 emits no frag (since we are asked to .fill 0 bytes)
  1410.  * but emits no error message because it seems a legal thing to do.
  1411.  * It is a degenerate case of .fill but could be emitted by a compiler.
  1412.  */
  1413.     }
  1414.     demand_empty_rest_of_line();
  1415. }
  1416.  
  1417. #ifdef DONTDEF
  1418. void
  1419. s_gdbbeg()
  1420. {
  1421.     register int temp;
  1422.  
  1423.     temp = get_absolute_expression ();
  1424.     if (temp < 0)
  1425.         as_warn( "Block number <0. Ignored." );
  1426.     else if (flagseen ['G'])
  1427.         gdb_block_beg ( (long int) temp, frag_now, (long int)(obstack_next_free(& frags) - frag_now -> fr_literal));
  1428.     demand_empty_rest_of_line ();
  1429. }
  1430.  
  1431. void
  1432. s_gdbblock()
  1433. {
  1434.     register int    position;
  1435.     int    temp;
  1436.  
  1437.     if (get_absolute_expression_and_terminator (&temp) != ',') {
  1438.         as_warn( "expected comma before position in .gdbblock");
  1439.         --input_line_pointer;
  1440.         ignore_rest_of_line ();
  1441.         return;
  1442.     }
  1443.     position = get_absolute_expression ();
  1444.     if (flagseen ['G'])
  1445.         gdb_block_position ((long int) temp, (long int) position);
  1446.     demand_empty_rest_of_line ();
  1447. }
  1448.  
  1449. void
  1450. s_gdbend()
  1451. {
  1452.     register int temp;
  1453.  
  1454.     temp = get_absolute_expression ();
  1455.     if (temp < 0)
  1456.         as_warn( "Block number <0. Ignored." );
  1457.     else if (flagseen ['G'])
  1458.         gdb_block_end ( (long int) temp, frag_now, (long int)(obstack_next_free(& frags) - frag_now -> fr_literal));
  1459.     demand_empty_rest_of_line ();
  1460. }
  1461.  
  1462. void
  1463. s_gdbsym()
  1464. {
  1465.     register char *name,
  1466.             *p;
  1467.     register char c;
  1468.     register symbolS *    symbolP;
  1469.     register int temp;
  1470.  
  1471.     name = input_line_pointer;
  1472.     c = get_symbol_end();
  1473.     p = input_line_pointer;
  1474.     symbolP = symbol_find_or_make (name);
  1475.     *p = c;
  1476.     SKIP_WHITESPACE();
  1477.     if ( * input_line_pointer != ',' ) {
  1478.         as_warn("Expected comma after name");
  1479.         ignore_rest_of_line();
  1480.         return;
  1481.     }
  1482.     input_line_pointer ++;
  1483.     if ( (temp = get_absolute_expression ()) < 0 ) {
  1484.         as_warn("Bad GDB symbol file offset (%d.) <0! Ignored.", temp);
  1485.         ignore_rest_of_line();
  1486.         return;
  1487.     }
  1488.     if (flagseen ['G'])
  1489.         gdb_symbols_fixup (symbolP, (long int)temp);
  1490.     demand_empty_rest_of_line ();
  1491. }
  1492.  
  1493. void
  1494. s_gdbline()
  1495. {
  1496.     int    file_number,
  1497.         lineno;
  1498.  
  1499.     if(get_absolute_expression_and_terminator(&file_number) != ',') {
  1500.         as_warn("expected comman after filenum in .gdbline");
  1501.         ignore_rest_of_line();
  1502.         return;
  1503.     }
  1504.     lineno=get_absolute_expression();
  1505.     if(flagseen['G'])
  1506.         gdb_line(file_number,lineno);
  1507.     demand_empty_rest_of_line();
  1508. }
  1509.  
  1510.  
  1511. void
  1512. s_gdblinetab()
  1513. {
  1514.     int    file_number,
  1515.         offset;
  1516.  
  1517.     if(get_absolute_expression_and_terminator(&file_number) != ',') {
  1518.         as_warn("expected comman after filenum in .gdblinetab");
  1519.         ignore_rest_of_line();
  1520.         return;
  1521.     }
  1522.     offset=get_absolute_expression();
  1523.     if(flagseen['G'])
  1524.         gdb_line_tab(file_number,offset);
  1525.     demand_empty_rest_of_line();
  1526. }
  1527. #endif    
  1528.  
  1529. void
  1530. s_globl()
  1531. {
  1532.     register char *name;
  1533.     register int c;
  1534.     register symbolS *    symbolP;
  1535.  
  1536.     do {
  1537. #ifdef NeXT
  1538.         if( * input_line_pointer == '"')
  1539.           name = input_line_pointer + 1;
  1540.         else
  1541.           name = input_line_pointer;
  1542. #else !defined(NeXT)
  1543.         name = input_line_pointer;
  1544. #endif NeXT
  1545.         c = get_symbol_end();
  1546.         symbolP = symbol_find_or_make (name);
  1547.         * input_line_pointer = c;
  1548.         SKIP_WHITESPACE();
  1549.         symbolP -> sy_type |= N_EXT;
  1550.         if(c==',') {
  1551.             input_line_pointer++;
  1552.             SKIP_WHITESPACE();
  1553.             if(*input_line_pointer=='\n')
  1554.                 c='\n';
  1555.         }
  1556.     } while(c==',');
  1557.     demand_empty_rest_of_line();
  1558. }
  1559.  
  1560. void
  1561. s_lcomm()
  1562. {
  1563.     register char *name;
  1564.     register char c;
  1565.     register char *p;
  1566.     register int temp;
  1567.     register symbolS *    symbolP;
  1568. #ifdef NeXT
  1569.     int align;
  1570.  
  1571.     if( * input_line_pointer == '"')
  1572.       name = input_line_pointer + 1;
  1573.     else
  1574.       name = input_line_pointer;
  1575. #else !defined(NeXT)
  1576.     name = input_line_pointer;
  1577. #endif NeXT
  1578.     c = get_symbol_end();
  1579.     p = input_line_pointer;
  1580.     *p = c;
  1581.     SKIP_WHITESPACE();
  1582.     if ( * input_line_pointer != ',' ) {
  1583.         as_warn("Expected comma after name");
  1584.         ignore_rest_of_line();
  1585.         return;
  1586.     }
  1587.     input_line_pointer ++;
  1588.     if ( (temp = get_absolute_expression ()) < 0 ) {
  1589.         as_warn("BSS length (%d.) <0! Ignored.", temp);
  1590.         ignore_rest_of_line();
  1591.         return;
  1592.     }
  1593. #define MAX_ALIGNMENT (15)
  1594. #ifdef NeXT
  1595.     align = 0;
  1596.     if ( *input_line_pointer == ',' ) {
  1597.         input_line_pointer ++;
  1598.         align = get_absolute_expression ();
  1599.         if ( align > MAX_ALIGNMENT ) {
  1600.         as_warn("Alignment too large: %d. assumed.", MAX_ALIGNMENT);
  1601.             align = MAX_ALIGNMENT;
  1602.         }
  1603.         else if ( align < 0 ) {
  1604.         as_warn("Alignment negative. 0 assumed.");
  1605.         align = 0;
  1606.         }
  1607.     }
  1608. #endif NeXT
  1609.     *p = 0;
  1610.     symbolP = symbol_find_or_make (name);
  1611.     *p = c;
  1612.     if (   symbolP -> sy_other == 0
  1613.         && symbolP -> sy_desc  == 0
  1614.         && (   (   symbolP -> sy_type  == N_BSS
  1615.         && symbolP -> sy_value == local_bss_counter)
  1616.         || (   (symbolP -> sy_type & N_TYPE) == N_UNDF
  1617.         && symbolP -> sy_value == 0))) {
  1618. #ifdef NeXT
  1619.         local_bss_counter = (local_bss_counter + ((1 << align) - 1) ) &
  1620.                     ~((1 << align) - 1);
  1621. #endif NeXT
  1622.         symbolP -> sy_value = local_bss_counter;
  1623.         symbolP -> sy_type  = N_BSS;
  1624. #ifdef Mach_O
  1625.         symbolP -> sy_other = n_type_n_sect (symbolP->sy_type);
  1626. #endif Mach_O
  1627.         symbolP -> sy_frag  = & bss_address_frag;
  1628.         local_bss_counter += temp;
  1629.     } else
  1630.         as_warn( "Ignoring attempt to re-define symbol from %d. to %d.",
  1631.  symbolP -> sy_value, local_bss_counter );
  1632.     demand_empty_rest_of_line();
  1633. }
  1634.  
  1635. void
  1636. s_line()
  1637. {
  1638.     /* Assume delimiter is part of expression. */
  1639.     /* BSD4.2 as fails with delightful bug, so we */
  1640.     /* are not being incompatible here. */
  1641. #ifdef NeXT
  1642.     /*
  1643.      * Since the assembler bumps it's line counters at the end of a line
  1644.      * and it is most allways the case that the .line is on it's own line
  1645.      * what the intent is that the line number is for the next line.  Thus
  1646.      * the -1 .  This is the way cpp'ed assembler files work which is the
  1647.      * common case.
  1648.      */
  1649.     new_logical_line ((char *)NULL, (int)(get_absolute_expression ())-1);
  1650. #else NeXT
  1651.     new_logical_line ((char *)NULL, (int)(get_absolute_expression ()));
  1652. #endif NeXT
  1653.     demand_empty_rest_of_line();
  1654. }
  1655.  
  1656. void
  1657. s_long()
  1658. {
  1659.     cons(4);
  1660. }
  1661.  
  1662. void
  1663. s_int()
  1664. {
  1665.     cons(4);
  1666. }
  1667.  
  1668. void
  1669. s_lsym()
  1670. {
  1671.     register char *name;
  1672.     register char c;
  1673.     register char *p;
  1674.     register segT segment;
  1675.     expressionS exp;
  1676.     register symbolS *symbolP;
  1677.  
  1678.     /* we permit ANY expression: BSD4.2 demands constants */
  1679. #ifdef NeXT
  1680.     if( * input_line_pointer == '"')
  1681.       name = input_line_pointer + 1;
  1682.     else
  1683.       name = input_line_pointer;
  1684. #else !defined(NeXT)
  1685.     name = input_line_pointer;
  1686. #endif NeXT
  1687.     c = get_symbol_end();
  1688.     p = input_line_pointer;
  1689.     *p = c;
  1690.     SKIP_WHITESPACE();
  1691.     if ( * input_line_pointer != ',' ) {
  1692.         *p = 0;
  1693.         as_warn("Expected comma after name \"%s\"", name);
  1694.         *p = c;
  1695.         ignore_rest_of_line();
  1696.         return;
  1697.     }
  1698.     input_line_pointer ++;
  1699.     segment = expression (& exp);
  1700.     if (   segment != SEG_ABSOLUTE && segment != SEG_DATA &&
  1701.  segment != SEG_TEXT && segment != SEG_BSS) {
  1702.         as_warn("Bad expression: %s", seg_name [(int)segment]);
  1703.         ignore_rest_of_line();
  1704.         return;
  1705.     }
  1706.  know(   segment == SEG_ABSOLUTE || segment == SEG_DATA || segment == SEG_TEXT || segment == SEG_BSS );
  1707.     *p = 0;
  1708. #ifdef Mach_O
  1709.     symbolP = symbol_new (name,(unsigned char)(seg_N_TYPE [(int) segment]),
  1710.  seg_n_sect(segment, now_subseg),
  1711.     0, (valueT)(exp . X_add_number), & zero_address_frag);
  1712. #else !defined(Mach_O)
  1713.     symbolP = symbol_new (name,(unsigned char)(seg_N_TYPE [(int) segment]),
  1714.  0, 0, (valueT)(exp . X_add_number), & zero_address_frag);
  1715. #endif Mach_O
  1716.     *p = c;
  1717.     demand_empty_rest_of_line();
  1718. }
  1719.  
  1720. void
  1721. s_org()
  1722. {
  1723.     register segT segment;
  1724.     expressionS exp;
  1725.     register long int temp_fill;
  1726.     register char *p;
  1727. /*
  1728.  * Don't believe the documentation of BSD 4.2 AS.
  1729.  * There is no such thing as a sub-segment-relative origin.
  1730.  * Any absolute origin is given a warning, then assumed to be segment-relative.
  1731.  * Any segmented origin expression ("foo+42") had better be in the right
  1732.  * segment or the .org is ignored.
  1733.  *
  1734.  * BSD 4.2 AS warns if you try to .org backwards. We cannot because we
  1735.  * never know sub-segment sizes when we are reading code.
  1736.  * BSD will crash trying to emit -ve numbers of filler bytes in certain
  1737.  * .orgs. We don't crash, but see as-write for that code.
  1738.  */
  1739. /*
  1740.  * Don't make frag if need_pass_2==TRUE.
  1741.  */
  1742.     segment = get_known_segmented_expression(& exp);
  1743.     if ( *input_line_pointer == ',' ) {
  1744.         input_line_pointer ++;
  1745.         temp_fill = get_absolute_expression ();
  1746.     } else
  1747.         temp_fill = 0;
  1748.     if ( ! need_pass_2 ) {
  1749.         if (segment != now_seg && segment != SEG_ABSOLUTE)
  1750.             as_warn("Illegal segment \"%s\". Segment \"%s\" assumed.",
  1751.  seg_name [(int) segment], seg_name [(int) now_seg]);
  1752.         p = frag_var (rs_org, 1, 1, (relax_substateT)0, exp . X_add_symbol,
  1753.  exp . X_add_number, (char *)0);
  1754.         * p = temp_fill;
  1755.     } /* if (ok to make frag) */
  1756.     demand_empty_rest_of_line();
  1757. }
  1758.  
  1759. void
  1760. s_set()
  1761. {
  1762.     register char *name;
  1763.     register char delim;
  1764.     register char *end_name;
  1765.     register symbolS *symbolP;
  1766.  
  1767.     /*
  1768.      * Especial apologies for the random logic:
  1769.      * this just grew, and could be parsed much more simply!
  1770.      * Dean in haste.
  1771.      */
  1772. #ifdef NeXT
  1773.     if( * input_line_pointer == '"')
  1774.       name = input_line_pointer + 1;
  1775.     else
  1776.       name = input_line_pointer;
  1777. #else !defined(NeXT)
  1778.     name = input_line_pointer;
  1779. #endif NeXT
  1780.     delim = get_symbol_end();
  1781.     end_name = input_line_pointer;
  1782.     *end_name = delim;
  1783.     SKIP_WHITESPACE();
  1784.     if ( * input_line_pointer != ',' ) {
  1785.         *end_name = 0;
  1786.         as_warn("Expected comma after name \"%s\"", name);
  1787.         *end_name = delim;
  1788.         ignore_rest_of_line();
  1789.         return;
  1790.     }
  1791.     input_line_pointer ++;
  1792.     *end_name = 0;
  1793.     if(name[0]=='.' && name[1]=='\0') {
  1794.       /* Turn '. = mumble' into a .org mumble */
  1795.       register segT segment;
  1796.       expressionS exp;
  1797.       register char *ptr;
  1798.  
  1799.       segment = get_known_segmented_expression(& exp);
  1800.       if ( ! need_pass_2 ) {
  1801.         if (segment != now_seg && segment != SEG_ABSOLUTE)
  1802.           as_warn("Illegal segment \"%s\". Segment \"%s\" assumed.",
  1803.               seg_name [(int) segment], seg_name [(int) now_seg]);
  1804.         ptr = frag_var (rs_org, 1, 1, (relax_substateT)0, exp.X_add_symbol,
  1805.               exp.X_add_number, (char *)0);
  1806.         *ptr= 0;
  1807.       } /* if (ok to make frag) */
  1808.       *end_name = delim;
  1809.       return;
  1810.     }
  1811.     symbolP = symbol_find_or_make (name);
  1812.     *end_name = delim;
  1813.     pseudo_set (symbolP);
  1814.     demand_empty_rest_of_line ();
  1815. }
  1816.  
  1817. #ifdef NeXT
  1818. /*
  1819.  * s_abs() is used to implement ".abs symbol,exp" which set symbol to 1 or 0
  1820.  * depending on if the expression is an absolute expression.  This is intended
  1821.  * for use in macros.
  1822.  */
  1823. void
  1824. s_abs()
  1825. {
  1826.     register char *name;
  1827.     register char c;
  1828.     register char *p;
  1829.     register segT segment;
  1830.     expressionS exp;
  1831.     register symbolS *symbolP;
  1832.  
  1833. #ifdef NeXT
  1834.     if( * input_line_pointer == '"')
  1835.       name = input_line_pointer + 1;
  1836.     else
  1837.       name = input_line_pointer;
  1838. #else !defined(NeXT)
  1839.     name = input_line_pointer;
  1840. #endif NeXT
  1841.     c = get_symbol_end();
  1842.     p = input_line_pointer;
  1843.     *p = c;
  1844.     SKIP_WHITESPACE();
  1845.     if ( * input_line_pointer != ',' ) {
  1846.         *p = 0;
  1847.         as_warn("Expected comma after name \"%s\"", name);
  1848.         *p = c;
  1849.         ignore_rest_of_line();
  1850.         return;
  1851.     }
  1852.     input_line_pointer ++;
  1853.     *p = 0;
  1854.     segment = expression (& exp);
  1855.     symbolP = symbol_find_or_make (name);
  1856.     symbolP -> sy_type = N_ABS;
  1857. #ifdef Mach_O
  1858.     symbolP -> sy_other = 0; /* NO_SECT */
  1859. #endif Mach_O
  1860.     symbolP -> sy_frag = & zero_address_frag;
  1861.     if (segment == SEG_ABSOLUTE)
  1862.         symbolP -> sy_value = 1;
  1863.     else
  1864.         symbolP -> sy_value = 0;
  1865.     *p = c;
  1866.     totally_ignore_line();
  1867. }
  1868. #endif NeXT
  1869.  
  1870. void
  1871. s_space()
  1872. {
  1873.     long int temp_repeat;
  1874.     register long int temp_fill;
  1875.     register char *p;
  1876.  
  1877.     /* Just like .fill, but temp_size = 1 */
  1878.     if ( get_absolute_expression_and_terminator( & temp_repeat) == ',' ) {
  1879.         temp_fill = get_absolute_expression ();
  1880.     } else {
  1881.         input_line_pointer --; /* Backup over what was not a ','. */
  1882.         temp_fill = 0;
  1883.     }
  1884.     if ( temp_repeat <= 0 ) {
  1885.         as_warn("Repeat < 0, .space ignored");
  1886.         ignore_rest_of_line();
  1887.         return;
  1888.     }
  1889.     if ( ! need_pass_2 ) {
  1890.         p = frag_var (rs_fill, 1, 1, (relax_substateT)0, (symbolS *)0,
  1891.  temp_repeat, (char *)0);
  1892.         * p = temp_fill;
  1893.     }
  1894.     demand_empty_rest_of_line();
  1895. }
  1896.  
  1897. void
  1898. s_text()
  1899. {
  1900.     register int temp;
  1901.  
  1902.     temp = get_absolute_expression ();
  1903.     subseg_new (SEG_TEXT, (subsegT)temp);
  1904.     demand_empty_rest_of_line();
  1905. }
  1906.  
  1907. #ifdef NeXT
  1908. void
  1909. s_reference()
  1910. {
  1911.     register char *name;
  1912.     register char c;
  1913.     register char *p;
  1914.     register symbolS *    symbolP;
  1915.  
  1916.     if( * input_line_pointer == '"')
  1917.       name = input_line_pointer + 1;
  1918.     else
  1919.       name = input_line_pointer;
  1920.     c = get_symbol_end();
  1921.     p = input_line_pointer;
  1922.  
  1923.     *p = 0;
  1924.     symbolP = symbol_find_or_make (name);
  1925.     *p = c;
  1926.     demand_empty_rest_of_line();
  1927. }
  1928. #endif NeXT
  1929.  
  1930. #ifdef NeXT    /* .include feature */
  1931. void
  1932. s_include()
  1933. /*
  1934.  * DJA -- Include files.
  1935.  */
  1936. {
  1937.     register char *filename;
  1938.     int    length;
  1939.     void read_an_include_file ();
  1940.  
  1941.     symbolS *symbolP;
  1942.         extern char *physical_input_file;
  1943.  
  1944.     /* Some assemblers tolerate immediately following '"' */
  1945.     if ( filename = demand_copy_string( & length ) ) {
  1946.         demand_empty_rest_of_line();
  1947.         read_an_include_file (filename);
  1948.     }
  1949.  
  1950.     /* See the second comment about stabs in read_a_source_file()
  1951.        for a description of what is going on here */
  1952.     if (flagseen['g'] && now_seg == SEG_TEXT && now_subseg == 0){
  1953.         symbolP = symbol_new(
  1954.             physical_input_file,
  1955.             132 /* N_SOL */,
  1956.             seg_n_sect(now_seg, now_subseg),
  1957.             0,
  1958.             obstack_next_free(&frags) - frag_now->fr_literal,
  1959.             frag_now);
  1960.     }
  1961. }
  1962. #endif NeXT    /* .include feature */
  1963.  
  1964. #ifdef Mach_O
  1965. void
  1966. s_text_Mach_O(subseg)
  1967. int subseg;
  1968. {
  1969.     subseg_new(SEG_TEXT, subseg);
  1970.     demand_empty_rest_of_line();
  1971. }
  1972.  
  1973. void
  1974. s_data_Mach_O(subseg)
  1975. int subseg;
  1976. {
  1977.     subseg_new(SEG_DATA, subseg);
  1978.     demand_empty_rest_of_line();
  1979. }
  1980. #endif Mach_O
  1981.  
  1982.  
  1983. /*( JF was static, but can't be if machine dependent pseudo-ops are to use it */
  1984.  
  1985. void
  1986. demand_empty_rest_of_line()
  1987. {
  1988.   SKIP_WHITESPACE();
  1989.   if ( is_end_of_line [* input_line_pointer] )
  1990.     {
  1991.       input_line_pointer ++;
  1992.     }
  1993.   else
  1994.     {
  1995.       ignore_rest_of_line();
  1996.     }
  1997.                 /* Return having already swallowed end-of-line. */
  1998. }                /* Return pointing just after end-of-line. */
  1999.  
  2000. void
  2001. ignore_rest_of_line()        /* For suspect lines: gives warning. */
  2002. {
  2003.   if ( ! is_end_of_line [* input_line_pointer])
  2004.     {
  2005.       as_warn("Rest of line ignored. 1st junk character valued %d (%c)."
  2006.           , * input_line_pointer, *input_line_pointer);
  2007.       while (   input_line_pointer < buffer_limit
  2008.          && ! is_end_of_line [* input_line_pointer] )
  2009.     {
  2010.       input_line_pointer ++;
  2011.     }
  2012.     }
  2013.   input_line_pointer ++;    /* Return pointing just after end-of-line. */
  2014.   know( is_end_of_line [input_line_pointer [-1]] );
  2015. }
  2016.  
  2017. /*
  2018.  *            stab()
  2019.  *
  2020.  * Handle .stabX directives, which used to be open-coded.
  2021.  * So much creeping featurism overloaded the semantics that we decided
  2022.  * to put all .stabX thinking in one place. Here.
  2023.  *
  2024.  * We try to make any .stabX directive legal. Other people's AS will often
  2025.  * do assembly-time consistency checks: eg assigning meaning to n_type bits
  2026.  * and "protecting" you from setting them to certain values. (They also zero
  2027.  * certain bits before emitting symbols. Tut tut.)
  2028.  *
  2029.  * If an expression is not absolute we either gripe or use the relocation
  2030.  * information. Other people's assemblers silently forget information they
  2031.  * don't need and invent information they need that you didn't supply.
  2032.  *
  2033.  * .stabX directives always make a symbol table entry. It may be junk if
  2034.  * the rest of your .stabX directive is malformed.
  2035.  */
  2036. static void
  2037. stab (what)
  2038. int what;
  2039. {
  2040.   register symbolS *    symbolP;
  2041.   register char *    string;
  2042.        int        saved_type;
  2043.          int        length;
  2044.          int        goof;    /* TRUE if we have aborted. */
  2045.        long int    longint;
  2046.  
  2047. /*
  2048.  * Enter with input_line_pointer pointing past .stabX and any following
  2049.  * whitespace.
  2050.  */
  2051.     goof = FALSE; /* JF who forgot this?? */
  2052.     if (what == 's') {
  2053.         string = demand_copy_C_string (& length);
  2054.         SKIP_WHITESPACE();
  2055.         if (* input_line_pointer == ',')
  2056.             input_line_pointer ++;
  2057.         else {
  2058.             as_warn( "I need a comma after symbol's name" );
  2059.             goof = TRUE;
  2060.         }
  2061.     } else
  2062.         string = "";
  2063.  
  2064. /*
  2065.  * Input_line_pointer->after ','.  String -> symbol name.
  2066.  */
  2067.     if (! goof) {
  2068.         symbolP = symbol_new (string, 0,0,0,0,(struct frag *)0);
  2069.         switch (what) {
  2070.         case 'd':
  2071.             symbolP->sy_name = NULL; /* .stabd feature. */
  2072.             symbolP->sy_value = obstack_next_free(& frags) - frag_now->fr_literal;
  2073.             symbolP->sy_frag = frag_now;
  2074.             break;
  2075.  
  2076.         case 'n':
  2077.             symbolP->sy_frag = &zero_address_frag;
  2078.             break;
  2079.  
  2080.         case 's':
  2081.             symbolP->sy_frag = & zero_address_frag;
  2082.             break;
  2083.  
  2084.         default:
  2085.             BAD_CASE( what );
  2086.             break;
  2087.         }
  2088.         if (get_absolute_expression_and_terminator (& longint) == ',')
  2089.             symbolP->sy_type = saved_type = longint;
  2090.         else {
  2091.             as_warn( "I want a comma after the n_type expression" );
  2092.             goof = TRUE;
  2093.             input_line_pointer --; /* Backup over a non-',' char. */
  2094.         }
  2095.     }
  2096.     if (! goof) {
  2097.         if (get_absolute_expression_and_terminator (& longint) == ',')
  2098.             symbolP->sy_other = longint;
  2099.         else {
  2100.             as_warn( "I want a comma after the n_other expression" );
  2101.             goof = TRUE;
  2102.             input_line_pointer --; /* Backup over a non-',' char. */
  2103.         }
  2104.     }
  2105.     if (! goof) {
  2106.         symbolP->sy_desc = get_absolute_expression ();
  2107.         if (what == 's' || what == 'n') {
  2108.             if (* input_line_pointer != ',') {
  2109.                 as_warn( "I want a comma after the n_desc expression" );
  2110.                 goof = TRUE;
  2111.             } else {
  2112.                 input_line_pointer ++;
  2113.             }
  2114.         }
  2115.     }
  2116.     if ((! goof) && (what=='s' || what=='n')) {
  2117.         pseudo_set (symbolP);
  2118.         symbolP->sy_type = saved_type;
  2119.     }
  2120. #ifdef Mach_O
  2121.     else if (! goof) {
  2122.         symbolP->sy_other = seg_n_sect(now_seg, now_subseg);
  2123.     }
  2124. #endif Mach_O
  2125.     if (goof)
  2126.         ignore_rest_of_line ();
  2127.     else
  2128.         demand_empty_rest_of_line ();
  2129. }
  2130.  
  2131. /*
  2132.  *            pseudo_set()
  2133.  *
  2134.  * In:    Pointer to a symbol.
  2135.  *    Input_line_pointer -> expression.
  2136.  *
  2137.  * Out:    Input_line_pointer -> just after any whitespace after expression.
  2138.  *    Tried to set symbol to value of expression.
  2139.  *    Will change sy_type, sy_value, sy_frag;
  2140.  *    May set need_pass_2 == TRUE.
  2141.  */
  2142. static void
  2143. pseudo_set (symbolP)
  2144.      symbolS *    symbolP;
  2145. {
  2146.   expressionS    exp;
  2147.   register segT    segment;
  2148.   int ext;
  2149.  
  2150.   know( symbolP );        /* NULL pointer is logic error. */
  2151.   ext=(symbolP->sy_type&N_EXT);
  2152.   if ((segment = expression( & exp )) == SEG_NONE)
  2153.     {
  2154.       as_warn( "Missing expression: absolute 0 assumed" );
  2155.       exp . X_seg        = SEG_ABSOLUTE;
  2156.       exp . X_add_number    = 0;
  2157.     }
  2158.   switch (segment)
  2159.     {
  2160.     case SEG_BIG:
  2161.       as_warn( "%s number illegal. Absolute 0 assumed.",
  2162.           exp . X_add_number > 0 ? "Bignum" : "Floating-Point" );
  2163.       symbolP -> sy_type = N_ABS | ext;
  2164. #ifdef Mach_O
  2165.       symbolP -> sy_other = 0; /* NO_SECT */
  2166. #endif Mach_O
  2167.       symbolP -> sy_value = 0;
  2168.       symbolP -> sy_frag = & zero_address_frag;
  2169.       break;
  2170.  
  2171.     case SEG_NONE:
  2172.       as_warn("No expression:  Using absolute 0");
  2173.       symbolP -> sy_type = N_ABS | ext;
  2174. #ifdef Mach_O
  2175.       symbolP -> sy_other = 0; /* NO_SECT */
  2176. #endif Mach_O
  2177.       symbolP -> sy_value = 0;
  2178.       symbolP -> sy_frag = & zero_address_frag;
  2179.       break;
  2180.  
  2181.     case SEG_DIFFERENCE:
  2182.       if (exp.X_add_symbol && exp.X_subtract_symbol
  2183.           &&    (exp.X_add_symbol->sy_type & N_TYPE)
  2184.          == (exp.X_subtract_symbol->sy_type & N_TYPE))
  2185.     exp.X_add_number+=exp.X_add_symbol->sy_value - exp.X_subtract_symbol->sy_value;
  2186.       else
  2187.     as_warn( "Complex expression. Absolute segment assumed." );
  2188.     case SEG_ABSOLUTE:
  2189.       symbolP -> sy_type = N_ABS | ext;
  2190. #ifdef Mach_O
  2191.       symbolP -> sy_other = 0; /* NO_SECT */
  2192. #endif Mach_O
  2193.       symbolP -> sy_value = exp . X_add_number;
  2194.       symbolP -> sy_frag = & zero_address_frag;
  2195.       break;
  2196.  
  2197.     case SEG_DATA:
  2198.     case SEG_TEXT:
  2199.     case SEG_BSS:
  2200.       symbolP -> sy_type = seg_N_TYPE [(int) segment] | ext;
  2201. #ifdef Mach_O
  2202.       symbolP -> sy_other = n_type_n_sect (exp . X_add_symbol -> sy_type);
  2203. #endif Mach_O
  2204.       symbolP -> sy_value= exp . X_add_number + exp . X_add_symbol -> sy_value;
  2205.       symbolP -> sy_frag = exp . X_add_symbol -> sy_frag;
  2206.       break;
  2207.       
  2208.     case SEG_PASS1:        /* Not an error. Just try another pass. */
  2209.       symbolP->sy_forward=exp.X_add_symbol;
  2210.       as_warn("Unknown expression");
  2211.       know( need_pass_2 == TRUE );
  2212.       break;
  2213.       
  2214.     case SEG_UNKNOWN:
  2215.       symbolP->sy_forward=exp.X_add_symbol;
  2216.       /* as_warn("unknown symbol"); */
  2217.       /* need_pass_2 = TRUE; */
  2218.       break;
  2219.       
  2220.     default:
  2221.       BAD_CASE( segment );
  2222.       break;
  2223.     }
  2224. }
  2225.  
  2226. /*
  2227.  *            cons()
  2228.  *
  2229.  * CONStruct more frag of .bytes, or .words etc.
  2230.  * Should need_pass_2 be TRUE then emit no frag(s).
  2231.  * This understands EXPRESSIONS, as opposed to big_cons().
  2232.  *
  2233.  * Bug (?)
  2234.  *
  2235.  * This has a split personality. We use expression() to read the
  2236.  * value. We can detect if the value won't fit in a byte or word.
  2237.  * But we can't detect if expression() discarded significant digits
  2238.  * in the case of a long. Not worth the crocks required to fix it.
  2239.  */
  2240. void
  2241. cons(nbytes)            /* worker to do .byte etc statements */
  2242.                 /* clobbers input_line_pointer, checks */
  2243.                 /* end-of-line. */
  2244.      register int    nbytes;    /* 1=.byte, 2=.word, 4=.long */
  2245. {
  2246.   register char        c;
  2247.   register long int    mask;    /* High-order bits we will left-truncate, */
  2248.                 /* but includes sign bit also. */
  2249.   register long int     get;    /* what we get */
  2250.   register long int    use;    /* get after truncation. */
  2251.   register long int    unmask;    /* what bits we will store */
  2252.   register char *    p;
  2253.   register segT        segment;
  2254.            expressionS    exp;
  2255. #ifdef NS32K
  2256.   void fix_new_ns32k();
  2257. #else
  2258.   void    fix_new();
  2259. #endif
  2260.  
  2261.   /*
  2262.    * Input_line_pointer -> 1st char after pseudo-op-code and could legally
  2263.    * be a end-of-line. (Or, less legally an eof - which we cope with.)
  2264.    */
  2265.   /* JF << of >= number of bits in the object is undefined.  In particular
  2266.      SPARC (Sun 4) has problems */
  2267.   if(nbytes>=sizeof(long int))
  2268.     mask = 0;
  2269.   else 
  2270.     mask = ~0 << (BITS_PER_CHAR * nbytes); /* Don't store these bits. */
  2271.   unmask = ~ mask;        /* Do store these bits. */
  2272. #ifdef NEVER
  2273.   "Do this mod if you want every overflow check to assume SIGNED 2's complement data.";
  2274.   mask = ~ (unmask >> 1);    /* Includes sign bit now. */
  2275. #endif
  2276.   /*
  2277.    * The following awkward logic is to parse ZERO or more expressions,
  2278.    * comma seperated. Recall an expression includes its leading &
  2279.    * trailing blanks. We fake a leading ',' if there is (supposed to
  2280.    * be) a 1st expression, and keep demanding 1 expression for each ','.
  2281.    */
  2282.   if (is_it_end_of_statement())
  2283.     {
  2284.       c = 0;            /* Skip loop. */
  2285.       input_line_pointer ++;    /* Matches end-of-loop 'correction'. */
  2286.     }
  2287.   else
  2288.       c = ',';            /* Do loop. */
  2289.   while ( c == ','  )
  2290.     {
  2291.       segment = expression( &exp ); /* At least scan over the expression. */
  2292.       if ( ! need_pass_2 )
  2293.     {            /* Still worthwhile making frags. */
  2294.  
  2295.       /* Don't call this if we are going to junk this pass anyway! */
  2296.       know( segment != SEG_PASS1 );
  2297.  
  2298.       if ( segment == SEG_DIFFERENCE && exp . X_add_symbol == NULL )
  2299.         {
  2300.           as_warn( "Subtracting symbol \"%s\"(segment\"%s\") is too hard. Absolute segment assumed.",
  2301.               exp . X_subtract_symbol -> sy_name,
  2302.               seg_name [(int) N_TYPE_seg [exp . X_subtract_symbol -> sy_type & N_TYPE]]);
  2303.           segment = SEG_ABSOLUTE;
  2304.           /* Leave exp . X_add_number alone. */
  2305.         }
  2306.       p = frag_more (nbytes);
  2307.       switch (segment)
  2308.         {
  2309.         case SEG_BIG:
  2310.           as_warn( "%s number illegal. Absolute 0 assumed.",
  2311.               exp . X_add_number > 0 ? "Bignum" : "Floating-Point");
  2312.           md_number_to_chars (p, (long)0, nbytes);
  2313.           break;
  2314.  
  2315.         case SEG_NONE:
  2316.           as_warn( "0 assumed for missing expression" );
  2317.           exp . X_add_number = 0;
  2318.           know( exp . X_add_symbol == NULL );
  2319.           /* fall into SEG_ABSOLUTE */
  2320.         case SEG_ABSOLUTE:
  2321.           get = exp . X_add_number;
  2322.           use = get & unmask;
  2323.           if ( (get & mask) && (get & mask) != mask )
  2324.         {        /* Leading bits contain both 0s & 1s. */
  2325.           as_warn("Value x%x truncated to x%x.", get, use);
  2326.         }
  2327.           md_number_to_chars (p, use, nbytes); /* put bytes in right order. */
  2328.           break;
  2329.  
  2330.         case SEG_DIFFERENCE:
  2331. #ifndef WORKING_DOT_WORD
  2332.           if(nbytes==2) {
  2333.         struct broken_word *x;
  2334.  
  2335.         x=(struct broken_word *)xmalloc(sizeof(struct broken_word));
  2336.         x->next_broken_word=broken_words;
  2337.         broken_words=x;
  2338.         x->frag=frag_now;
  2339.         x->word_goes_here=p;
  2340.         x->dispfrag=0;
  2341.         x->add=exp.X_add_symbol;
  2342.         x->sub=exp.X_subtract_symbol;
  2343.         x->addnum=exp.X_add_number;
  2344.         x->added=0;
  2345.         new_broken_words++;
  2346.         break;
  2347.           }
  2348.           /* Else Fall through into. . . */
  2349. #endif
  2350.         case SEG_BSS:
  2351.         case SEG_UNKNOWN:
  2352.         case SEG_TEXT:
  2353.         case SEG_DATA:
  2354. #ifdef RISC
  2355. #ifdef NeXT
  2356.           fix_new (frag_now, p - frag_now -> fr_literal, nbytes,
  2357.                exp . X_add_symbol, exp . X_subtract_symbol,
  2358.                exp . X_add_number, 0, RELOC_VANILLA);
  2359. #else !defined(NeXT)
  2360.           fix_new (frag_now, p - frag_now -> fr_literal, nbytes,
  2361.                exp . X_add_symbol, exp . X_subtract_symbol,
  2362.                exp . X_add_number, 0, RELOC_32);
  2363. #endif NeXT
  2364. #endif
  2365. #ifdef NS32K
  2366.           fix_new_ns32k (frag_now, p - frag_now -> fr_literal, nbytes,
  2367.                exp . X_add_symbol, exp . X_subtract_symbol,
  2368.                exp . X_add_number, 0, 0, 2, 0, 0);
  2369. #endif
  2370. #if !defined(RISC) && !defined(NS32K)
  2371.           fix_new (frag_now, p - frag_now -> fr_literal, nbytes,
  2372.                exp . X_add_symbol, exp . X_subtract_symbol,
  2373.                exp . X_add_number, 0);
  2374. #endif
  2375.           break;
  2376.  
  2377.         default:
  2378.           BAD_CASE( segment );
  2379.           break;
  2380.         }            /* switch(segment) */
  2381.     }            /* if(!need_pass_2) */
  2382.       c = * input_line_pointer ++;
  2383.     }                /* while(c==',') */
  2384.   input_line_pointer --;    /* Put terminator back into stream. */
  2385.   demand_empty_rest_of_line();
  2386. }                /* cons() */
  2387.  
  2388. /*
  2389.  *            big_cons()
  2390.  *
  2391.  * CONStruct more frag(s) of .quads, or .octa etc.
  2392.  * Makes 0 or more new frags.
  2393.  * If need_pass_2 == TRUE, generate no frag.
  2394.  * This understands only bignums, not expressions. Cons() understands
  2395.  * expressions.
  2396.  *
  2397.  * Constants recognised are '0...'(octal) '0x...'(hex) '...'(decimal).
  2398.  *
  2399.  * This creates objects with struct obstack_control objs, destroying
  2400.  * any context objs held about a partially completed object. Beware!
  2401.  *
  2402.  *
  2403.  * I think it sucks to have 2 different types of integers, with 2
  2404.  * routines to read them, store them etc.
  2405.  * It would be nicer to permit bignums in expressions and only
  2406.  * complain if the result overflowed. However, due to "efficiency"...
  2407.  */
  2408. void
  2409. big_cons(nbytes)        /* worker to do .quad etc statements */
  2410.                 /* clobbers input_line_pointer, checks */
  2411.                 /* end-of-line. */
  2412.      register int    nbytes;    /* 8=.quad 16=.octa ... */
  2413. {
  2414.   register char        c;    /* input_line_pointer -> c. */
  2415.   register int        radix;
  2416.   register long int    length;    /* Number of chars in an object. */
  2417.   register int        digit;    /* Value of 1 digit. */
  2418.   register int        carry;    /* For multi-precision arithmetic. */
  2419.   register int        work;    /* For multi-precision arithmetic. */
  2420.   register char *    p;    /* For multi-precision arithmetic. */
  2421.  
  2422.   extern char hex_value[];    /* In hex_value.c. */
  2423.  
  2424.   /*
  2425.    * The following awkward logic is to parse ZERO or more strings,
  2426.    * comma seperated. Recall an expression includes its leading &
  2427.    * trailing blanks. We fake a leading ',' if there is (supposed to
  2428.    * be) a 1st expression, and keep demanding 1 expression for each ','.
  2429.    */
  2430.   if (is_it_end_of_statement())
  2431.     {
  2432.       c = 0;            /* Skip loop. */
  2433.     }
  2434.   else
  2435.     {
  2436.       c = ',';            /* Do loop. */
  2437.       -- input_line_pointer;
  2438.     }
  2439.   while (c == ',')
  2440.     {
  2441.       ++ input_line_pointer;
  2442.       SKIP_WHITESPACE();
  2443.       c = * input_line_pointer;
  2444.       /* C contains 1st non-blank character of what we hope is a number. */
  2445.       if (c == '0')
  2446.     {
  2447.       c = * ++ input_line_pointer;
  2448.       if (c == 'x' || c=='X')
  2449.         {
  2450.           c = * ++ input_line_pointer;
  2451.           radix = 16;
  2452.         }
  2453.       else
  2454.         {
  2455.           radix = 8;
  2456.         }
  2457.     }
  2458.       else
  2459.     {
  2460.       radix = 10;
  2461.     }
  2462.       /*
  2463.        * This feature (?) is here to stop people worrying about
  2464.        * mysterious zero constants: which is what they get when
  2465.        * they completely omit digits.
  2466.        */
  2467.       if (hex_value[c] >= radix)
  2468.     {
  2469.       as_warn( "Missing digits. 0 assumed." );
  2470.     }
  2471.       bignum_high = bignum_low - 1; /* Start constant with 0 chars. */
  2472.       for(   ;   (digit = hex_value [c]) < radix;   c = * ++ input_line_pointer)
  2473.     {
  2474.       /* Multiply existing number by radix, then add digit. */
  2475.       carry = digit;
  2476.       for (p=bignum_low;   p <= bignum_high;   p++)
  2477.         {
  2478.           work = (*p & MASK_CHAR) * radix + carry;
  2479.           *p = work & MASK_CHAR;
  2480.           carry = work >> BITS_PER_CHAR;
  2481.         }
  2482.       if (carry)
  2483.         {
  2484.           grow_bignum();
  2485.           * bignum_high = carry & MASK_CHAR;
  2486.           know( (carry & ~ MASK_CHAR) == 0);
  2487.         }
  2488.     }
  2489.       length = bignum_high - bignum_low + 1;
  2490.       if (length > nbytes)
  2491.     {
  2492.       as_warn( "Most significant bits truncated in integer constant." );
  2493.     }
  2494.       else
  2495.     {
  2496.       register long int    leading_zeroes;
  2497.  
  2498.       for(leading_zeroes = nbytes - length;
  2499.           leading_zeroes;
  2500.           leading_zeroes --)
  2501.         {
  2502.           grow_bignum();
  2503.           * bignum_high = 0;
  2504.         }
  2505.     }
  2506.       if (! need_pass_2)
  2507.     {
  2508.       p = frag_more (nbytes);
  2509.       bcopy (bignum_low, p, (int)nbytes);
  2510.     }
  2511.       /* C contains character after number. */
  2512.       SKIP_WHITESPACE();
  2513.       c = * input_line_pointer;
  2514.       /* C contains 1st non-blank character after number. */
  2515.     }
  2516.   demand_empty_rest_of_line();
  2517. }                /* big_cons() */
  2518.  
  2519. static void
  2520. grow_bignum()            /* Extend bignum by 1 char. */
  2521. {
  2522.   register long int    length;
  2523.  
  2524.   bignum_high ++;
  2525.   if (bignum_high >= bignum_limit)
  2526.     {
  2527.       length = bignum_limit - bignum_low;
  2528.       bignum_low = xrealloc (bignum_low, length + length);
  2529.       bignum_high = bignum_low + length;
  2530.       bignum_limit = bignum_low + length + length;
  2531.     }
  2532. }                /* grow_bignum(); */
  2533.  
  2534. /*
  2535.  *            float_cons()
  2536.  *
  2537.  * CONStruct some more frag chars of .floats .ffloats etc.
  2538.  * Makes 0 or more new frags.
  2539.  * If need_pass_2 == TRUE, no frags are emitted.
  2540.  * This understands only floating literals, not expressions. Sorry.
  2541.  *
  2542.  * A floating constant is defined by atof_generic(), except it is preceded
  2543.  * by 0d 0f 0g or 0h. After observing the STRANGE way my BSD AS does its
  2544.  * reading, I decided to be incompatible. This always tries to give you
  2545.  * rounded bits to the precision of the pseudo-op. Former AS did premature
  2546.  * truncatation, restored noisy bits instead of trailing 0s AND gave you
  2547.  * a choice of 2 flavours of noise according to which of 2 floating-point
  2548.  * scanners you directed AS to use.
  2549.  *
  2550.  * In:    input_line_pointer -> whitespace before, or '0' of flonum.
  2551.  *
  2552.  */
  2553.  
  2554. void    /* JF was static, but can't be if VAX.C is goning to use it */
  2555. float_cons(float_type)        /* Worker to do .float etc statements. */
  2556.                 /* Clobbers input_line-pointer, checks end-of-line. */
  2557.      register float_type;    /* 'f':.ffloat ... 'F':.float ... */
  2558. {
  2559.   register char *    p;
  2560.   register char        c;
  2561.   int    length;    /* Number of chars in an object. */
  2562.   register char *    err;    /* Error from scanning floating literal. */
  2563.   char        temp [MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT];
  2564.  
  2565.   /*
  2566.    * The following awkward logic is to parse ZERO or more strings,
  2567.    * comma seperated. Recall an expression includes its leading &
  2568.    * trailing blanks. We fake a leading ',' if there is (supposed to
  2569.    * be) a 1st expression, and keep demanding 1 expression for each ','.
  2570.    */
  2571.   if (is_it_end_of_statement())
  2572.     {
  2573.       c = 0;            /* Skip loop. */
  2574.       ++ input_line_pointer;    /* -> past termintor. */
  2575.     }
  2576.   else
  2577.     {
  2578.       c = ',';            /* Do loop. */
  2579.     }
  2580.   while (c == ',')
  2581.     {
  2582.       /* input_line_pointer -> 1st char of a flonum (we hope!). */
  2583.       SKIP_WHITESPACE();
  2584.       /* Skip any 0{letter} that may be present. Don't even check if the
  2585.        * letter is legal. Someone may invent a "z" format and this routine
  2586.        * has no use for such information. Lusers beware: you get
  2587.        * diagnostics if your input is ill-conditioned.
  2588.        */
  2589.  
  2590.       if(input_line_pointer[0]=='0' && isalpha(input_line_pointer[1]))
  2591.       input_line_pointer+=2;
  2592.  
  2593.       err = md_atof (float_type, temp, &length);
  2594.       know( length <=  MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT);
  2595.       know( length > 0 );
  2596.       if (* err)
  2597.     {
  2598.       as_warn( "Bad floating literal: %s", err);
  2599.       ignore_rest_of_line();
  2600.       /* Input_line_pointer -> just after end-of-line. */
  2601.       c = 0;        /* Break out of loop. */
  2602.     }
  2603.       else
  2604.     {
  2605.       if ( ! need_pass_2)
  2606.         {
  2607.           p = frag_more (length);
  2608.           bcopy (temp, p, length);
  2609.         }
  2610.       SKIP_WHITESPACE();
  2611.       c = * input_line_pointer ++;
  2612.       /* C contains 1st non-white character after number. */
  2613.       /* input_line_pointer -> just after terminator (c). */
  2614.     }
  2615.     }
  2616.   -- input_line_pointer;        /* -> terminator (is not ','). */
  2617.   demand_empty_rest_of_line();
  2618. }                /* float_cons() */
  2619.  
  2620. /*
  2621.  *            stringer()
  2622.  *
  2623.  * We read 0 or more ',' seperated, double-quoted strings.
  2624.  *
  2625.  * Caller should have checked need_pass_2 is FALSE because we don't check it.
  2626.  */
  2627. #ifdef I860
  2628. void
  2629. #else !defined(I860)
  2630. static void
  2631. #endif I860
  2632. stringer(append_zero)        /* Worker to do .ascii etc statements. */
  2633.                 /* Checks end-of-line. */
  2634.      register int append_zero;    /* 0: don't append '\0', else 1 */
  2635. {
  2636.   /* register char *    p; JF unused */
  2637.   /* register int        length; JF unused */    /* Length of string we read, excluding */
  2638.                 /* trailing '\0' implied by closing quote. */
  2639.   /* register char *    where; JF unused */
  2640.   /* register fragS *    fragP; JF unused */
  2641.   register int c;
  2642.  
  2643.   /*
  2644.    * The following awkward logic is to parse ZERO or more strings,
  2645.    * comma seperated. Recall a string expression includes spaces
  2646.    * before the opening '\"' and spaces after the closing '\"'.
  2647.    * We fake a leading ',' if there is (supposed to be)
  2648.    * a 1st, expression. We keep demanding expressions for each
  2649.    * ','.
  2650.    */
  2651.   if (is_it_end_of_statement())
  2652.     {
  2653.       c = 0;            /* Skip loop. */
  2654.       ++ input_line_pointer;    /* Compensate for end of loop. */
  2655.     }
  2656.   else
  2657.     {
  2658.       c = ',';            /* Do loop. */
  2659.     }
  2660.   for (   ;   c == ',';   c = *input_line_pointer ++)
  2661.     {
  2662.       SKIP_WHITESPACE();
  2663.       if (* input_line_pointer == '\"')
  2664.     {
  2665.       ++ input_line_pointer; /* -> 1st char of string. */
  2666.       while ( (c = next_char_of_string()) >= 0 )
  2667.         {
  2668.           FRAG_APPEND_1_CHAR( c );
  2669.         }
  2670.       if (append_zero)
  2671.         {
  2672.           FRAG_APPEND_1_CHAR( 0 );
  2673.         }
  2674.       know( input_line_pointer [-1] == '\"' );
  2675.     }
  2676.       else
  2677.     {
  2678.       as_warn( "Expected \"-ed string" );
  2679.     }
  2680.       SKIP_WHITESPACE();
  2681.     }
  2682.   -- input_line_pointer;
  2683.   demand_empty_rest_of_line();
  2684. }                /* stringer() */
  2685.  
  2686. static int
  2687. next_char_of_string ()
  2688. {
  2689.   register int c;
  2690.  
  2691.   c = * input_line_pointer ++;
  2692. #ifdef NeXT /* allow 8 bit chars in strings */
  2693.   c = (c & MASK_CHAR); /* to make sure the 0xff char is not returned as -1 */
  2694. #endif NeXT
  2695.   switch (c)
  2696.     {
  2697.     case '\"':
  2698.       c = -1;
  2699.       break;
  2700.  
  2701.     case '\\':
  2702.       switch (c = * input_line_pointer ++)
  2703.     {
  2704.     case 'b':
  2705.       c = '\b';
  2706.       break;
  2707.  
  2708.     case 'f':
  2709.       c = '\f';
  2710.       break;
  2711.  
  2712.     case 'n':
  2713.       c = '\n';
  2714.       break;
  2715.  
  2716.     case 'r':
  2717.       c = '\r';
  2718.       break;
  2719.  
  2720.     case 't':
  2721.       c = '\t';
  2722.       break;
  2723.  
  2724.     case '\\':
  2725.     case '"':
  2726.       break;        /* As itself. */
  2727.  
  2728.     case '0':
  2729.     case '1':
  2730.     case '2':
  2731.     case '3':
  2732.     case '4':
  2733.     case '5':
  2734.     case '6':
  2735.     case '7':
  2736.     case '8':
  2737.     case '9':
  2738.       {
  2739.         long int number;
  2740.  
  2741.         for (number = 0;   isdigit(c);   c = * input_line_pointer ++)
  2742.           {
  2743.         number = number * 8 + c - '0';
  2744.           }
  2745.         c = number;
  2746.       }
  2747.       -- input_line_pointer;
  2748.       break;
  2749.  
  2750.     case '\n':
  2751. /*      as_fatal( "Unterminated string - use app!" ); */
  2752. /* To be compatible with BSD 4.2 as: give the luser a linefeed!! */
  2753.       c = '\n';
  2754.       break;
  2755.  
  2756.     default:
  2757.       as_warn( "Bad escaped character in string, '?' assumed" );
  2758.       c = '?';
  2759.       break;
  2760.     }
  2761.       break;
  2762.  
  2763.     default:
  2764.       break;
  2765.     }
  2766.   return (c);
  2767. }
  2768.  
  2769. static segT
  2770. get_segmented_expression ( expP )
  2771.      register expressionS *    expP;
  2772. {
  2773.   register segT        retval;
  2774.  
  2775.   if ( (retval = expression( expP )) == SEG_PASS1 || retval == SEG_NONE || retval == SEG_BIG )
  2776.     {
  2777.       as_warn("Expected address expression: absolute 0 assumed");
  2778.       retval = expP -> X_seg = SEG_ABSOLUTE;
  2779.       expP -> X_add_number   = 0;
  2780.       expP -> X_add_symbol   = expP -> X_subtract_symbol = 0;
  2781.     }
  2782.   return (retval);        /* SEG_ ABSOLUTE,UNKNOWN,DATA,TEXT,BSS */
  2783. }
  2784.  
  2785. #ifdef I860
  2786. segT
  2787. #else !defined(I860)
  2788. static segT
  2789. #endif I860
  2790. get_known_segmented_expression ( expP )
  2791.      register expressionS *    expP;
  2792. {
  2793.   register segT        retval;
  2794.   register char *    name1;
  2795.   register char *    name2;
  2796.  
  2797.   if (   (retval = get_segmented_expression (expP)) == SEG_UNKNOWN
  2798.       )
  2799.     {
  2800.       name1 = expP -> X_add_symbol ? expP -> X_add_symbol -> sy_name : "";
  2801.       name2 = expP -> X_subtract_symbol ? expP -> X_subtract_symbol -> sy_name : "";
  2802.       if ( name1 && name2 )
  2803.     {
  2804.       as_warn("Symbols \"%s\" \"%s\" are undefined: absolute 0 assumed.",
  2805.           name1, name2);
  2806.     }
  2807.       else
  2808.     {
  2809.       as_warn("Symbol \"%s\" undefined: absolute 0 assumed.",
  2810.           name1 ? name1 : name2);
  2811.     }
  2812.       retval = expP -> X_seg = SEG_ABSOLUTE;
  2813.       expP -> X_add_number   = 0;
  2814.       expP -> X_add_symbol   = expP -> X_subtract_symbol = NULL;
  2815.     }
  2816.  know(   retval == SEG_ABSOLUTE || retval == SEG_DATA || retval == SEG_TEXT || retval == SEG_BSS || retval == SEG_DIFFERENCE );
  2817.   return (retval);
  2818. }                /* get_known_segmented_expression() */
  2819.  
  2820.  
  2821.  
  2822. /* static */ long int /* JF was static, but can't be if the MD pseudos are to use it */
  2823. get_absolute_expression ()
  2824. {
  2825.   expressionS    exp;
  2826.   register segT s;
  2827.  
  2828.   if ( (s = expression(& exp)) != SEG_ABSOLUTE )
  2829.     {
  2830.       if ( s != SEG_NONE )
  2831.     {
  2832.       as_warn( "Bad Absolute Expression, absolute 0 assumed.");
  2833.     }
  2834.       exp . X_add_number = 0;
  2835.     }
  2836.   return (exp . X_add_number);
  2837. }
  2838.  
  2839. static char            /* return terminator */
  2840. get_absolute_expression_and_terminator( val_pointer)
  2841.      long int *        val_pointer; /* return value of expression */
  2842. {
  2843.   * val_pointer = get_absolute_expression ();
  2844.   return ( * input_line_pointer ++ );
  2845. }
  2846.  
  2847. /*
  2848.  *            demand_copy_C_string()
  2849.  *
  2850.  * Like demand_copy_string, but return NULL if the string contains any '\0's.
  2851.  * Give a warning if that happens.
  2852.  */
  2853. static char *
  2854. demand_copy_C_string (len_pointer)
  2855.      int *    len_pointer;
  2856. {
  2857.   register char *    s;
  2858.  
  2859.   if (s = demand_copy_string (len_pointer))
  2860.     {
  2861.       register int    len;
  2862.  
  2863.       for (len = * len_pointer;
  2864.        len > 0;
  2865.        len--)
  2866.     {
  2867.       if (* s == 0)
  2868.         {
  2869.           s = 0;
  2870.           len = 1;
  2871.           * len_pointer = 0;
  2872.           as_warn( "This string may not contain \'\\0\'" );
  2873.         }
  2874.     }
  2875.     }
  2876.   return (s);
  2877. }
  2878.  
  2879. /*
  2880.  *            demand_copy_string()
  2881.  *
  2882.  * Demand string, but return a safe (=private) copy of the string.
  2883.  * Return NULL if we can't read a string here.
  2884.  */
  2885. static char *
  2886. demand_copy_string (lenP)
  2887.      int *    lenP;
  2888. {
  2889.   register int        c;
  2890.   register int        len;
  2891.        char *    retval;
  2892.  
  2893.   len = 0;
  2894.   SKIP_WHITESPACE();
  2895.   if (* input_line_pointer == '\"')
  2896.     {
  2897.       input_line_pointer ++;    /* Skip opening quote. */
  2898.       while ( (c = next_char_of_string()) >= 0 ) {
  2899.       obstack_1grow ( ¬es, c );
  2900.       len ++;
  2901.     }
  2902.       /* JF this next line is so demand_copy_C_string will return a null
  2903.          termanated string. */
  2904.       obstack_1grow(¬es,'\0');
  2905.       retval=obstack_finish( ¬es);
  2906.   } else {
  2907.       as_warn( "Missing string" );
  2908.       retval = NULL;
  2909.       ignore_rest_of_line ();
  2910.     }
  2911.   * lenP = len;
  2912.   return (retval);
  2913. }
  2914.  
  2915. /*
  2916.  *        is_it_end_of_statement()
  2917.  *
  2918.  * In:    Input_line_pointer -> next character.
  2919.  *
  2920.  * Do:    Skip input_line_pointer over all whitespace.
  2921.  *
  2922.  * Out:    TRUE if input_line_pointer -> end-of-line.
  2923.  */
  2924. static int
  2925. is_it_end_of_statement()
  2926. {
  2927.   SKIP_WHITESPACE();
  2928.   return (is_end_of_line [* input_line_pointer]);
  2929. }
  2930.  
  2931. void
  2932. equals(sym_name)
  2933. char *sym_name;
  2934. {
  2935.   register struct symbol * symbolP; /* symbol we are working with */
  2936.  
  2937.   if(sym_name[0]=='.' && sym_name[1]=='\0') {
  2938.     /* Turn '. = mumble' into a .org mumble */
  2939.     register segT segment;
  2940.     expressionS exp;
  2941.     register char *p;
  2942.  
  2943.     if(input_line_pointer[1]=='=')
  2944.       input_line_pointer+=2;
  2945.     else
  2946.       *input_line_pointer++='=';        /* Put it back */
  2947.     if(*input_line_pointer==' ' || *input_line_pointer=='\t')
  2948.         input_line_pointer++;
  2949.     segment = get_known_segmented_expression(& exp);
  2950.     if ( ! need_pass_2 ) {
  2951.       if (segment != now_seg && segment != SEG_ABSOLUTE)
  2952.         as_warn("Illegal segment \"%s\". Segment \"%s\" assumed.",
  2953.                 seg_name [(int) segment], seg_name [(int) now_seg]);
  2954.       p = frag_var (rs_org, 1, 1, (relax_substateT)0, exp.X_add_symbol,
  2955.                     exp.X_add_number, (char *)0);
  2956.       * p = 0;
  2957.     } /* if (ok to make frag) */
  2958.     return;
  2959.   }
  2960.  
  2961.   symbolP=symbol_find_or_make(sym_name);
  2962.   if(input_line_pointer[1]=='=')
  2963.     input_line_pointer+=2;
  2964.   else
  2965.     *input_line_pointer++='=';        /* Put it back */
  2966.   pseudo_set(symbolP);
  2967. }
  2968.  
  2969. #ifdef NeXT    /* the conditional assembly feature (.if, .else, and .endif) */
  2970. void
  2971. s_if()
  2972. /*
  2973.  * DJA -- A pseudo op that does conditional assembly using
  2974.  * assembler defined expressions.
  2975.  */
  2976. {
  2977.     if (if_depth >= MAX_IF_DEPTH)
  2978.         as_fatal ("You can't nest if's more than %d levels deep", MAX_IF_DEPTH);
  2979.     last_states [if_depth++] = the_cond_state;
  2980.     the_cond_state.the_cond = if_cond;
  2981.     if (the_cond_state.ignore)
  2982.       totally_ignore_line ();
  2983.     else
  2984.       {
  2985.         the_cond_state.cond_met = get_absolute_expression ();
  2986.         the_cond_state.ignore = !the_cond_state.cond_met;
  2987.         demand_empty_rest_of_line();
  2988.       }
  2989. }
  2990.  
  2991. void
  2992. s_elseif()
  2993. /*
  2994.  * DJA -- A pseudo op that does conditional assembly using
  2995.  * assembler defined expressions.
  2996.  */
  2997. {
  2998.     register int last_ignore_state;
  2999.  
  3000.     if (the_cond_state.the_cond != if_cond &&
  3001.         the_cond_state.the_cond != elseif_cond)
  3002.         as_fatal ("Encountered a .elseif that doesn't follow a .if "
  3003.               "or an .elseif");
  3004.     the_cond_state.the_cond = elseif_cond;
  3005.  
  3006.     last_ignore_state = FALSE;
  3007.     if (if_depth)
  3008.       last_ignore_state = last_states [if_depth-1].ignore;
  3009.         if (last_ignore_state || the_cond_state.cond_met)
  3010.       {
  3011.         the_cond_state.ignore = TRUE;
  3012.         totally_ignore_line ();
  3013.       }
  3014.     else
  3015.       {
  3016.         the_cond_state.cond_met = get_absolute_expression ();
  3017.         the_cond_state.ignore = !the_cond_state.cond_met;
  3018.         demand_empty_rest_of_line();
  3019.       }
  3020. }
  3021.  
  3022. void
  3023. s_else()
  3024. /*
  3025.  * DJA -- A pseudo op that does conditional assembly using
  3026.  * assembler defined expressions.
  3027.  */
  3028. {
  3029.     register int last_ignore_state;
  3030.  
  3031.     if (the_cond_state.the_cond != if_cond &&
  3032.         the_cond_state.the_cond != elseif_cond)
  3033.         as_fatal ("Encountered a .else that doesn't follow a .if "
  3034.               " or an .elseif");
  3035.     the_cond_state.the_cond = else_cond;
  3036.     last_ignore_state = FALSE;
  3037.     if (if_depth)
  3038.       last_ignore_state = last_states [if_depth-1].ignore;
  3039.         if (last_ignore_state || the_cond_state.cond_met)
  3040.       the_cond_state.ignore = TRUE;
  3041.     else
  3042.       the_cond_state.ignore = FALSE;
  3043.     demand_empty_rest_of_line();
  3044. }
  3045.  
  3046. void
  3047. s_endif()
  3048. /*
  3049.  * DJA -- A pseudo op that does conditional assembly using
  3050.  * assembler defined expressions.
  3051.  */
  3052. {
  3053.     if ((the_cond_state.the_cond == no_cond) || (if_depth == 0))
  3054.         as_fatal ("Encountered a .endif that doesn't follow a .if or .else");
  3055.     the_cond_state = last_states [--if_depth];
  3056.     demand_empty_rest_of_line();
  3057. }
  3058.  
  3059. void
  3060. totally_ignore_line()        /* Ignores lines during conditional assembly. */
  3061. {
  3062.   if ( ! is_end_of_line [* input_line_pointer])
  3063.     {
  3064.       while (   input_line_pointer < buffer_limit
  3065.          && ! is_end_of_line [* input_line_pointer] )
  3066.     {
  3067.       input_line_pointer ++;
  3068.     }
  3069.     }
  3070.   input_line_pointer ++;    /* Return pointing just after end-of-line. */
  3071.   know( is_end_of_line [input_line_pointer [-1]] );
  3072. }
  3073. #endif NeXT    /* the conditional assembly feature (.if, .else, and .endif) */
  3074.  
  3075. #ifdef NeXT    /* the .macro feature */
  3076. void
  3077. s_macros_on()
  3078. {
  3079.     macros_on = TRUE;
  3080.     demand_empty_rest_of_line();
  3081. }
  3082.  
  3083. void
  3084. s_macros_off()
  3085. {
  3086.     macros_on = FALSE;
  3087.     demand_empty_rest_of_line();
  3088. }
  3089.  
  3090. void
  3091. s_macro()
  3092. /*
  3093.  * DJA -- define macros
  3094.  */
  3095. {
  3096.   register int    c;
  3097.   pseudo_typeS *pop;
  3098.  
  3099.   if (macro_name)
  3100.     as_warn ("Can't define a macro inside another macro definition");
  3101.   else
  3102.     {
  3103.       SKIP_WHITESPACE();
  3104.       while (is_part_of_name (c = * input_line_pointer ++))
  3105.     obstack_1grow (¯os, c);
  3106.       obstack_1grow (¯os, '\0');
  3107.       -- input_line_pointer;
  3108.       macro_name = obstack_finish (¯os);
  3109.       if (macro_name == "")
  3110.     as_warn ("Missing name of macro");
  3111.       if(*macro_name == '.')
  3112.     {
  3113.       pop = (pseudo_typeS *)hash_find(po_hash, macro_name+1);
  3114.       if(pop != NULL)
  3115.         as_warn ("Pseudo-op name: %s can't be a macro name", macro_name);
  3116.     }
  3117.     }
  3118.   totally_ignore_line ();
  3119. } /* s_macro */
  3120.  
  3121. void
  3122. s_endmacro()
  3123. /*
  3124.  * DJA -- end macro definition
  3125.  */
  3126. {
  3127.   char *    errorString;
  3128.  
  3129.   if (!macro_name)
  3130.     {
  3131.       as_warn ("This .endmacro does not match with a preceeding .macro");
  3132.       ignore_rest_of_line();
  3133.     }
  3134.   else
  3135.     {
  3136.       obstack_1grow (¯os, '\0');
  3137.       errorString = hash_insert (ma_hash, macro_name, obstack_finish(¯os));
  3138.       if (* errorString)
  3139.         as_warn ("The macro named \"%s\" is already defined", macro_name);
  3140.       macro_name = FALSE;
  3141.     }
  3142. } /* s_endmacro */
  3143.  
  3144. static void
  3145. ma_begin()
  3146. /*
  3147.  * DJA -- initialize macros
  3148.  */
  3149. {
  3150.   ma_hash = hash_new ();
  3151.   obstack_begin (¯os, 5000);
  3152. } /* ma_begin() */
  3153.  
  3154. void
  3155. add_to_macro_definition (char_pointer)
  3156. /*
  3157.  * DJA -- Store the contents of a macro into the obstack
  3158.  */
  3159.   register char * char_pointer;
  3160. {
  3161.   register char c;
  3162.  
  3163.   do
  3164.     {
  3165.       c = * char_pointer ++;
  3166.       know (c != '\0');
  3167.       obstack_1grow (¯os, c);
  3168.     }
  3169.   while ((c != ':') && !(is_end_of_line [c]));
  3170.   if (char_pointer > input_line_pointer)
  3171.     input_line_pointer = char_pointer;
  3172. }
  3173.  
  3174. static
  3175. void
  3176. expand_macro (macro_contents)
  3177. register char * macro_contents;
  3178. /*
  3179.  * DJA -- expand macros
  3180.  */
  3181. {
  3182.   char *    buffer;
  3183.   register char c;
  3184.   register int    index, nargs;
  3185.   char *    last_buffer_limit;
  3186.   int        last_count_lines;
  3187.   char *    last_input_line_pointer;
  3188.   char *    arguments [10]; /* at most 10 arguments, each is substituted */
  3189.  
  3190.   if (macro_depth >= MAX_MACRO_DEPTH)
  3191.      as_fatal ("You can't nest macro's more than %d levels deep",
  3192.         MAX_MACRO_DEPTH);
  3193.   macro_depth++;
  3194.  
  3195.  /* copy each argument to a object in the macro obstack */
  3196.   nargs = 0;
  3197.   for (index = 0; index < 10; index ++)
  3198.     {
  3199.       if (* input_line_pointer == ' ')
  3200.         ++ input_line_pointer;
  3201.       know (* input_line_pointer != ' ');
  3202.       if (is_end_of_line [c = * input_line_pointer])
  3203.     arguments [index] = NULL;
  3204.       else
  3205.     {
  3206.       register int parenthesis_depth = 0;
  3207.       do
  3208.         {
  3209.           c = * input_line_pointer ++;
  3210.           if (parenthesis_depth)
  3211.             {
  3212.           if (c == ')')
  3213.             parenthesis_depth --;
  3214.         }
  3215.           else
  3216.             {
  3217.           if (c == '(')
  3218.             parenthesis_depth ++;
  3219.           else
  3220.             if ( is_end_of_line [c] || (c == ' ') || (c == ',') )
  3221.               break;
  3222.         }
  3223.           know (c != '\0');
  3224.           if (is_end_of_line [c])
  3225.             as_warn ("missmatched parenthesis");
  3226.           obstack_1grow (¯os, c);
  3227.         }
  3228.       while (1);
  3229.       obstack_1grow (¯os, '\0');
  3230.       arguments [index] = obstack_finish (¯os);
  3231.       nargs++;
  3232.       if (is_end_of_line [c])
  3233.         -- input_line_pointer;
  3234.       else if (c == ' ')
  3235.         if (* input_line_pointer == ',')
  3236.           input_line_pointer++;
  3237.     }
  3238.      }
  3239.   if (!is_end_of_line [c])
  3240.     {
  3241.       as_warn ("More than 10 arguments not allowed for macros");
  3242.       ignore_rest_of_line();
  3243.     }
  3244.  /* build a buffer containing the macro contents with arguments substituted */
  3245.   obstack_1grow (¯os, '\n');
  3246.   while (c = * macro_contents ++)
  3247.     {
  3248.       if (c == '$')
  3249.     {
  3250.       if ((*macro_contents >= '0') && (*macro_contents <= '9'))
  3251.         {
  3252.           index = *macro_contents ++ - '0';
  3253.           last_input_line_pointer = macro_contents;
  3254.           macro_contents = arguments [index];
  3255.           if (macro_contents)
  3256.         {
  3257.           while (c = * macro_contents ++)
  3258.           obstack_1grow (¯os, c);
  3259.         }
  3260.           macro_contents = last_input_line_pointer;
  3261.           continue;
  3262.         }
  3263.       else if (*macro_contents == 'n')
  3264.         {
  3265.           macro_contents ++ ;
  3266.           obstack_1grow (¯os, nargs + '0');
  3267.           continue;
  3268.         }
  3269.     }
  3270.       obstack_1grow (¯os, c);
  3271.     }
  3272.   obstack_1grow (¯os, '\n');
  3273.   obstack_1grow (¯os, '\0');
  3274.   last_buffer_limit = buffer_limit;
  3275.   last_count_lines = count_lines;
  3276.   last_input_line_pointer = input_line_pointer;
  3277.   buffer_limit = obstack_next_free (¯os) - 1;
  3278.   buffer = obstack_finish (¯os);
  3279.   count_lines = FALSE;
  3280. /*
  3281. printf("expanded macro: %s", buffer + 1);
  3282. */
  3283.   parse_a_buffer (buffer + 1);
  3284.   obstack_free (¯os, buffer);
  3285.   for (index = 9; index >= 0; index --)
  3286.     if (arguments [index])
  3287.       obstack_free (¯os, arguments [index]);
  3288.   buffer_limit = last_buffer_limit;
  3289.   count_lines = last_count_lines;
  3290.   input_line_pointer = last_input_line_pointer;
  3291.   macro_depth--;
  3292. }
  3293. #endif NeXT    /* the .macro feature */
  3294.  
  3295. #ifdef NeXT    /* the .dump/.load feature */
  3296. void
  3297. s_dump()
  3298. /*
  3299.  * DJA -- A pseudo op that does a quick binary dump of symbol tables.
  3300.  */
  3301. {
  3302.     register char * filename;
  3303.     int        length;
  3304.     static char    null_string [] = "";
  3305.  
  3306.     char *        write_macro ();
  3307.     char *        write_symbol ();
  3308.  
  3309.     /* Some assemblers tolerate immediately following '"' */
  3310.     if ( filename = demand_copy_string( & length ) ) {
  3311.         demand_empty_rest_of_line();
  3312.         if (dump_fp = fopen(filename, "w+"))
  3313.           {
  3314.             hash_apply (ma_hash, write_macro);
  3315.             fwrite (null_string, 1, 1, dump_fp);
  3316.             hash_apply (sy_hash, write_symbol);
  3317.             fwrite (null_string, 1, 1, dump_fp);
  3318.             fclose (dump_fp);
  3319.           }
  3320.         else
  3321.           as_warn ("couldn't write to dump file: \"%s\"", filename);
  3322.     }
  3323. }
  3324.  
  3325. char *
  3326. write_macro (string, value)
  3327. /*
  3328.  * DJA -- Used by hash_apply to write one macro.
  3329.  */
  3330.   register char * string;
  3331.   register char * value;
  3332. {
  3333.   know (string);
  3334.   know (value);
  3335.   know (strlen (string));
  3336.   fwrite (string, (strlen (string) + 1), 1, dump_fp);
  3337.   fwrite (value, (strlen (value) + 1), 1, dump_fp);
  3338.   return NULL;
  3339. }
  3340.  
  3341. char *
  3342. write_symbol (string, symbolP)
  3343. /*
  3344.  * DJA -- Used by hash_apply to write one N_ABS symbol and its value.
  3345.  */
  3346.   register char          * string;
  3347.   register symbolS    * symbolP;
  3348. {
  3349.   know (symbolP);
  3350.   if (((symbolP -> sy_type) & N_TYPE) == N_ABS)
  3351.     {
  3352.       know (string);
  3353.       know (strlen (string));
  3354.       fwrite (string, (strlen (string) + 1), 1, dump_fp);
  3355.       fwrite (& (symbolP -> sy_value), 4, 1, dump_fp);
  3356.     }
  3357.   return NULL;
  3358. }
  3359.  
  3360. void
  3361. s_load()
  3362. /*
  3363.  * DJA -- A pseudo op that does a quick binary load of symbol tables.
  3364.  */
  3365. {
  3366.   register char        * char_pointer;
  3367.   register char        * filename;
  3368.   int              length;
  3369.   register char          the_char;
  3370.   register symbolS    * the_symbol;
  3371.   symbolS        * temp_symbol_lastP;
  3372.   static symbolS    * dump_symbol_lastP;
  3373.  
  3374.   extern symbolS    * symbol_find_or_make ();
  3375.  
  3376.   /* Some assemblers tolerate immediately following '"' */
  3377.   if ( filename = demand_copy_string( & length ) )
  3378.     {
  3379.       demand_empty_rest_of_line();
  3380.       if (dump_fp = fopen(filename, "r+"))
  3381.     {
  3382.       do
  3383.         {
  3384.           do
  3385.         {
  3386.           the_char = getc (dump_fp);
  3387.           obstack_1grow (¯os, the_char);
  3388.         }
  3389.           while (the_char);
  3390.           char_pointer = obstack_finish (¯os);
  3391.           if (!(*char_pointer))
  3392.             break;
  3393.           do
  3394.         {
  3395.           the_char = getc (dump_fp);
  3396.           obstack_1grow (¯os, the_char);
  3397.         }
  3398.           while (the_char);
  3399.           if (* hash_insert (ma_hash, char_pointer, obstack_finish(¯os)))
  3400.         as_warn ("a macro named \"%s\" encountered in a .load is already defined", char_pointer);
  3401.         }
  3402.       while (1);
  3403.      /*
  3404.       * We don't want to link in symbols that were loaded so they don't go out in the
  3405.       * object file.  Instead these symbols should go out in the object file that did
  3406.       * the .dump
  3407.       */
  3408.       temp_symbol_lastP = symbol_lastP;
  3409.       symbol_lastP = dump_symbol_lastP;
  3410.       do
  3411.         {
  3412.           do
  3413.         {
  3414.           the_char = getc (dump_fp);
  3415.           obstack_1grow (¯os, the_char);
  3416.         }
  3417.           while (the_char);
  3418.           char_pointer = obstack_base (¯os);
  3419.           obstack_next_free (¯os) = char_pointer;
  3420.           if (!(*char_pointer))
  3421.             break;
  3422.           the_symbol = symbol_find_or_make (char_pointer);
  3423.           the_symbol -> sy_type = N_ABS;
  3424.           char_pointer = (char *) &the_symbol -> sy_value;
  3425.           * char_pointer ++ = getc (dump_fp);
  3426.           * char_pointer ++ = getc (dump_fp);
  3427.           * char_pointer ++ = getc (dump_fp);
  3428.           * char_pointer ++ = getc (dump_fp);
  3429.           the_symbol -> sy_frag = & zero_address_frag;
  3430.         }
  3431.       while (1);
  3432.       dump_symbol_lastP = symbol_lastP;
  3433.       symbol_lastP = temp_symbol_lastP;
  3434.       fclose (dump_fp);
  3435.     }
  3436.       else
  3437.       as_fatal ("Couldn't find the dump file: \"%s\"", filename);
  3438.     }
  3439. }
  3440. #endif NeXT    /* the .dump/.load feature */
  3441. /* end: read.c */
  3442.