1 /* gasp.c - Gnu assembler preprocessor main program.
2 Copyright (C) 1994, 95, 96, 97, 1998 Free Software Foundation, Inc.
4 Written by Steve and Judy Chamberlain of Cygnus Support,
7 This file is part of GASP, the GNU Assembler Preprocessor.
9 GASP is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
14 GASP is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with GASP; see the file COPYING. If not, write to the Free
21 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
26 This program translates the input macros and stuff into a form
27 suitable for gas to consume.
30 gasp [-sdhau] [-c char] [-o <outfile>] <infile>*
32 -s copy source to output
33 -c <char> comments are started with <char> instead of !
34 -u allow unreasonable stuff
36 -d print debugging stats
37 -s semi colons start comments
38 -a use alternate syntax
39 Pseudo ops can start with or without a .
40 Labels have to be in first column.
41 -I specify include dir
42 Macro arg parameters subsituted by name, don't need the &.
43 String can start with ' too.
44 Strings can be surrounded by <..>
45 A %<exp> in a string evaluates the expression
46 Literal char in a string with !
62 #ifdef NEED_MALLOC_DECLARATION
63 extern char *malloc ();
67 #include "libiberty.h"
71 char *program_version
= "1.2";
73 /* This is normally declared in as.h, but we don't include that. We
74 need the function because other files linked with gasp.c might call
76 extern void as_abort
PARAMS ((const char *, int, const char *));
78 #define MAX_INCLUDES 30 /* Maximum include depth */
79 #define MAX_REASONABLE 1000 /* Maximum number of expansions */
81 int unreasonable
; /* -u on command line */
82 int stats
; /* -d on command line */
83 int print_line_number
; /* -p flag on command line */
84 int copysource
; /* -c flag on command line */
85 int warnings
; /* Number of WARNINGs generated so far. */
86 int errors
; /* Number of ERRORs generated so far. */
87 int fatals
; /* Number of fatal ERRORs generated so far (either 0 or 1). */
88 int alternate
= 0; /* -a on command line */
89 int mri
= 0; /* -M on command line */
90 char comment_char
= '!';
91 int radix
= 10; /* Default radix */
93 int had_end
; /* Seen .END */
95 /* The output stream */
98 /* the attributes of each character are stored as a bit pattern
99 chartype, which gives us quick tests. */
106 #define COMMENTBIT 16
108 #define ISCOMMENTCHAR(x) (chartype[(unsigned)(x)] & COMMENTBIT)
109 #define ISFIRSTCHAR(x) (chartype[(unsigned)(x)] & FIRSTBIT)
110 #define ISNEXTCHAR(x) (chartype[(unsigned)(x)] & NEXTBIT)
111 #define ISSEP(x) (chartype[(unsigned)(x)] & SEPBIT)
112 #define ISWHITE(x) (chartype[(unsigned)(x)] & WHITEBIT)
113 #define ISBASE(x) (chartype[(unsigned)(x)] & BASEBIT)
114 static char chartype
[256];
117 /* Conditional assembly uses the `ifstack'. Each aif pushes another
118 entry onto the stack, and sets the on flag if it should. The aelse
119 sets hadelse, and toggles on. An aend pops a level. We limit to
120 100 levels of nesting, not because we're facists pigs with read
121 only minds, but because more than 100 levels of nesting is probably
122 a bug in the user's macro structure. */
124 #define IFNESTING 100
127 int on
; /* is the level being output */
128 int hadelse
; /* has an aelse been seen */
133 /* The final and intermediate results of expression evaluation are kept in
134 exp_t's. Note that a symbol is not an sb, but a pointer into the input
135 line. It must be coped somewhere safe before the next line is read in. */
146 int value
; /* constant part */
147 symbol add_symbol
; /* name part */
148 symbol sub_symbol
; /* name part */
153 /* Hashing is done in a pretty standard way. A hash_table has a
154 pointer to a vector of pointers to hash_entrys, and the size of the
155 vector. A hash_entry contains a union of all the info we like to
156 store in hash table. If there is a hash collision, hash_entries
157 with the same hash are kept in a chain. */
159 /* What the data in a hash_entry means */
162 hash_integer
, /* name->integer mapping */
163 hash_string
, /* name->string mapping */
164 hash_macro
, /* name is a macro */
165 hash_formal
/* name is a formal argument */
170 sb key
; /* symbol name */
171 hash_type type
; /* symbol meaning */
176 struct macro_struct
*m
;
177 struct formal_struct
*f
;
179 struct hs
*next
; /* next hash_entry with same hash key */
189 /* Structures used to store macros.
191 Each macro knows its name and included text. It gets built with a
192 list of formal arguments, and also keeps a hash table which points
193 into the list to speed up formal search. Each formal knows its
194 name and its default value. Each time the macro is expanded, the
195 formals get the actual values attatched to them. */
197 /* describe the formal arguments to a macro */
199 typedef struct formal_struct
201 struct formal_struct
*next
; /* next formal in list */
202 sb name
; /* name of the formal */
203 sb def
; /* the default value */
204 sb actual
; /* the actual argument (changed on each expansion) */
205 int index
; /* the index of the formal 0..formal_count-1 */
209 /* describe the macro. */
211 typedef struct macro_struct
213 sb sub
; /* substitution text. */
214 int formal_count
; /* number of formal args. */
215 formal_entry
*formals
; /* pointer to list of formal_structs */
216 hash_table formal_hash
; /* hash table of formals. */
220 /* how we nest files and expand macros etc.
222 we keep a stack of of include_stack structs. each include file
223 pushes a new level onto the stack. we keep an sb with a pushback
224 too. unget chars are pushed onto the pushback sb, getchars first
225 checks the pushback sb before reading from the input stream.
227 small things are expanded by adding the text of the item onto the
228 pushback sb. larger items are grown by pushing a new level and
229 allocating the entire pushback buf for the item. each time
230 something like a macro is expanded, the stack index is changed. we
231 can then perform an exitm by popping all entries off the stack with
232 the same stack index. if we're being reasonable, we can detect
233 recusive expansion by checking the index is reasonably small.
238 include_file
, include_repeat
, include_while
, include_macro
243 sb pushback
; /* current pushback stream */
244 int pushback_index
; /* next char to read from stream */
245 FILE *handle
; /* open file */
246 sb name
; /* name of file */
247 int linecount
; /* number of lines read so far */
249 int index
; /* index of this layer */
251 include_stack
[MAX_INCLUDES
];
253 struct include_stack
*sp
;
254 #define isp (sp - include_stack)
256 /* Include file list */
258 typedef struct include_path
260 struct include_path
*next
;
264 include_path
*paths_head
;
265 include_path
*paths_tail
;
268 static void quit
PARAMS ((void));
269 static void hash_new_table
PARAMS ((int, hash_table
*));
270 static int hash
PARAMS ((sb
*));
271 static hash_entry
*hash_create
PARAMS ((hash_table
*, sb
*));
272 static void hash_add_to_string_table
PARAMS ((hash_table
*, sb
*, sb
*, int));
273 static void hash_add_to_int_table
PARAMS ((hash_table
*, sb
*, int));
274 static hash_entry
*hash_lookup
PARAMS ((hash_table
*, sb
*));
275 static void checkconst
PARAMS ((int, exp_t
*));
276 static int sb_strtol
PARAMS ((int, sb
*, int, int *));
277 static int level_0
PARAMS ((int, sb
*, exp_t
*));
278 static int level_1
PARAMS ((int, sb
*, exp_t
*));
279 static int level_2
PARAMS ((int, sb
*, exp_t
*));
280 static int level_3
PARAMS ((int, sb
*, exp_t
*));
281 static int level_4
PARAMS ((int, sb
*, exp_t
*));
282 static int level_5
PARAMS ((int, sb
*, exp_t
*));
283 static int exp_parse
PARAMS ((int, sb
*, exp_t
*));
284 static void exp_string
PARAMS ((exp_t
*, sb
*));
285 static int exp_get_abs
PARAMS ((const char *, int, sb
*, int *));
287 static void strip_comments
PARAMS ((sb
*));
289 static void unget
PARAMS ((int));
290 static void include_buf
PARAMS ((sb
*, sb
*, include_type
, int));
291 static void include_print_where_line
PARAMS ((FILE *));
292 static void include_print_line
PARAMS ((FILE *));
293 static int get_line
PARAMS ((sb
*));
294 static int grab_label
PARAMS ((sb
*, sb
*));
295 static void change_base
PARAMS ((int, sb
*, sb
*));
296 static void do_end
PARAMS ((sb
*));
297 static void do_assign
PARAMS ((int, int, sb
*));
298 static void do_radix
PARAMS ((sb
*));
299 static int get_opsize
PARAMS ((int, sb
*, int *));
300 static int eol
PARAMS ((int, sb
*));
301 static void do_data
PARAMS ((int, sb
*, int));
302 static void do_datab
PARAMS ((int, sb
*));
303 static void do_align
PARAMS ((int, sb
*));
304 static void do_res
PARAMS ((int, sb
*, int));
305 static void do_export
PARAMS ((sb
*));
306 static void do_print
PARAMS ((int, sb
*));
307 static void do_heading
PARAMS ((int, sb
*));
308 static void do_page
PARAMS ((void));
309 static void do_form
PARAMS ((int, sb
*));
310 static int get_any_string
PARAMS ((int, sb
*, sb
*, int, int));
311 static int skip_openp
PARAMS ((int, sb
*));
312 static int skip_closep
PARAMS ((int, sb
*));
313 static int dolen
PARAMS ((int, sb
*, sb
*));
314 static int doinstr
PARAMS ((int, sb
*, sb
*));
315 static int dosubstr
PARAMS ((int, sb
*, sb
*));
316 static void process_assigns
PARAMS ((int, sb
*, sb
*));
317 static int get_and_process
PARAMS ((int, sb
*, sb
*));
318 static void process_file
PARAMS ((void));
319 static void free_old_entry
PARAMS ((hash_entry
*));
320 static void do_assigna
PARAMS ((int, sb
*));
321 static void do_assignc
PARAMS ((int, sb
*));
322 static void do_reg
PARAMS ((int, sb
*));
323 static int condass_lookup_name
PARAMS ((sb
*, int, sb
*, int));
324 static int whatcond
PARAMS ((int, sb
*, int *));
325 static int istrue
PARAMS ((int, sb
*));
326 static void do_aif
PARAMS ((int, sb
*));
327 static void do_aelse
PARAMS ((void));
328 static void do_aendi
PARAMS ((void));
329 static int condass_on
PARAMS ((void));
330 static void do_if
PARAMS ((int, sb
*, int));
331 static int get_mri_string
PARAMS ((int, sb
*, sb
*, int));
332 static void do_ifc
PARAMS ((int, sb
*, int));
333 static void do_aendr
PARAMS ((void));
334 static void do_awhile
PARAMS ((int, sb
*));
335 static void do_aendw
PARAMS ((void));
336 static void do_exitm
PARAMS ((void));
337 static void do_arepeat
PARAMS ((int, sb
*));
338 static void do_endm
PARAMS ((void));
339 static void do_irp
PARAMS ((int, sb
*, int));
340 static void do_local
PARAMS ((int, sb
*));
341 static void do_macro
PARAMS ((int, sb
*));
342 static int macro_op
PARAMS ((int, sb
*));
343 static int getstring
PARAMS ((int, sb
*, sb
*));
344 static void do_sdata
PARAMS ((int, sb
*, int));
345 static void do_sdatab
PARAMS ((int, sb
*));
346 static int new_file
PARAMS ((const char *));
347 static void do_include
PARAMS ((int, sb
*));
348 static void include_pop
PARAMS ((void));
349 static int get
PARAMS ((void));
350 static int linecount
PARAMS ((void));
351 static int include_next_index
PARAMS ((void));
352 static void chartype_init
PARAMS ((void));
353 static int process_pseudo_op
PARAMS ((int, sb
*, sb
*));
354 static void add_keyword
PARAMS ((const char *, int));
355 static void process_init
PARAMS ((void));
356 static void do_define
PARAMS ((const char *));
357 static void show_usage
PARAMS ((FILE *, int));
358 static void show_help
PARAMS ((void));
361 do { include_print_where_line (stderr); fprintf x ; fatals++; quit(); } while(0)
363 do { include_print_where_line (stderr); fprintf x; errors++; } while(0)
365 do { include_print_where_line (stderr); fprintf x; warnings++;} while(0)
369 /* exit the program and return the right ERROR code. */
382 for (i
= 0; i
< sb_max_power_two
; i
++)
384 fprintf (stderr
, "strings size %8d : %d\n", 1<<i
, string_count
[i
]);
390 /* hash table maintenance. */
392 /* build a new hash table with size buckets, and fill in the info at ptr. */
395 hash_new_table (size
, ptr
)
401 ptr
->table
= (hash_entry
**) xmalloc (size
* (sizeof (hash_entry
*)));
402 /* Fill with null-pointer, not zero-bit-pattern. */
403 for (i
= 0; i
< size
; i
++)
407 /* calculate and return the hash value of the sb at key. */
416 for (i
= 0; i
< key
->len
; i
++)
424 /* lookup key in hash_table tab, if present, then return it, otherwise
425 build a new one and fill it with hash_integer. */
429 hash_create (tab
, key
)
433 int k
= hash (key
) % tab
->size
;
435 hash_entry
**table
= tab
->table
;
443 hash_entry
*n
= (hash_entry
*) xmalloc (sizeof (hash_entry
));
446 sb_add_sb (&n
->key
, key
);
448 n
->type
= hash_integer
;
451 if (strncmp (table
[k
]->key
.ptr
, key
->ptr
, key
->len
) == 0)
459 /* add sb name with key into hash_table tab. if replacing old value
460 and again, then ERROR. */
464 hash_add_to_string_table (tab
, key
, name
, again
)
470 hash_entry
*ptr
= hash_create (tab
, key
);
471 if (ptr
->type
== hash_integer
)
473 sb_new (&ptr
->value
.s
);
475 if (ptr
->value
.s
.len
)
478 ERROR ((stderr
, "redefinition not allowed\n"));
481 ptr
->type
= hash_string
;
482 sb_reset (&ptr
->value
.s
);
484 sb_add_sb (&ptr
->value
.s
, name
);
487 /* add integer name to hash_table tab with sb key. */
491 hash_add_to_int_table (tab
, key
, name
)
496 hash_entry
*ptr
= hash_create (tab
, key
);
500 /* lookup sb key in hash_table tab. if found return hash_entry result,
505 hash_lookup (tab
, key
)
509 int k
= hash (key
) % tab
->size
;
510 hash_entry
**table
= tab
->table
;
511 hash_entry
*p
= table
[k
];
514 if (p
->key
.len
== key
->len
515 && strncmp (p
->key
.ptr
, key
->ptr
, key
->len
) == 0)
525 are handled in a really simple recursive decent way. each bit of
526 the machine takes an index into an sb and a pointer to an exp_t,
527 modifies the *exp_t and returns the index of the first character
528 past the part of the expression parsed.
530 expression precedence:
541 /* make sure that the exp_t at term is constant, if not the give the op ERROR. */
545 checkconst (op
, term
)
549 if (term
->add_symbol
.len
550 || term
->sub_symbol
.len
)
552 ERROR ((stderr
, "the %c operator cannot take non-absolute arguments.\n", op
));
556 /* turn the number in string at idx into a number of base,
557 fill in ptr and return the index of the first character not in the
562 sb_strtol (idx
, string
, base
, ptr
)
569 idx
= sb_skip_white (idx
, string
);
571 while (idx
< string
->len
)
573 int ch
= string
->ptr
[idx
];
577 else if (ch
>= 'a' && ch
<= 'f')
579 else if (ch
>= 'A' && ch
<= 'F')
587 value
= value
* base
+ dig
;
595 level_0 (idx
, string
, lhs
)
600 lhs
->add_symbol
.len
= 0;
601 lhs
->add_symbol
.name
= 0;
603 lhs
->sub_symbol
.len
= 0;
604 lhs
->sub_symbol
.name
= 0;
606 idx
= sb_skip_white (idx
, string
);
610 if (isdigit (string
->ptr
[idx
]))
612 idx
= sb_strtol (idx
, string
, 10, &lhs
->value
);
614 else if (ISFIRSTCHAR (string
->ptr
[idx
]))
617 lhs
->add_symbol
.name
= string
->ptr
+ idx
;
618 while (idx
< string
->len
&& ISNEXTCHAR (string
->ptr
[idx
]))
623 lhs
->add_symbol
.len
= len
;
625 else if (string
->ptr
[idx
] == '"')
629 ERROR ((stderr
, "string where expression expected.\n"));
630 idx
= getstring (idx
, string
, &acc
);
635 ERROR ((stderr
, "can't find primary in expression.\n"));
638 return sb_skip_white (idx
, string
);
644 level_1 (idx
, string
, lhs
)
649 idx
= sb_skip_white (idx
, string
);
651 switch (string
->ptr
[idx
])
654 idx
= level_1 (idx
+ 1, string
, lhs
);
657 idx
= level_1 (idx
+ 1, string
, lhs
);
658 checkconst ('~', lhs
);
659 lhs
->value
= ~lhs
->value
;
664 idx
= level_1 (idx
+ 1, string
, lhs
);
665 lhs
->value
= -lhs
->value
;
667 lhs
->add_symbol
= lhs
->sub_symbol
;
673 idx
= level_5 (sb_skip_white (idx
, string
), string
, lhs
);
674 if (string
->ptr
[idx
] != ')')
675 ERROR ((stderr
, "misplaced closing parens.\n"));
680 idx
= level_0 (idx
, string
, lhs
);
683 return sb_skip_white (idx
, string
);
687 level_2 (idx
, string
, lhs
)
694 idx
= level_1 (idx
, string
, lhs
);
696 while (idx
< string
->len
&& (string
->ptr
[idx
] == '*'
697 || string
->ptr
[idx
] == '/'))
699 char op
= string
->ptr
[idx
++];
700 idx
= level_1 (idx
, string
, &rhs
);
704 checkconst ('*', lhs
);
705 checkconst ('*', &rhs
);
706 lhs
->value
*= rhs
.value
;
709 checkconst ('/', lhs
);
710 checkconst ('/', &rhs
);
712 ERROR ((stderr
, "attempt to divide by zero.\n"));
714 lhs
->value
/= rhs
.value
;
718 return sb_skip_white (idx
, string
);
723 level_3 (idx
, string
, lhs
)
730 idx
= level_2 (idx
, string
, lhs
);
732 while (idx
< string
->len
733 && (string
->ptr
[idx
] == '+'
734 || string
->ptr
[idx
] == '-'))
736 char op
= string
->ptr
[idx
++];
737 idx
= level_2 (idx
, string
, &rhs
);
741 lhs
->value
+= rhs
.value
;
742 if (lhs
->add_symbol
.name
&& rhs
.add_symbol
.name
)
744 ERROR ((stderr
, "can't add two relocatable expressions\n"));
746 /* change nn+symbol to symbol + nn */
747 if (rhs
.add_symbol
.name
)
749 lhs
->add_symbol
= rhs
.add_symbol
;
753 lhs
->value
-= rhs
.value
;
754 lhs
->sub_symbol
= rhs
.add_symbol
;
758 return sb_skip_white (idx
, string
);
762 level_4 (idx
, string
, lhs
)
769 idx
= level_3 (idx
, string
, lhs
);
771 while (idx
< string
->len
&&
772 string
->ptr
[idx
] == '&')
774 char op
= string
->ptr
[idx
++];
775 idx
= level_3 (idx
, string
, &rhs
);
779 checkconst ('&', lhs
);
780 checkconst ('&', &rhs
);
781 lhs
->value
&= rhs
.value
;
785 return sb_skip_white (idx
, string
);
789 level_5 (idx
, string
, lhs
)
796 idx
= level_4 (idx
, string
, lhs
);
798 while (idx
< string
->len
799 && (string
->ptr
[idx
] == '|' || string
->ptr
[idx
] == '~'))
801 char op
= string
->ptr
[idx
++];
802 idx
= level_4 (idx
, string
, &rhs
);
806 checkconst ('|', lhs
);
807 checkconst ('|', &rhs
);
808 lhs
->value
|= rhs
.value
;
811 checkconst ('~', lhs
);
812 checkconst ('~', &rhs
);
813 lhs
->value
^= rhs
.value
;
817 return sb_skip_white (idx
, string
);
821 /* parse the expression at offset idx into string, fill up res with
822 the result. return the index of the first char past the expression.
826 exp_parse (idx
, string
, res
)
831 return level_5 (sb_skip_white (idx
, string
), string
, res
);
835 /* turn the expression at exp into text and glue it onto the end of
839 exp_string (exp
, string
)
847 if (exp
->add_symbol
.len
)
849 sb_add_buffer (string
, exp
->add_symbol
.name
, exp
->add_symbol
.len
);
857 sb_add_char (string
, '+');
858 sprintf (buf
, "%d", exp
->value
);
859 sb_add_string (string
, buf
);
863 if (exp
->sub_symbol
.len
)
865 sb_add_char (string
, '-');
866 sb_add_buffer (string
, exp
->add_symbol
.name
, exp
->add_symbol
.len
);
872 sb_add_char (string
, '0');
876 /* parse the expression at offset idx into sb in, return the value in val.
877 if the expression is not constant, give ERROR emsg. returns the index
878 of the first character past the end of the expression. */
881 exp_get_abs (emsg
, idx
, in
, val
)
888 idx
= exp_parse (idx
, in
, &res
);
889 if (res
.add_symbol
.len
|| res
.sub_symbol
.len
)
890 ERROR ((stderr
, emsg
));
896 sb label
; /* current label parsed from line */
897 hash_table assign_hash_table
; /* hash table for all assigned variables */
898 hash_table keyword_hash_table
; /* hash table for keyword */
899 hash_table vars
; /* hash table for eq variables */
901 #define in_comment ';'
910 for (i
= 0; i
< out
->len
; i
++)
912 if (ISCOMMENTCHAR(s
[i
]))
921 /* push back character ch so that it can be read again. */
931 if (sp
->pushback_index
)
932 sp
->pushback_index
--;
934 sb_add_char (&sp
->pushback
, ch
);
937 /* push the sb ptr onto the include stack, with the given name, type and index. */
941 include_buf (name
, ptr
, type
, index
)
948 if (sp
- include_stack
>= MAX_INCLUDES
)
949 FATAL ((stderr
, "unreasonable nesting.\n"));
951 sb_add_sb (&sp
->name
, name
);
954 sp
->pushback_index
= 0;
957 sb_new (&sp
->pushback
);
958 sb_add_sb (&sp
->pushback
, ptr
);
962 /* used in ERROR messages, print info on where the include stack is onto file. */
965 include_print_where_line (file
)
968 struct include_stack
*p
= include_stack
+ 1;
972 fprintf (file
, "%s:%d ", sb_name (&p
->name
), p
->linecount
- 1);
977 /* used in listings, print the line number onto file. */
979 include_print_line (file
)
983 struct include_stack
*p
= include_stack
+ 1;
985 n
= fprintf (file
, "%4d", p
->linecount
);
989 n
+= fprintf (file
, ".%d", p
->linecount
);
1000 /* read a line from the top of the include stack into sb in. */
1011 putc (comment_char
, outfile
);
1012 if (print_line_number
)
1013 include_print_line (outfile
);
1027 WARNING ((stderr
, "End of file not at start of line.\n"));
1029 putc ('\n', outfile
);
1048 /* continued line */
1051 putc (comment_char
, outfile
);
1052 putc ('+', outfile
);
1065 sb_add_char (in
, ch
);
1073 /* find a label from sb in and put it in out. */
1076 grab_label (in
, out
)
1082 if (ISFIRSTCHAR (in
->ptr
[i
]))
1084 sb_add_char (out
, in
->ptr
[i
]);
1086 while ((ISNEXTCHAR (in
->ptr
[i
])
1087 || in
->ptr
[i
] == '\\'
1088 || in
->ptr
[i
] == '&')
1091 sb_add_char (out
, in
->ptr
[i
]);
1098 /* find all strange base stuff and turn into decimal. also
1099 find all the other numbers and convert them from the default radix */
1102 change_base (idx
, in
, out
)
1109 while (idx
< in
->len
)
1111 if (in
->ptr
[idx
] == '\\'
1112 && idx
+ 1 < in
->len
1113 && in
->ptr
[idx
+ 1] == '(')
1116 while (idx
< in
->len
1117 && in
->ptr
[idx
] != ')')
1119 sb_add_char (out
, in
->ptr
[idx
]);
1125 else if (idx
< in
->len
- 1 && in
->ptr
[idx
+ 1] == '\'' && ! mri
)
1129 switch (in
->ptr
[idx
])
1148 ERROR ((stderr
, "Illegal base character %c.\n", in
->ptr
[idx
]));
1153 idx
= sb_strtol (idx
+ 2, in
, base
, &value
);
1154 sprintf (buffer
, "%d", value
);
1155 sb_add_string (out
, buffer
);
1157 else if (ISFIRSTCHAR (in
->ptr
[idx
]))
1159 /* copy entire names through quickly */
1160 sb_add_char (out
, in
->ptr
[idx
]);
1162 while (idx
< in
->len
&& ISNEXTCHAR (in
->ptr
[idx
]))
1164 sb_add_char (out
, in
->ptr
[idx
]);
1168 else if (isdigit (in
->ptr
[idx
]))
1171 /* all numbers must start with a digit, let's chew it and
1173 idx
= sb_strtol (idx
, in
, radix
, &value
);
1174 sprintf (buffer
, "%d", value
);
1175 sb_add_string (out
, buffer
);
1177 /* skip all undigsested letters */
1178 while (idx
< in
->len
&& ISNEXTCHAR (in
->ptr
[idx
]))
1180 sb_add_char (out
, in
->ptr
[idx
]);
1184 else if (in
->ptr
[idx
] == '"' || in
->ptr
[idx
] == '\'')
1186 char tchar
= in
->ptr
[idx
];
1187 /* copy entire names through quickly */
1188 sb_add_char (out
, in
->ptr
[idx
]);
1190 while (idx
< in
->len
&& in
->ptr
[idx
] != tchar
)
1192 sb_add_char (out
, in
->ptr
[idx
]);
1198 /* nothing special, just pass it through */
1199 sb_add_char (out
, in
->ptr
[idx
]);
1213 fprintf (outfile
, "%s\n", sb_name (in
));
1219 do_assign (again
, idx
, in
)
1224 /* stick label in symbol table with following value */
1229 idx
= exp_parse (idx
, in
, &e
);
1230 exp_string (&e
, &acc
);
1231 hash_add_to_string_table (&assign_hash_table
, &label
, &acc
, again
);
1236 /* .radix [b|q|d|h] */
1243 int idx
= sb_skip_white (0, ptr
);
1244 switch (ptr
->ptr
[idx
])
1263 ERROR ((stderr
, "radix is %c must be one of b, q, d or h", radix
));
1268 /* Parse off a .b, .w or .l */
1271 get_opsize (idx
, in
, size
)
1277 if (in
->ptr
[idx
] == '.')
1281 switch (in
->ptr
[idx
])
1299 ERROR ((stderr
, "size must be one of b, w or l, is %c.\n", in
->ptr
[idx
]));
1312 idx
= sb_skip_white (idx
, line
);
1314 && ISCOMMENTCHAR(line
->ptr
[idx
]))
1316 if (idx
>= line
->len
)
1321 /* .data [.b|.w|.l] <data>*
1322 or d[bwl] <data>* */
1325 do_data (idx
, in
, size
)
1331 char *opname
= ".yikes!";
1337 idx
= get_opsize (idx
, in
, &opsize
);
1356 fprintf (outfile
, "%s\t", opname
);
1358 idx
= sb_skip_white (idx
, in
);
1362 && in
->ptr
[idx
] == '"')
1365 idx
= getstring (idx
, in
, &acc
);
1366 for (i
= 0; i
< acc
.len
; i
++)
1369 fprintf(outfile
,",");
1370 fprintf (outfile
, "%d", acc
.ptr
[i
]);
1375 while (!eol (idx
, in
))
1378 idx
= exp_parse (idx
, in
, &e
);
1379 exp_string (&e
, &acc
);
1380 sb_add_char (&acc
, 0);
1381 fprintf (outfile
, acc
.ptr
);
1382 if (idx
< in
->len
&& in
->ptr
[idx
] == ',')
1384 fprintf (outfile
, ",");
1390 sb_print_at (outfile
, idx
, in
);
1391 fprintf (outfile
, "\n");
1394 /* .datab [.b|.w|.l] <repeat>,<fill> */
1405 idx
= get_opsize (idx
, in
, &opsize
);
1407 idx
= exp_get_abs ("datab repeat must be constant.\n", idx
, in
, &repeat
);
1408 idx
= sb_skip_comma (idx
, in
);
1409 idx
= exp_get_abs ("datab data must be absolute.\n", idx
, in
, &fill
);
1411 fprintf (outfile
, ".fill\t%d,%d,%d\n", repeat
, opsize
, fill
);
1421 int al
, have_fill
, fill
;
1423 idx
= exp_get_abs ("align needs absolute expression.\n", idx
, in
, &al
);
1424 idx
= sb_skip_white (idx
, in
);
1427 if (! eol (idx
, in
))
1429 idx
= sb_skip_comma (idx
, in
);
1430 idx
= exp_get_abs (".align needs absolute fill value.\n", idx
, in
,
1438 WARNING ((stderr
, "alignment must be one of 1, 2 or 4.\n"));
1440 fprintf (outfile
, ".align %d", al
);
1442 fprintf (outfile
, ",%d", fill
);
1443 fprintf (outfile
, "\n");
1446 /* .res[.b|.w|.l] <size> */
1449 do_res (idx
, in
, type
)
1457 idx
= get_opsize (idx
, in
, &size
);
1458 while (!eol(idx
, in
))
1460 idx
= sb_skip_white (idx
, in
);
1461 if (in
->ptr
[idx
] == ',')
1463 idx
= exp_get_abs ("res needs absolute expression for fill count.\n", idx
, in
, &count
);
1465 if (type
== 'c' || type
== 'z')
1468 fprintf (outfile
, ".space %d\n", count
* size
);
1479 fprintf (outfile
, ".global %s\n", sb_name (in
));
1482 /* .print [list] [nolist] */
1489 idx
= sb_skip_white (idx
, in
);
1490 while (idx
< in
->len
)
1492 if (strncasecmp (in
->ptr
+ idx
, "LIST", 4) == 0)
1494 fprintf (outfile
, ".list\n");
1497 else if (strncasecmp (in
->ptr
+ idx
, "NOLIST", 6) == 0)
1499 fprintf (outfile
, ".nolist\n");
1508 do_heading (idx
, in
)
1514 idx
= getstring (idx
, in
, &head
);
1515 fprintf (outfile
, ".title \"%s\"\n", sb_name (&head
));
1524 fprintf (outfile
, ".eject\n");
1527 /* .form [lin=<value>] [col=<value>] */
1535 idx
= sb_skip_white (idx
, in
);
1537 while (idx
< in
->len
)
1540 if (strncasecmp (in
->ptr
+ idx
, "LIN=", 4) == 0)
1543 idx
= exp_get_abs ("form LIN= needs absolute expresssion.\n", idx
, in
, &lines
);
1546 if (strncasecmp (in
->ptr
+ idx
, "COL=", 4) == 0)
1549 idx
= exp_get_abs ("form COL= needs absolute expresssion.\n", idx
, in
, &columns
);
1554 fprintf (outfile
, ".psize %d,%d\n", lines
, columns
);
1559 /* Fetch string from the input stream,
1561 'Bxyx<whitespace> -> return 'Bxyza
1562 %<char> -> return string of decimal value of x
1563 "<string>" -> return string
1564 xyx<whitespace> -> return xyz
1567 get_any_string (idx
, in
, out
, expand
, pretend_quoted
)
1575 idx
= sb_skip_white (idx
, in
);
1579 if (in
->len
> 2 && in
->ptr
[idx
+1] == '\'' && ISBASE (in
->ptr
[idx
]))
1581 while (!ISSEP (in
->ptr
[idx
]))
1582 sb_add_char (out
, in
->ptr
[idx
++]);
1584 else if (in
->ptr
[idx
] == '%'
1590 /* Turns the next expression into a string */
1591 idx
= exp_get_abs ("% operator needs absolute expression",
1595 sprintf(buf
, "%d", val
);
1596 sb_add_string (out
, buf
);
1598 else if (in
->ptr
[idx
] == '"'
1599 || in
->ptr
[idx
] == '<'
1600 || (alternate
&& in
->ptr
[idx
] == '\''))
1602 if (alternate
&& expand
)
1604 /* Keep the quotes */
1605 sb_add_char (out
, '\"');
1607 idx
= getstring (idx
, in
, out
);
1608 sb_add_char (out
, '\"');
1612 idx
= getstring (idx
, in
, out
);
1617 while (idx
< in
->len
1618 && (in
->ptr
[idx
] == '"'
1619 || in
->ptr
[idx
] == '\''
1621 || !ISSEP (in
->ptr
[idx
])))
1623 if (in
->ptr
[idx
] == '"'
1624 || in
->ptr
[idx
] == '\'')
1626 char tchar
= in
->ptr
[idx
];
1627 sb_add_char (out
, in
->ptr
[idx
++]);
1628 while (idx
< in
->len
1629 && in
->ptr
[idx
] != tchar
)
1630 sb_add_char (out
, in
->ptr
[idx
++]);
1634 sb_add_char (out
, in
->ptr
[idx
++]);
1643 /* skip along sb in starting at idx, suck off whitespace a ( and more
1644 whitespace. return the idx of the next char */
1647 skip_openp (idx
, in
)
1651 idx
= sb_skip_white (idx
, in
);
1652 if (in
->ptr
[idx
] != '(')
1653 ERROR ((stderr
, "misplaced ( .\n"));
1654 idx
= sb_skip_white (idx
+ 1, in
);
1658 /* skip along sb in starting at idx, suck off whitespace a ) and more
1659 whitespace. return the idx of the next char */
1662 skip_closep (idx
, in
)
1666 idx
= sb_skip_white (idx
, in
);
1667 if (in
->ptr
[idx
] != ')')
1668 ERROR ((stderr
, "misplaced ).\n"));
1669 idx
= sb_skip_white (idx
+ 1, in
);
1676 dolen (idx
, in
, out
)
1685 sb_new (&stringout
);
1686 idx
= skip_openp (idx
, in
);
1687 idx
= get_and_process (idx
, in
, &stringout
);
1688 idx
= skip_closep (idx
, in
);
1689 sprintf (buffer
, "%d", stringout
.len
);
1690 sb_add_string (out
, buffer
);
1692 sb_kill (&stringout
);
1701 doinstr (idx
, in
, out
)
1715 idx
= skip_openp (idx
, in
);
1716 idx
= get_and_process (idx
, in
, &string
);
1717 idx
= sb_skip_comma (idx
, in
);
1718 idx
= get_and_process (idx
, in
, &search
);
1719 idx
= sb_skip_comma (idx
, in
);
1720 if (isdigit (in
->ptr
[idx
]))
1722 idx
= exp_get_abs (".instr needs absolute expresson.\n", idx
, in
, &start
);
1728 idx
= skip_closep (idx
, in
);
1730 for (i
= start
; i
< string
.len
; i
++)
1732 if (strncmp (string
.ptr
+ i
, search
.ptr
, search
.len
) == 0)
1738 sprintf (buffer
, "%d", res
);
1739 sb_add_string (out
, buffer
);
1747 dosubstr (idx
, in
, out
)
1757 idx
= skip_openp (idx
, in
);
1758 idx
= get_and_process (idx
, in
, &string
);
1759 idx
= sb_skip_comma (idx
, in
);
1760 idx
= exp_get_abs ("need absolute position.\n", idx
, in
, &pos
);
1761 idx
= sb_skip_comma (idx
, in
);
1762 idx
= exp_get_abs ("need absolute length.\n", idx
, in
, &len
);
1763 idx
= skip_closep (idx
, in
);
1766 if (len
< 0 || pos
< 0 ||
1768 || pos
+ len
> string
.len
)
1770 sb_add_string (out
, " ");
1774 sb_add_char (out
, '"');
1777 sb_add_char (out
, string
.ptr
[pos
++]);
1780 sb_add_char (out
, '"');
1786 /* scan line, change tokens in the hash table to their replacements */
1788 process_assigns (idx
, in
, buf
)
1793 while (idx
< in
->len
)
1796 if (in
->ptr
[idx
] == '\\'
1797 && idx
+ 1 < in
->len
1798 && in
->ptr
[idx
+ 1] == '(')
1802 sb_add_char (buf
, in
->ptr
[idx
]);
1805 while (idx
< in
->len
&& in
->ptr
[idx
- 1] != ')');
1807 else if (in
->ptr
[idx
] == '\\'
1808 && idx
+ 1 < in
->len
1809 && in
->ptr
[idx
+ 1] == '&')
1811 idx
= condass_lookup_name (in
, idx
+ 2, buf
, 1);
1813 else if (in
->ptr
[idx
] == '\\'
1814 && idx
+ 1 < in
->len
1815 && in
->ptr
[idx
+ 1] == '$')
1817 idx
= condass_lookup_name (in
, idx
+ 2, buf
, 0);
1819 else if (idx
+ 3 < in
->len
1820 && in
->ptr
[idx
] == '.'
1821 && toupper ((unsigned char) in
->ptr
[idx
+ 1]) == 'L'
1822 && toupper ((unsigned char) in
->ptr
[idx
+ 2]) == 'E'
1823 && toupper ((unsigned char) in
->ptr
[idx
+ 3]) == 'N')
1824 idx
= dolen (idx
+ 4, in
, buf
);
1825 else if (idx
+ 6 < in
->len
1826 && in
->ptr
[idx
] == '.'
1827 && toupper ((unsigned char) in
->ptr
[idx
+ 1]) == 'I'
1828 && toupper ((unsigned char) in
->ptr
[idx
+ 2]) == 'N'
1829 && toupper ((unsigned char) in
->ptr
[idx
+ 3]) == 'S'
1830 && toupper ((unsigned char) in
->ptr
[idx
+ 4]) == 'T'
1831 && toupper ((unsigned char) in
->ptr
[idx
+ 5]) == 'R')
1832 idx
= doinstr (idx
+ 6, in
, buf
);
1833 else if (idx
+ 7 < in
->len
1834 && in
->ptr
[idx
] == '.'
1835 && toupper ((unsigned char) in
->ptr
[idx
+ 1]) == 'S'
1836 && toupper ((unsigned char) in
->ptr
[idx
+ 2]) == 'U'
1837 && toupper ((unsigned char) in
->ptr
[idx
+ 3]) == 'B'
1838 && toupper ((unsigned char) in
->ptr
[idx
+ 4]) == 'S'
1839 && toupper ((unsigned char) in
->ptr
[idx
+ 5]) == 'T'
1840 && toupper ((unsigned char) in
->ptr
[idx
+ 6]) == 'R')
1841 idx
= dosubstr (idx
+ 7, in
, buf
);
1842 else if (ISFIRSTCHAR (in
->ptr
[idx
]))
1844 /* may be a simple name subsitution, see if we have a word */
1847 while (cur
< in
->len
1848 && (ISNEXTCHAR (in
->ptr
[cur
])))
1852 sb_add_buffer (&acc
, in
->ptr
+ idx
, cur
- idx
);
1853 ptr
= hash_lookup (&assign_hash_table
, &acc
);
1856 /* Found a definition for it */
1857 sb_add_sb (buf
, &ptr
->value
.s
);
1861 /* No definition, just copy the word */
1862 sb_add_sb (buf
, &acc
);
1869 sb_add_char (buf
, in
->ptr
[idx
++]);
1875 get_and_process (idx
, in
, out
)
1882 idx
= get_any_string (idx
, in
, &t
, 1, 0);
1883 process_assigns (0, &t
, out
);
1904 more
= get_line (&line
);
1907 /* Find any label and pseudo op that we're intested in */
1912 fprintf (outfile
, "\n");
1915 && (line
.ptr
[0] == '*'
1916 || line
.ptr
[0] == '!'))
1918 /* MRI line comment. */
1919 fprintf (outfile
, sb_name (&line
));
1923 l
= grab_label (&line
, &label_in
);
1926 if (line
.ptr
[l
] == ':')
1928 while (ISWHITE (line
.ptr
[l
]) && l
< line
.len
)
1935 /* Munge the label, unless this is EQU or ASSIGN. */
1938 && (line
.ptr
[l
] == '.' || alternate
|| mri
))
1942 if (line
.ptr
[lx
] == '.')
1944 if (lx
+ 3 <= line
.len
1945 && strncasecmp ("EQU", line
.ptr
+ lx
, 3) == 0
1946 && (lx
+ 3 == line
.len
1947 || ! ISFIRSTCHAR (line
.ptr
[lx
+ 3])))
1949 else if (lx
+ 6 <= line
.len
1950 && strncasecmp ("ASSIGN", line
.ptr
+ lx
, 6) == 0
1951 && (lx
+ 6 == line
.len
1952 || ! ISFIRSTCHAR (line
.ptr
[lx
+ 6])))
1957 process_assigns (0, &label_in
, &label
);
1959 sb_add_sb (&label
, &label_in
);
1964 if (process_pseudo_op (l
, &line
, &acc
))
1970 else if (condass_on ())
1972 if (macro_op (l
, &line
))
1982 fprintf (outfile
, "%s:\t", sb_name (&label
));
1985 fprintf (outfile
, "\t");
1987 process_assigns (l
, &line
, &t1
);
1989 change_base (0, &t1
, &t2
);
1990 fprintf (outfile
, "%s\n", sb_name (&t2
));
1996 /* Only a label on this line */
1997 if (label
.len
&& condass_on())
1999 fprintf (outfile
, "%s:\n", sb_name (&label
));
2007 more
= get_line (&line
);
2010 if (!had_end
&& !mri
)
2011 WARNING ((stderr
, "END missing from end of file.\n"));
2019 free_old_entry (ptr
)
2024 if (ptr
->type
== hash_string
)
2025 sb_kill(&ptr
->value
.s
);
2029 /* name: .ASSIGNA <value> */
2032 do_assigna (idx
, in
)
2040 process_assigns (idx
, in
, &tmp
);
2041 idx
= exp_get_abs (".ASSIGNA needs constant expression argument.\n", 0, &tmp
, &val
);
2045 ERROR ((stderr
, ".ASSIGNA without label.\n"));
2049 hash_entry
*ptr
= hash_create (&vars
, &label
);
2050 free_old_entry (ptr
);
2051 ptr
->type
= hash_integer
;
2057 /* name: .ASSIGNC <string> */
2060 do_assignc (idx
, in
)
2066 idx
= getstring (idx
, in
, &acc
);
2070 ERROR ((stderr
, ".ASSIGNS without label.\n"));
2074 hash_entry
*ptr
= hash_create (&vars
, &label
);
2075 free_old_entry (ptr
);
2076 ptr
->type
= hash_string
;
2077 sb_new (&ptr
->value
.s
);
2078 sb_add_sb (&ptr
->value
.s
, &acc
);
2084 /* name: .REG (reg) */
2091 /* remove reg stuff from inside parens */
2094 idx
= skip_openp (idx
, in
);
2096 idx
= sb_skip_white (idx
, in
);
2098 while (idx
< in
->len
2101 : in
->ptr
[idx
] != ')'))
2103 sb_add_char (&what
, in
->ptr
[idx
]);
2106 hash_add_to_string_table (&assign_hash_table
, &label
, &what
, 1);
2112 condass_lookup_name (inbuf
, idx
, out
, warn
)
2120 sb_new (&condass_acc
);
2122 while (idx
< inbuf
->len
2123 && ISNEXTCHAR (inbuf
->ptr
[idx
]))
2125 sb_add_char (&condass_acc
, inbuf
->ptr
[idx
++]);
2128 if (inbuf
->ptr
[idx
] == '\'')
2130 ptr
= hash_lookup (&vars
, &condass_acc
);
2137 WARNING ((stderr
, "Can't find preprocessor variable %s.\n", sb_name (&condass_acc
)));
2141 sb_add_string (out
, "0");
2146 if (ptr
->type
== hash_integer
)
2149 sprintf (buffer
, "%d", ptr
->value
.i
);
2150 sb_add_string (out
, buffer
);
2154 sb_add_sb (out
, &ptr
->value
.s
);
2157 sb_kill (&condass_acc
);
2170 whatcond (idx
, in
, val
)
2177 idx
= sb_skip_white (idx
, in
);
2179 if (idx
+ 1 < in
->len
)
2185 a
= toupper ((unsigned char) p
[0]);
2186 b
= toupper ((unsigned char) p
[1]);
2187 if (a
== 'E' && b
== 'Q')
2189 else if (a
== 'N' && b
== 'E')
2191 else if (a
== 'L' && b
== 'T')
2193 else if (a
== 'L' && b
== 'E')
2195 else if (a
== 'G' && b
== 'T')
2197 else if (a
== 'G' && b
== 'E')
2202 ERROR ((stderr
, "Comparison operator must be one of EQ, NE, LT, LE, GT or GE.\n"));
2205 idx
= sb_skip_white (idx
+ 2, in
);
2222 idx
= sb_skip_white (idx
, in
);
2224 if (in
->ptr
[idx
] == '"')
2228 /* This is a string comparision */
2229 idx
= getstring (idx
, in
, &acc_a
);
2230 idx
= whatcond (idx
, in
, &cond
);
2231 idx
= getstring (idx
, in
, &acc_b
);
2232 same
= acc_a
.len
== acc_b
.len
&& (strncmp (acc_a
.ptr
, acc_b
.ptr
, acc_a
.len
) == 0);
2234 if (cond
!= EQ
&& cond
!= NE
)
2236 ERROR ((stderr
, "Comparison operator for strings must be EQ or NE\n"));
2240 res
= (cond
!= EQ
) ^ same
;
2243 /* This is a numeric expression */
2248 idx
= exp_get_abs ("Conditional operator must have absolute operands.\n", idx
, in
, &vala
);
2249 idx
= whatcond (idx
, in
, &cond
);
2250 idx
= sb_skip_white (idx
, in
);
2251 if (in
->ptr
[idx
] == '"')
2253 WARNING ((stderr
, "String compared against expression.\n"));
2258 idx
= exp_get_abs ("Conditional operator must have absolute operands.\n", idx
, in
, &valb
);
2301 if (ifi
>= IFNESTING
)
2303 FATAL ((stderr
, "AIF nesting unreasonable.\n"));
2306 ifstack
[ifi
].on
= ifstack
[ifi
-1].on
? istrue (idx
, in
) : 0;
2307 ifstack
[ifi
].hadelse
= 0;
2315 ifstack
[ifi
].on
= ifstack
[ifi
-1].on
? !ifstack
[ifi
].on
: 0;
2316 if (ifstack
[ifi
].hadelse
)
2318 ERROR ((stderr
, "Multiple AELSEs in AIF.\n"));
2320 ifstack
[ifi
].hadelse
= 1;
2334 ERROR ((stderr
, "AENDI without AIF.\n"));
2341 return ifstack
[ifi
].on
;
2344 /* MRI IFEQ, IFNE, IFLT, IFLE, IFGE, IFGT. */
2347 do_if (idx
, in
, cond
)
2355 if (ifi
>= IFNESTING
)
2357 FATAL ((stderr
, "IF nesting unreasonable.\n"));
2360 idx
= exp_get_abs ("Conditional operator must have absolute operands.\n",
2365 case EQ
: res
= val
== 0; break;
2366 case NE
: res
= val
!= 0; break;
2367 case LT
: res
= val
< 0; break;
2368 case LE
: res
= val
<= 0; break;
2369 case GE
: res
= val
>= 0; break;
2370 case GT
: res
= val
> 0; break;
2374 ifstack
[ifi
].on
= ifstack
[ifi
-1].on
? res
: 0;
2375 ifstack
[ifi
].hadelse
= 0;
2378 /* Get a string for the MRI IFC or IFNC pseudo-ops. */
2381 get_mri_string (idx
, in
, val
, terminator
)
2387 idx
= sb_skip_white (idx
, in
);
2390 && in
->ptr
[idx
] == '\'')
2392 sb_add_char (val
, '\'');
2393 for (++idx
; idx
< in
->len
; ++idx
)
2395 sb_add_char (val
, in
->ptr
[idx
]);
2396 if (in
->ptr
[idx
] == '\'')
2400 || in
->ptr
[idx
] != '\'')
2404 idx
= sb_skip_white (idx
, in
);
2410 while (idx
< in
->len
2411 && in
->ptr
[idx
] != terminator
)
2413 sb_add_char (val
, in
->ptr
[idx
]);
2417 while (i
>= 0 && ISWHITE (val
->ptr
[i
]))
2425 /* MRI IFC, IFNC. */
2428 do_ifc (idx
, in
, ifnc
)
2437 if (ifi
>= IFNESTING
)
2439 FATAL ((stderr
, "IF nesting unreasonable.\n"));
2445 idx
= get_mri_string (idx
, in
, &first
, ',');
2447 if (idx
>= in
->len
|| in
->ptr
[idx
] != ',')
2449 ERROR ((stderr
, "Bad format for IF or IFNC.\n"));
2453 idx
= get_mri_string (idx
+ 1, in
, &second
, ';');
2455 res
= (first
.len
== second
.len
2456 && strncmp (first
.ptr
, second
.ptr
, first
.len
) == 0);
2460 ifstack
[ifi
].on
= ifstack
[ifi
-1].on
? res
: 0;
2461 ifstack
[ifi
].hadelse
= 0;
2469 ERROR ((stderr
, "AENDR without a AREPEAT.\n"));
2471 ERROR ((stderr
, "ENDR without a REPT.\n"));
2482 int line
= linecount ();
2490 process_assigns (idx
, in
, &exp
);
2491 doit
= istrue (0, &exp
);
2493 if (! buffer_and_nest ("AWHILE", "AENDW", &sub
, get_line
))
2494 FATAL ((stderr
, "AWHILE without a AENDW at %d.\n", line
- 1));
2509 int index
= include_next_index ();
2513 sb_add_sb (©
, &sub
);
2514 sb_add_sb (©
, in
);
2515 sb_add_string (©
, "\n");
2516 sb_add_sb (©
, &sub
);
2517 sb_add_string (©
, "\t.AENDW\n");
2518 /* Push another WHILE */
2519 include_buf (&exp
, ©
, include_while
, index
);
2532 ERROR ((stderr
, "AENDW without a AENDW.\n"));
2538 Pop things off the include stack until the type and index changes */
2543 include_type type
= sp
->type
;
2544 if (type
== include_repeat
2545 || type
== include_while
2546 || type
== include_macro
)
2548 int index
= sp
->index
;
2550 while (sp
->index
== index
2551 && sp
->type
== type
)
2561 do_arepeat (idx
, in
)
2565 int line
= linecount ();
2566 sb exp
; /* buffer with expression in it */
2567 sb copy
; /* expanded repeat block */
2568 sb sub
; /* contents of AREPEAT */
2576 process_assigns (idx
, in
, &exp
);
2577 idx
= exp_get_abs ("AREPEAT must have absolute operand.\n", 0, &exp
, &rc
);
2579 ret
= buffer_and_nest ("AREPEAT", "AENDR", &sub
, get_line
);
2581 ret
= buffer_and_nest ("REPT", "ENDR", &sub
, get_line
);
2583 FATAL ((stderr
, "AREPEAT without a AENDR at %d.\n", line
- 1));
2586 /* Push back the text following the repeat, and another repeat block
2597 int index
= include_next_index ();
2598 sb_add_sb (©
, &sub
);
2602 sprintf (buffer
, "\t.AREPEAT %d\n", rc
- 1);
2604 sprintf (buffer
, "\tREPT %d\n", rc
- 1);
2605 sb_add_string (©
, buffer
);
2606 sb_add_sb (©
, &sub
);
2608 sb_add_string (©
, " .AENDR\n");
2610 sb_add_string (©
, " ENDR\n");
2613 include_buf (&exp
, ©
, include_repeat
, index
);
2625 ERROR ((stderr
, ".ENDM without a matching .MACRO.\n"));
2628 /* MRI IRP pseudo-op. */
2631 do_irp (idx
, in
, irpc
)
2641 err
= expand_irp (irpc
, idx
, in
, &out
, get_line
, comment_char
);
2643 ERROR ((stderr
, "%s\n", err
));
2645 fprintf (outfile
, "%s", sb_terminate (&out
));
2650 /* MACRO PROCESSING */
2652 /* Parse off LOCAL n1, n2,... Invent a label name for it */
2655 do_local (idx
, line
)
2659 ERROR ((stderr
, "LOCAL outside of MACRO"));
2668 int line
= linecount ();
2670 err
= define_macro (idx
, in
, &label
, get_line
, (const char **) NULL
);
2672 ERROR ((stderr
, "macro at line %d: %s\n", line
- 1, err
));
2684 if (! macro_defined
)
2688 if (! check_macro (in
->ptr
+ idx
, &out
, comment_char
, &err
))
2692 ERROR ((stderr
, "%s\n", err
));
2695 sb_add_string (&name
, "macro expansion");
2697 include_buf (&name
, &out
, include_macro
, include_next_index ());
2705 /* STRING HANDLING */
2708 getstring (idx
, in
, acc
)
2713 idx
= sb_skip_white (idx
, in
);
2715 while (idx
< in
->len
2716 && (in
->ptr
[idx
] == '"'
2717 || in
->ptr
[idx
] == '<'
2718 || (in
->ptr
[idx
] == '\'' && alternate
)))
2720 if (in
->ptr
[idx
] == '<')
2722 if (alternate
|| mri
)
2726 while ((in
->ptr
[idx
] != '>' || nest
)
2729 if (in
->ptr
[idx
] == '!')
2732 sb_add_char (acc
, in
->ptr
[idx
++]);
2735 if (in
->ptr
[idx
] == '>')
2737 if (in
->ptr
[idx
] == '<')
2739 sb_add_char (acc
, in
->ptr
[idx
++]);
2747 idx
= exp_get_abs ("Character code in string must be absolute expression.\n",
2749 sb_add_char (acc
, code
);
2751 if (in
->ptr
[idx
] != '>')
2752 ERROR ((stderr
, "Missing > for character code.\n"));
2756 else if (in
->ptr
[idx
] == '"' || in
->ptr
[idx
] == '\'')
2758 char tchar
= in
->ptr
[idx
];
2760 while (idx
< in
->len
)
2762 if (alternate
&& in
->ptr
[idx
] == '!')
2765 sb_add_char (acc
, in
->ptr
[idx
++]);
2768 if (in
->ptr
[idx
] == tchar
)
2771 if (idx
>= in
->len
|| in
->ptr
[idx
] != tchar
)
2774 sb_add_char (acc
, in
->ptr
[idx
]);
2784 /* .SDATA[C|Z] <string> */
2788 do_sdata (idx
, in
, type
)
2797 fprintf (outfile
, ".byte\t");
2799 while (!eol (idx
, in
))
2803 idx
= sb_skip_white (idx
, in
);
2804 while (!eol (idx
, in
))
2806 pidx
= idx
= get_any_string (idx
, in
, &acc
, 0, 1);
2811 ERROR ((stderr
, "string for SDATAC longer than 255 characters (%d).\n", acc
.len
));
2813 fprintf (outfile
, "%d", acc
.len
);
2817 for (i
= 0; i
< acc
.len
; i
++)
2821 fprintf (outfile
, ",");
2823 fprintf (outfile
, "%d", acc
.ptr
[i
]);
2830 fprintf (outfile
, ",");
2831 fprintf (outfile
, "0");
2833 idx
= sb_skip_comma (idx
, in
);
2834 if (idx
== pidx
) break;
2836 if (!alternate
&& in
->ptr
[idx
] != ',' && idx
!= in
->len
)
2838 fprintf (outfile
, "\n");
2839 ERROR ((stderr
, "illegal character in SDATA line (0x%x).\n", in
->ptr
[idx
]));
2845 fprintf (outfile
, "\n");
2848 /* .SDATAB <count> <string> */
2860 idx
= exp_get_abs ("Must have absolute SDATAB repeat count.\n", idx
, in
, &repeat
);
2863 ERROR ((stderr
, "Must have positive SDATAB repeat count (%d).\n", repeat
));
2867 idx
= sb_skip_comma (idx
, in
);
2868 idx
= getstring (idx
, in
, &acc
);
2870 for (i
= 0; i
< repeat
; i
++)
2873 fprintf (outfile
, "\t");
2874 fprintf (outfile
, ".byte\t");
2875 sb_print (outfile
, &acc
);
2876 fprintf (outfile
, "\n");
2886 FILE *newone
= fopen (name
, "r");
2890 if (isp
== MAX_INCLUDES
)
2891 FATAL ((stderr
, "Unreasonable include depth (%ld).\n", (long) isp
));
2894 sp
->handle
= newone
;
2897 sb_add_string (&sp
->name
, name
);
2900 sp
->pushback_index
= 0;
2901 sp
->type
= include_file
;
2903 sb_new (&sp
->pushback
);
2908 do_include (idx
, in
)
2914 include_path
*includes
;
2920 idx
= getstring (idx
, in
, &t
);
2923 idx
= sb_skip_white (idx
, in
);
2924 while (idx
< in
->len
&& ! ISWHITE (in
->ptr
[idx
]))
2926 sb_add_char (&t
, in
->ptr
[idx
]);
2931 for (includes
= paths_head
; includes
; includes
= includes
->next
)
2934 sb_add_sb (&cat
, &includes
->path
);
2935 sb_add_char (&cat
, '/');
2936 sb_add_sb (&cat
, &t
);
2937 if (new_file (sb_name (&cat
)))
2944 if (! new_file (sb_name (&t
)))
2945 FATAL ((stderr
, "Can't open include file `%s'.\n", sb_name (&t
)));
2954 if (sp
!= include_stack
)
2957 fclose (sp
->handle
);
2962 /* Get the next character from the include stack. If there's anything
2963 in the pushback buffer, take that first. If we're at eof, pop from
2964 the stack and try again. Keep the linecount up to date. */
2971 if (sp
->pushback
.len
!= sp
->pushback_index
)
2973 r
= (char) (sp
->pushback
.ptr
[sp
->pushback_index
++]);
2974 /* When they've all gone, reset the pointer */
2975 if (sp
->pushback_index
== sp
->pushback
.len
)
2977 sp
->pushback
.len
= 0;
2978 sp
->pushback_index
= 0;
2981 else if (sp
->handle
)
2983 r
= getc (sp
->handle
);
2988 if (r
== EOF
&& isp
)
2992 while (r
== EOF
&& isp
)
3010 return sp
->linecount
;
3014 include_next_index ()
3018 && index
> MAX_REASONABLE
)
3019 FATAL ((stderr
, "Unreasonable expansion (-u turns off check).\n"));
3024 /* Initialize the chartype vector. */
3030 for (x
= 0; x
< 256; x
++)
3032 if (isalpha (x
) || x
== '_' || x
== '$')
3033 chartype
[x
] |= FIRSTBIT
;
3035 if (mri
&& x
== '.')
3036 chartype
[x
] |= FIRSTBIT
;
3038 if (isdigit (x
) || isalpha (x
) || x
== '_' || x
== '$')
3039 chartype
[x
] |= NEXTBIT
;
3041 if (x
== ' ' || x
== '\t' || x
== ',' || x
== '"' || x
== ';'
3042 || x
== '"' || x
== '<' || x
== '>' || x
== ')' || x
== '(')
3043 chartype
[x
] |= SEPBIT
;
3045 if (x
== 'b' || x
== 'B'
3046 || x
== 'q' || x
== 'Q'
3047 || x
== 'h' || x
== 'H'
3048 || x
== 'd' || x
== 'D')
3049 chartype
[x
] |= BASEBIT
;
3051 if (x
== ' ' || x
== '\t')
3052 chartype
[x
] |= WHITEBIT
;
3054 if (x
== comment_char
)
3055 chartype
[x
] |= COMMENTBIT
;
3061 /* What to do with all the keywords */
3062 #define PROCESS 0x1000 /* Run substitution over the line */
3063 #define LAB 0x2000 /* Spit out the label */
3065 #define K_EQU (PROCESS|1)
3066 #define K_ASSIGN (PROCESS|2)
3067 #define K_REG (PROCESS|3)
3068 #define K_ORG (PROCESS|4)
3069 #define K_RADIX (PROCESS|5)
3070 #define K_DATA (LAB|PROCESS|6)
3071 #define K_DATAB (LAB|PROCESS|7)
3072 #define K_SDATA (LAB|PROCESS|8)
3073 #define K_SDATAB (LAB|PROCESS|9)
3074 #define K_SDATAC (LAB|PROCESS|10)
3075 #define K_SDATAZ (LAB|PROCESS|11)
3076 #define K_RES (LAB|PROCESS|12)
3077 #define K_SRES (LAB|PROCESS|13)
3078 #define K_SRESC (LAB|PROCESS|14)
3079 #define K_SRESZ (LAB|PROCESS|15)
3080 #define K_EXPORT (LAB|PROCESS|16)
3081 #define K_GLOBAL (LAB|PROCESS|17)
3082 #define K_PRINT (LAB|PROCESS|19)
3083 #define K_FORM (LAB|PROCESS|20)
3084 #define K_HEADING (LAB|PROCESS|21)
3085 #define K_PAGE (LAB|PROCESS|22)
3086 #define K_IMPORT (LAB|PROCESS|23)
3087 #define K_PROGRAM (LAB|PROCESS|24)
3088 #define K_END (PROCESS|25)
3089 #define K_INCLUDE (PROCESS|26)
3090 #define K_IGNORED (PROCESS|27)
3091 #define K_ASSIGNA (PROCESS|28)
3092 #define K_ASSIGNC (29)
3093 #define K_AIF (PROCESS|30)
3094 #define K_AELSE (PROCESS|31)
3095 #define K_AENDI (PROCESS|32)
3096 #define K_AREPEAT (PROCESS|33)
3097 #define K_AENDR (PROCESS|34)
3098 #define K_AWHILE (35)
3099 #define K_AENDW (PROCESS|36)
3100 #define K_EXITM (37)
3101 #define K_MACRO (PROCESS|38)
3103 #define K_ALIGN (PROCESS|LAB|40)
3104 #define K_ALTERNATE (41)
3105 #define K_DB (LAB|PROCESS|42)
3106 #define K_DW (LAB|PROCESS|43)
3107 #define K_DL (LAB|PROCESS|44)
3108 #define K_LOCAL (45)
3109 #define K_IFEQ (PROCESS|46)
3110 #define K_IFNE (PROCESS|47)
3111 #define K_IFLT (PROCESS|48)
3112 #define K_IFLE (PROCESS|49)
3113 #define K_IFGE (PROCESS|50)
3114 #define K_IFGT (PROCESS|51)
3115 #define K_IFC (PROCESS|52)
3116 #define K_IFNC (PROCESS|53)
3117 #define K_IRP (PROCESS|54)
3118 #define K_IRPC (PROCESS|55)
3128 static struct keyword kinfo
[] =
3130 { "EQU", K_EQU
, 0 },
3131 { "ALTERNATE", K_ALTERNATE
, 0 },
3132 { "ASSIGN", K_ASSIGN
, 0 },
3133 { "REG", K_REG
, 0 },
3134 { "ORG", K_ORG
, 0 },
3135 { "RADIX", K_RADIX
, 0 },
3136 { "DATA", K_DATA
, 0 },
3140 { "DATAB", K_DATAB
, 0 },
3141 { "SDATA", K_SDATA
, 0 },
3142 { "SDATAB", K_SDATAB
, 0 },
3143 { "SDATAZ", K_SDATAZ
, 0 },
3144 { "SDATAC", K_SDATAC
, 0 },
3145 { "RES", K_RES
, 0 },
3146 { "SRES", K_SRES
, 0 },
3147 { "SRESC", K_SRESC
, 0 },
3148 { "SRESZ", K_SRESZ
, 0 },
3149 { "EXPORT", K_EXPORT
, 0 },
3150 { "GLOBAL", K_GLOBAL
, 0 },
3151 { "PRINT", K_PRINT
, 0 },
3152 { "FORM", K_FORM
, 0 },
3153 { "HEADING", K_HEADING
, 0 },
3154 { "PAGE", K_PAGE
, 0 },
3155 { "PROGRAM", K_IGNORED
, 0 },
3156 { "END", K_END
, 0 },
3157 { "INCLUDE", K_INCLUDE
, 0 },
3158 { "ASSIGNA", K_ASSIGNA
, 0 },
3159 { "ASSIGNC", K_ASSIGNC
, 0 },
3160 { "AIF", K_AIF
, 0 },
3161 { "AELSE", K_AELSE
, 0 },
3162 { "AENDI", K_AENDI
, 0 },
3163 { "AREPEAT", K_AREPEAT
, 0 },
3164 { "AENDR", K_AENDR
, 0 },
3165 { "EXITM", K_EXITM
, 0 },
3166 { "MACRO", K_MACRO
, 0 },
3167 { "ENDM", K_ENDM
, 0 },
3168 { "AWHILE", K_AWHILE
, 0 },
3169 { "ALIGN", K_ALIGN
, 0 },
3170 { "AENDW", K_AENDW
, 0 },
3171 { "ALTERNATE", K_ALTERNATE
, 0 },
3172 { "LOCAL", K_LOCAL
, 0 },
3176 /* Although the conditional operators are handled by gas, we need to
3177 handle them here as well, in case they are used in a recursive
3178 macro to end the recursion. */
3180 static struct keyword mrikinfo
[] =
3182 { "IFEQ", K_IFEQ
, 0 },
3183 { "IFNE", K_IFNE
, 0 },
3184 { "IFLT", K_IFLT
, 0 },
3185 { "IFLE", K_IFLE
, 0 },
3186 { "IFGE", K_IFGE
, 0 },
3187 { "IFGT", K_IFGT
, 0 },
3188 { "IFC", K_IFC
, 0 },
3189 { "IFNC", K_IFNC
, 0 },
3190 { "ELSEC", K_AELSE
, 0 },
3191 { "ENDC", K_AENDI
, 0 },
3192 { "MEXIT", K_EXITM
, 0 },
3193 { "REPT", K_AREPEAT
, 0 },
3194 { "IRP", K_IRP
, 0 },
3195 { "IRPC", K_IRPC
, 0 },
3196 { "ENDR", K_AENDR
, 0 },
3200 /* Look for a pseudo op on the line. If one's there then call
3204 process_pseudo_op (idx
, line
, acc
)
3211 if (line
->ptr
[idx
] == '.' || alternate
|| mri
)
3213 /* Scan forward and find pseudo name */
3219 if (line
->ptr
[idx
] == '.')
3221 in
= line
->ptr
+ idx
;
3226 while (idx
< line
->len
&& *e
&& ISFIRSTCHAR (*e
))
3228 sb_add_char (acc
, *e
);
3233 ptr
= hash_lookup (&keyword_hash_table
, acc
);
3238 /* This one causes lots of pain when trying to preprocess
3240 WARNING ((stderr
, "Unrecognised pseudo op `%s'.\n", sb_name (acc
)));
3244 if (ptr
->value
.i
& LAB
)
3245 { /* output the label */
3248 fprintf (outfile
, "%s:\t", sb_name (&label
));
3251 fprintf (outfile
, "\t");
3254 if (mri
&& ptr
->value
.i
== K_END
)
3259 sb_add_buffer (&t
, line
->ptr
+ oidx
, idx
- oidx
);
3260 fprintf (outfile
, "\t%s", sb_name (&t
));
3264 if (ptr
->value
.i
& PROCESS
)
3266 /* Polish the rest of the line before handling the pseudo op */
3268 strip_comments(line
);
3271 process_assigns (idx
, line
, acc
);
3273 change_base (0, acc
, line
);
3278 switch (ptr
->value
.i
)
3294 switch (ptr
->value
.i
)
3298 macro_init (1, mri
, 0, exp_get_abs
);
3307 ERROR ((stderr
, "ORG command not allowed.\n"));
3313 do_data (idx
, line
, 1);
3316 do_data (idx
, line
, 2);
3319 do_data (idx
, line
, 4);
3322 do_data (idx
, line
, 0);
3325 do_datab (idx
, line
);
3328 do_sdata (idx
, line
, 0);
3331 do_sdatab (idx
, line
);
3334 do_sdata (idx
, line
, 'c');
3337 do_sdata (idx
, line
, 'z');
3340 do_assign (0, 0, line
);
3346 do_arepeat (idx
, line
);
3352 do_awhile (idx
, line
);
3358 do_assign (1, idx
, line
);
3361 do_align (idx
, line
);
3364 do_res (idx
, line
, 0);
3367 do_res (idx
, line
, 's');
3370 do_include (idx
, line
);
3373 do_local (idx
, line
);
3376 do_macro (idx
, line
);
3382 do_res (idx
, line
, 'c');
3385 do_print (idx
, line
);
3388 do_form (idx
, line
);
3391 do_heading (idx
, line
);
3403 do_res (idx
, line
, 'z');
3411 do_assigna (idx
, line
);
3414 do_assignc (idx
, line
);
3423 do_if (idx
, line
, EQ
);
3426 do_if (idx
, line
, NE
);
3429 do_if (idx
, line
, LT
);
3432 do_if (idx
, line
, LE
);
3435 do_if (idx
, line
, GE
);
3438 do_if (idx
, line
, GT
);
3441 do_ifc (idx
, line
, 0);
3444 do_ifc (idx
, line
, 1);
3447 do_irp (idx
, line
, 0);
3450 do_irp (idx
, line
, 1);
3460 /* Add a keyword to the hash table. */
3463 add_keyword (name
, code
)
3471 sb_add_string (&label
, name
);
3473 hash_add_to_int_table (&keyword_hash_table
, &label
, code
);
3476 for (j
= 0; name
[j
]; j
++)
3477 sb_add_char (&label
, name
[j
] - 'A' + 'a');
3478 hash_add_to_int_table (&keyword_hash_table
, &label
, code
);
3483 /* Build the keyword hash table - put each keyword in the table twice,
3484 once upper and once lower case.*/
3491 for (i
= 0; kinfo
[i
].name
; i
++)
3492 add_keyword (kinfo
[i
].name
, kinfo
[i
].code
);
3496 for (i
= 0; mrikinfo
[i
].name
; i
++)
3497 add_keyword (mrikinfo
[i
].name
, mrikinfo
[i
].code
);
3521 sb_add_char (&value
, *string
);
3524 exp_get_abs ("Invalid expression on command line.\n", 0, &value
, &res
);
3528 sb_add_char (&label
, *string
);
3533 ptr
= hash_create (&vars
, &label
);
3534 free_old_entry (ptr
);
3535 ptr
->type
= hash_integer
;
3541 /* The list of long options. */
3542 static struct option long_options
[] =
3544 { "alternate", no_argument
, 0, 'a' },
3545 { "include", required_argument
, 0, 'I' },
3546 { "commentchar", required_argument
, 0, 'c' },
3547 { "copysource", no_argument
, 0, 's' },
3548 { "debug", no_argument
, 0, 'd' },
3549 { "help", no_argument
, 0, 'h' },
3550 { "mri", no_argument
, 0, 'M' },
3551 { "output", required_argument
, 0, 'o' },
3552 { "print", no_argument
, 0, 'p' },
3553 { "unreasonable", no_argument
, 0, 'u' },
3554 { "version", no_argument
, 0, 'v' },
3555 { "define", required_argument
, 0, 'd' },
3556 { NULL
, no_argument
, 0, 0 }
3559 /* Show a usage message and exit. */
3561 show_usage (file
, status
)
3567 [-a] [--alternate] enter alternate macro mode\n\
3568 [-c char] [--commentchar char] change the comment character from !\n\
3569 [-d] [--debug] print some debugging info\n\
3570 [-h] [--help] print this message\n\
3571 [-M] [--mri] enter MRI compatibility mode\n\
3572 [-o out] [--output out] set the output file\n\
3573 [-p] [--print] print line numbers\n", program_name
);
3575 [-s] [--copysource] copy source through as comments \n\
3576 [-u] [--unreasonable] allow unreasonable nesting\n\
3577 [-v] [--version] print the program version\n\
3578 [-Dname=value] create preprocessor variable called name, with value\n\
3579 [-Ipath] add to include path list\n\
3582 printf ("\nReport bugs to bug-gnu-utils@gnu.org\n");
3586 /* Display a help message and exit. */
3590 printf ("%s: Gnu Assembler Macro Preprocessor\n",
3592 show_usage (stdout
, 0);
3609 program_name
= argv
[0];
3610 xmalloc_set_program_name (program_name
);
3612 hash_new_table (101, &keyword_hash_table
);
3613 hash_new_table (101, &assign_hash_table
);
3614 hash_new_table (101, &vars
);
3618 while ((opt
= getopt_long (argc
, argv
, "I:sdhavc:upo:D:M", long_options
,
3632 include_path
*p
= (include_path
*) xmalloc (sizeof (include_path
));
3634 sb_add_string (&p
->path
, optarg
);
3636 paths_tail
->next
= p
;
3643 print_line_number
= 1;
3646 comment_char
= optarg
[0];
3668 /* This output is intended to follow the GNU standards document. */
3669 printf ("GNU assembler pre-processor %s\n", program_version
);
3670 printf ("Copyright 1996 Free Software Foundation, Inc.\n");
3672 This program is free software; you may redistribute it under the terms of\n\
3673 the GNU General Public License. This program has absolutely no warranty.\n");
3679 show_usage (stderr
, 1);
3686 macro_init (alternate
, mri
, 0, exp_get_abs
);
3689 outfile
= fopen (out_name
, "w");
3692 fprintf (stderr
, "%s: Can't open output file `%s'.\n",
3693 program_name
, out_name
);
3705 /* Process all the input files */
3707 while (optind
< argc
)
3709 if (new_file (argv
[optind
]))
3715 fprintf (stderr
, "%s: Can't open input file `%s'.\n",
3716 program_name
, argv
[optind
]);
3726 /* This function is used because an abort in some of the other files
3727 may be compiled into as_abort because they include as.h. */
3730 as_abort (file
, line
, fn
)
3731 const char *file
, *fn
;
3734 fprintf (stderr
, "Internal error, aborting at %s line %d", file
, line
);
3736 fprintf (stderr
, " in %s", fn
);
3737 fprintf (stderr
, "\nPlease report this bug.\n");