1 /* gasp.c - Gnu assembler preprocessor main program.
2 Copyright (C) 1994, 1995 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 #define MAX_INCLUDES 30 /* Maximum include depth */
74 #define MAX_REASONABLE 1000 /* Maximum number of expansions */
76 int unreasonable
; /* -u on command line */
77 int stats
; /* -d on command line */
78 int print_line_number
; /* -p flag on command line */
79 int copysource
; /* -c flag on command line */
80 int warnings
; /* Number of WARNINGs generated so far. */
81 int errors
; /* Number of ERRORs generated so far. */
82 int fatals
; /* Number of fatal ERRORs generated so far (either 0 or 1). */
83 int alternate
= 0; /* -a on command line */
84 int mri
= 0; /* -M on command line */
85 char comment_char
= '!';
86 int radix
= 10; /* Default radix */
88 int had_end
; /* Seen .END */
90 /* The output stream */
93 /* the attributes of each character are stored as a bit pattern
94 chartype, which gives us quick tests. */
101 #define COMMENTBIT 16
103 #define ISCOMMENTCHAR(x) (chartype[(unsigned)(x)] & COMMENTBIT)
104 #define ISFIRSTCHAR(x) (chartype[(unsigned)(x)] & FIRSTBIT)
105 #define ISNEXTCHAR(x) (chartype[(unsigned)(x)] & NEXTBIT)
106 #define ISSEP(x) (chartype[(unsigned)(x)] & SEPBIT)
107 #define ISWHITE(x) (chartype[(unsigned)(x)] & WHITEBIT)
108 #define ISBASE(x) (chartype[(unsigned)(x)] & BASEBIT)
109 static char chartype
[256];
112 /* Conditional assembly uses the `ifstack'. Each aif pushes another
113 entry onto the stack, and sets the on flag if it should. The aelse
114 sets hadelse, and toggles on. An aend pops a level. We limit to
115 100 levels of nesting, not because we're facists pigs with read
116 only minds, but because more than 100 levels of nesting is probably
117 a bug in the user's macro structure. */
119 #define IFNESTING 100
122 int on
; /* is the level being output */
123 int hadelse
; /* has an aelse been seen */
128 /* The final and intermediate results of expression evaluation are kept in
129 exp_t's. Note that a symbol is not an sb, but a pointer into the input
130 line. It must be coped somewhere safe before the next line is read in. */
141 int value
; /* constant part */
142 symbol add_symbol
; /* name part */
143 symbol sub_symbol
; /* name part */
148 /* Hashing is done in a pretty standard way. A hash_table has a
149 pointer to a vector of pointers to hash_entrys, and the size of the
150 vector. A hash_entry contains a union of all the info we like to
151 store in hash table. If there is a hash collision, hash_entries
152 with the same hash are kept in a chain. */
154 /* What the data in a hash_entry means */
157 hash_integer
, /* name->integer mapping */
158 hash_string
, /* name->string mapping */
159 hash_macro
, /* name is a macro */
160 hash_formal
/* name is a formal argument */
165 sb key
; /* symbol name */
166 hash_type type
; /* symbol meaning */
171 struct macro_struct
*m
;
172 struct formal_struct
*f
;
174 struct hs
*next
; /* next hash_entry with same hash key */
184 /* Structures used to store macros.
186 Each macro knows its name and included text. It gets built with a
187 list of formal arguments, and also keeps a hash table which points
188 into the list to speed up formal search. Each formal knows its
189 name and its default value. Each time the macro is expanded, the
190 formals get the actual values attatched to them. */
192 /* describe the formal arguments to a macro */
194 typedef struct formal_struct
196 struct formal_struct
*next
; /* next formal in list */
197 sb name
; /* name of the formal */
198 sb def
; /* the default value */
199 sb actual
; /* the actual argument (changed on each expansion) */
200 int index
; /* the index of the formal 0..formal_count-1 */
204 /* describe the macro. */
206 typedef struct macro_struct
208 sb sub
; /* substitution text. */
209 int formal_count
; /* number of formal args. */
210 formal_entry
*formals
; /* pointer to list of formal_structs */
211 hash_table formal_hash
; /* hash table of formals. */
215 /* how we nest files and expand macros etc.
217 we keep a stack of of include_stack structs. each include file
218 pushes a new level onto the stack. we keep an sb with a pushback
219 too. unget chars are pushed onto the pushback sb, getchars first
220 checks the pushback sb before reading from the input stream.
222 small things are expanded by adding the text of the item onto the
223 pushback sb. larger items are grown by pushing a new level and
224 allocating the entire pushback buf for the item. each time
225 something like a macro is expanded, the stack index is changed. we
226 can then perform an exitm by popping all entries off the stack with
227 the same stack index. if we're being reasonable, we can detect
228 recusive expansion by checking the index is reasonably small.
233 include_file
, include_repeat
, include_while
, include_macro
238 sb pushback
; /* current pushback stream */
239 int pushback_index
; /* next char to read from stream */
240 FILE *handle
; /* open file */
241 sb name
; /* name of file */
242 int linecount
; /* number of lines read so far */
244 int index
; /* index of this layer */
246 include_stack
[MAX_INCLUDES
];
248 struct include_stack
*sp
;
249 #define isp (sp - include_stack)
251 /* Include file list */
253 typedef struct include_path
255 struct include_path
*next
;
259 include_path
*paths_head
;
260 include_path
*paths_tail
;
263 static void quit
PARAMS ((void));
264 static void hash_new_table
PARAMS ((int, hash_table
*));
265 static int hash
PARAMS ((sb
*));
266 static hash_entry
*hash_create
PARAMS ((hash_table
*, sb
*));
267 static void hash_add_to_string_table
PARAMS ((hash_table
*, sb
*, sb
*, int));
268 static void hash_add_to_int_table
PARAMS ((hash_table
*, sb
*, int));
269 static hash_entry
*hash_lookup
PARAMS ((hash_table
*, sb
*));
270 static void checkconst
PARAMS ((int, exp_t
*));
271 static int sb_strtol
PARAMS ((int, sb
*, int, int *));
272 static int level_0
PARAMS ((int, sb
*, exp_t
*));
273 static int level_1
PARAMS ((int, sb
*, exp_t
*));
274 static int level_2
PARAMS ((int, sb
*, exp_t
*));
275 static int level_3
PARAMS ((int, sb
*, exp_t
*));
276 static int level_4
PARAMS ((int, sb
*, exp_t
*));
277 static int level_5
PARAMS ((int, sb
*, exp_t
*));
278 static int exp_parse
PARAMS ((int, sb
*, exp_t
*));
279 static void exp_string
PARAMS ((exp_t
*, sb
*));
280 static int exp_get_abs
PARAMS ((const char *, int, sb
*, int *));
282 static void strip_comments
PARAMS ((sb
*));
284 static void unget
PARAMS ((int));
285 static void include_buf
PARAMS ((sb
*, sb
*, include_type
, int));
286 static void include_print_where_line
PARAMS ((FILE *));
287 static void include_print_line
PARAMS ((FILE *));
288 static int get_line
PARAMS ((sb
*));
289 static int grab_label
PARAMS ((sb
*, sb
*));
290 static void change_base
PARAMS ((int, sb
*, sb
*));
291 static void do_end
PARAMS ((sb
*));
292 static void do_assign
PARAMS ((int, int, sb
*));
293 static void do_radix
PARAMS ((sb
*));
294 static int get_opsize
PARAMS ((int, sb
*, int *));
295 static int eol
PARAMS ((int, sb
*));
296 static void do_data
PARAMS ((int, sb
*, int));
297 static void do_datab
PARAMS ((int, sb
*));
298 static void do_align
PARAMS ((int, sb
*));
299 static void do_res
PARAMS ((int, sb
*, int));
300 static void do_export
PARAMS ((sb
*));
301 static void do_print
PARAMS ((int, sb
*));
302 static void do_heading
PARAMS ((int, sb
*));
303 static void do_page
PARAMS ((void));
304 static void do_form
PARAMS ((int, sb
*));
305 static int get_any_string
PARAMS ((int, sb
*, sb
*, int, int));
306 static int skip_openp
PARAMS ((int, sb
*));
307 static int skip_closep
PARAMS ((int, sb
*));
308 static int dolen
PARAMS ((int, sb
*, sb
*));
309 static int doinstr
PARAMS ((int, sb
*, sb
*));
310 static int dosubstr
PARAMS ((int, sb
*, sb
*));
311 static void process_assigns
PARAMS ((int, sb
*, sb
*));
312 static int get_and_process
PARAMS ((int, sb
*, sb
*));
313 static void process_file
PARAMS ((void));
314 static void free_old_entry
PARAMS ((hash_entry
*));
315 static void do_assigna
PARAMS ((int, sb
*));
316 static void do_assignc
PARAMS ((int, sb
*));
317 static void do_reg
PARAMS ((int, sb
*));
318 static int condass_lookup_name
PARAMS ((sb
*, int, sb
*, int));
319 static int whatcond
PARAMS ((int, sb
*, int *));
320 static int istrue
PARAMS ((int, sb
*));
321 static void do_aif
PARAMS ((int, sb
*));
322 static void do_aelse
PARAMS ((void));
323 static void do_aendi
PARAMS ((void));
324 static int condass_on
PARAMS ((void));
325 static void do_if
PARAMS ((int, sb
*, int));
326 static int get_mri_string
PARAMS ((int, sb
*, sb
*, int));
327 static void do_ifc
PARAMS ((int, sb
*, int));
328 static void do_aendr
PARAMS ((void));
329 static void do_awhile
PARAMS ((int, sb
*));
330 static void do_aendw
PARAMS ((void));
331 static void do_exitm
PARAMS ((void));
332 static void do_arepeat
PARAMS ((int, sb
*));
333 static void do_endm
PARAMS ((void));
334 static void do_irp
PARAMS ((int, sb
*, int));
335 static void do_local
PARAMS ((int, sb
*));
336 static void do_macro
PARAMS ((int, sb
*));
337 static int macro_op
PARAMS ((int, sb
*));
338 static int getstring
PARAMS ((int, sb
*, sb
*));
339 static void do_sdata
PARAMS ((int, sb
*, int));
340 static void do_sdatab
PARAMS ((int, sb
*));
341 static int new_file
PARAMS ((const char *));
342 static void do_include
PARAMS ((int, sb
*));
343 static void include_pop
PARAMS ((void));
344 static int get
PARAMS ((void));
345 static int linecount
PARAMS ((void));
346 static int include_next_index
PARAMS ((void));
347 static void chartype_init
PARAMS ((void));
348 static int process_pseudo_op
PARAMS ((int, sb
*, sb
*));
349 static void add_keyword
PARAMS ((const char *, int));
350 static void process_init
PARAMS ((void));
351 static void do_define
PARAMS ((const char *));
352 static void show_usage
PARAMS ((FILE *, int));
353 static void show_help
PARAMS ((void));
356 do { include_print_where_line (stderr); fprintf x ; fatals++; quit(); } while(0)
358 do { include_print_where_line (stderr); fprintf x; errors++; } while(0)
360 do { include_print_where_line (stderr); fprintf x; warnings++;} while(0)
364 /* exit the program and return the right ERROR code. */
377 for (i
= 0; i
< sb_max_power_two
; i
++)
379 fprintf (stderr
, "strings size %8d : %d\n", 1<<i
, string_count
[i
]);
385 /* hash table maintenance. */
387 /* build a new hash table with size buckets, and fill in the info at ptr. */
390 hash_new_table (size
, ptr
)
396 ptr
->table
= (hash_entry
**) xmalloc (size
* (sizeof (hash_entry
*)));
397 /* Fill with null-pointer, not zero-bit-pattern. */
398 for (i
= 0; i
< size
; i
++)
402 /* calculate and return the hash value of the sb at key. */
411 for (i
= 0; i
< key
->len
; i
++)
419 /* lookup key in hash_table tab, if present, then return it, otherwise
420 build a new one and fill it with hash_integer. */
424 hash_create (tab
, key
)
428 int k
= hash (key
) % tab
->size
;
430 hash_entry
**table
= tab
->table
;
438 hash_entry
*n
= (hash_entry
*) xmalloc (sizeof (hash_entry
));
441 sb_add_sb (&n
->key
, key
);
443 n
->type
= hash_integer
;
446 if (strncmp (table
[k
]->key
.ptr
, key
->ptr
, key
->len
) == 0)
454 /* add sb name with key into hash_table tab. if replacing old value
455 and again, then ERROR. */
459 hash_add_to_string_table (tab
, key
, name
, again
)
465 hash_entry
*ptr
= hash_create (tab
, key
);
466 if (ptr
->type
== hash_integer
)
468 sb_new (&ptr
->value
.s
);
470 if (ptr
->value
.s
.len
)
473 ERROR ((stderr
, "redefintion not allowed"));
476 ptr
->type
= hash_string
;
477 sb_reset (&ptr
->value
.s
);
479 sb_add_sb (&ptr
->value
.s
, name
);
482 /* add integer name to hash_table tab with sb key. */
486 hash_add_to_int_table (tab
, key
, name
)
491 hash_entry
*ptr
= hash_create (tab
, key
);
495 /* lookup sb key in hash_table tab. if found return hash_entry result,
500 hash_lookup (tab
, key
)
504 int k
= hash (key
) % tab
->size
;
505 hash_entry
**table
= tab
->table
;
506 hash_entry
*p
= table
[k
];
509 if (p
->key
.len
== key
->len
510 && strncmp (p
->key
.ptr
, key
->ptr
, key
->len
) == 0)
520 are handled in a really simple recursive decent way. each bit of
521 the machine takes an index into an sb and a pointer to an exp_t,
522 modifies the *exp_t and returns the index of the first character
523 past the part of the expression parsed.
525 expression precedence:
536 /* make sure that the exp_t at term is constant, if not the give the op ERROR. */
540 checkconst (op
, term
)
544 if (term
->add_symbol
.len
545 || term
->sub_symbol
.len
)
547 ERROR ((stderr
, "the %c operator cannot take non-absolute arguments.\n", op
));
551 /* turn the number in string at idx into a number of base,
552 fill in ptr and return the index of the first character not in the
557 sb_strtol (idx
, string
, base
, ptr
)
564 idx
= sb_skip_white (idx
, string
);
566 while (idx
< string
->len
)
568 int ch
= string
->ptr
[idx
];
572 else if (ch
>= 'a' && ch
<= 'f')
574 else if (ch
>= 'A' && ch
<= 'F')
582 value
= value
* base
+ dig
;
590 level_0 (idx
, string
, lhs
)
595 lhs
->add_symbol
.len
= 0;
596 lhs
->add_symbol
.name
= 0;
598 lhs
->sub_symbol
.len
= 0;
599 lhs
->sub_symbol
.name
= 0;
601 idx
= sb_skip_white (idx
, string
);
605 if (isdigit (string
->ptr
[idx
]))
607 idx
= sb_strtol (idx
, string
, 10, &lhs
->value
);
609 else if (ISFIRSTCHAR (string
->ptr
[idx
]))
612 lhs
->add_symbol
.name
= string
->ptr
+ idx
;
613 while (idx
< string
->len
&& ISNEXTCHAR (string
->ptr
[idx
]))
618 lhs
->add_symbol
.len
= len
;
620 else if (string
->ptr
[idx
] == '"')
624 ERROR ((stderr
, "string where expression expected.\n"));
625 idx
= getstring (idx
, string
, &acc
);
630 ERROR ((stderr
, "can't find primary in expression.\n"));
633 return sb_skip_white (idx
, string
);
639 level_1 (idx
, string
, lhs
)
644 idx
= sb_skip_white (idx
, string
);
646 switch (string
->ptr
[idx
])
649 idx
= level_1 (idx
+ 1, string
, lhs
);
652 idx
= level_1 (idx
+ 1, string
, lhs
);
653 checkconst ('~', lhs
);
654 lhs
->value
= ~lhs
->value
;
659 idx
= level_1 (idx
+ 1, string
, lhs
);
660 lhs
->value
= -lhs
->value
;
662 lhs
->add_symbol
= lhs
->sub_symbol
;
668 idx
= level_5 (sb_skip_white (idx
, string
), string
, lhs
);
669 if (string
->ptr
[idx
] != ')')
670 ERROR ((stderr
, "misplaced closing parens.\n"));
675 idx
= level_0 (idx
, string
, lhs
);
678 return sb_skip_white (idx
, string
);
682 level_2 (idx
, string
, lhs
)
689 idx
= level_1 (idx
, string
, lhs
);
691 while (idx
< string
->len
&& (string
->ptr
[idx
] == '*'
692 || string
->ptr
[idx
] == '/'))
694 char op
= string
->ptr
[idx
++];
695 idx
= level_1 (idx
, string
, &rhs
);
699 checkconst ('*', lhs
);
700 checkconst ('*', &rhs
);
701 lhs
->value
*= rhs
.value
;
704 checkconst ('/', lhs
);
705 checkconst ('/', &rhs
);
707 ERROR ((stderr
, "attempt to divide by zero.\n"));
709 lhs
->value
/= rhs
.value
;
713 return sb_skip_white (idx
, string
);
718 level_3 (idx
, string
, lhs
)
725 idx
= level_2 (idx
, string
, lhs
);
727 while (idx
< string
->len
728 && (string
->ptr
[idx
] == '+'
729 || string
->ptr
[idx
] == '-'))
731 char op
= string
->ptr
[idx
++];
732 idx
= level_2 (idx
, string
, &rhs
);
736 lhs
->value
+= rhs
.value
;
737 if (lhs
->add_symbol
.name
&& rhs
.add_symbol
.name
)
739 ERROR ((stderr
, "can't add two relocatable expressions\n"));
741 /* change nn+symbol to symbol + nn */
742 if (rhs
.add_symbol
.name
)
744 lhs
->add_symbol
= rhs
.add_symbol
;
748 lhs
->value
-= rhs
.value
;
749 lhs
->sub_symbol
= rhs
.add_symbol
;
753 return sb_skip_white (idx
, string
);
757 level_4 (idx
, string
, lhs
)
764 idx
= level_3 (idx
, string
, lhs
);
766 while (idx
< string
->len
&&
767 string
->ptr
[idx
] == '&')
769 char op
= string
->ptr
[idx
++];
770 idx
= level_3 (idx
, string
, &rhs
);
774 checkconst ('&', lhs
);
775 checkconst ('&', &rhs
);
776 lhs
->value
&= rhs
.value
;
780 return sb_skip_white (idx
, string
);
784 level_5 (idx
, string
, lhs
)
791 idx
= level_4 (idx
, string
, lhs
);
793 while (idx
< string
->len
794 && (string
->ptr
[idx
] == '|' || string
->ptr
[idx
] == '~'))
796 char op
= string
->ptr
[idx
++];
797 idx
= level_4 (idx
, string
, &rhs
);
801 checkconst ('|', lhs
);
802 checkconst ('|', &rhs
);
803 lhs
->value
|= rhs
.value
;
806 checkconst ('~', lhs
);
807 checkconst ('~', &rhs
);
808 lhs
->value
^= rhs
.value
;
812 return sb_skip_white (idx
, string
);
816 /* parse the expression at offset idx into string, fill up res with
817 the result. return the index of the first char past the expression.
821 exp_parse (idx
, string
, res
)
826 return level_5 (sb_skip_white (idx
, string
), string
, res
);
830 /* turn the expression at exp into text and glue it onto the end of
834 exp_string (exp
, string
)
842 if (exp
->add_symbol
.len
)
844 sb_add_buffer (string
, exp
->add_symbol
.name
, exp
->add_symbol
.len
);
852 sb_add_char (string
, '+');
853 sprintf (buf
, "%d", exp
->value
);
854 sb_add_string (string
, buf
);
858 if (exp
->sub_symbol
.len
)
860 sb_add_char (string
, '-');
861 sb_add_buffer (string
, exp
->add_symbol
.name
, exp
->add_symbol
.len
);
867 sb_add_char (string
, '0');
871 /* parse the expression at offset idx into sb in, return the value in val.
872 if the expression is not constant, give ERROR emsg. returns the index
873 of the first character past the end of the expression. */
876 exp_get_abs (emsg
, idx
, in
, val
)
883 idx
= exp_parse (idx
, in
, &res
);
884 if (res
.add_symbol
.len
|| res
.sub_symbol
.len
)
885 ERROR ((stderr
, emsg
));
891 sb label
; /* current label parsed from line */
892 hash_table assign_hash_table
; /* hash table for all assigned variables */
893 hash_table keyword_hash_table
; /* hash table for keyword */
894 hash_table vars
; /* hash table for eq variables */
896 #define in_comment ';'
905 for (i
= 0; i
< out
->len
; i
++)
907 if (ISCOMMENTCHAR(s
[i
]))
916 /* push back character ch so that it can be read again. */
926 if (sp
->pushback_index
)
927 sp
->pushback_index
--;
929 sb_add_char (&sp
->pushback
, ch
);
932 /* push the sb ptr onto the include stack, with the given name, type and index. */
936 include_buf (name
, ptr
, type
, index
)
943 if (sp
- include_stack
>= MAX_INCLUDES
)
944 FATAL ((stderr
, "unreasonable nesting.\n"));
946 sb_add_sb (&sp
->name
, name
);
949 sp
->pushback_index
= 0;
952 sb_new (&sp
->pushback
);
953 sb_add_sb (&sp
->pushback
, ptr
);
957 /* used in ERROR messages, print info on where the include stack is onto file. */
960 include_print_where_line (file
)
963 struct include_stack
*p
= include_stack
+ 1;
967 fprintf (file
, "%s:%d ", sb_name (&p
->name
), p
->linecount
- 1);
972 /* used in listings, print the line number onto file. */
974 include_print_line (file
)
978 struct include_stack
*p
= include_stack
+ 1;
980 n
= fprintf (file
, "%4d", p
->linecount
);
984 n
+= fprintf (file
, ".%d", p
->linecount
);
995 /* read a line from the top of the include stack into sb in. */
1006 putc (comment_char
, outfile
);
1007 if (print_line_number
)
1008 include_print_line (outfile
);
1022 WARNING ((stderr
, "End of file not at start of line.\n"));
1024 putc ('\n', outfile
);
1043 /* continued line */
1046 putc (comment_char
, outfile
);
1047 putc ('+', outfile
);
1060 sb_add_char (in
, ch
);
1068 /* find a label from sb in and put it in out. */
1071 grab_label (in
, out
)
1077 if (ISFIRSTCHAR (in
->ptr
[i
]))
1079 sb_add_char (out
, in
->ptr
[i
]);
1081 while ((ISNEXTCHAR (in
->ptr
[i
])
1082 || in
->ptr
[i
] == '\\'
1083 || in
->ptr
[i
] == '&')
1086 sb_add_char (out
, in
->ptr
[i
]);
1093 /* find all strange base stuff and turn into decimal. also
1094 find all the other numbers and convert them from the default radix */
1097 change_base (idx
, in
, out
)
1104 while (idx
< in
->len
)
1106 if (idx
< in
->len
- 1 && in
->ptr
[idx
+ 1] == '\'' && ! mri
)
1110 switch (in
->ptr
[idx
])
1129 ERROR ((stderr
, "Illegal base character %c.\n", in
->ptr
[idx
]));
1134 idx
= sb_strtol (idx
+ 2, in
, base
, &value
);
1135 sprintf (buffer
, "%d", value
);
1136 sb_add_string (out
, buffer
);
1138 else if (ISFIRSTCHAR (in
->ptr
[idx
]))
1140 /* copy entire names through quickly */
1141 sb_add_char (out
, in
->ptr
[idx
]);
1143 while (idx
< in
->len
&& ISNEXTCHAR (in
->ptr
[idx
]))
1145 sb_add_char (out
, in
->ptr
[idx
]);
1149 else if (isdigit (in
->ptr
[idx
]))
1152 /* all numbers must start with a digit, let's chew it and
1154 idx
= sb_strtol (idx
, in
, radix
, &value
);
1155 sprintf (buffer
, "%d", value
);
1156 sb_add_string (out
, buffer
);
1158 /* skip all undigsested letters */
1159 while (idx
< in
->len
&& ISNEXTCHAR (in
->ptr
[idx
]))
1161 sb_add_char (out
, in
->ptr
[idx
]);
1165 else if (in
->ptr
[idx
] == '"' || in
->ptr
[idx
] == '\'')
1167 char tchar
= in
->ptr
[idx
];
1168 /* copy entire names through quickly */
1169 sb_add_char (out
, in
->ptr
[idx
]);
1171 while (idx
< in
->len
&& in
->ptr
[idx
] != tchar
)
1173 sb_add_char (out
, in
->ptr
[idx
]);
1179 /* nothing special, just pass it through */
1180 sb_add_char (out
, in
->ptr
[idx
]);
1194 fprintf (outfile
, "%s\n", sb_name (in
));
1200 do_assign (again
, idx
, in
)
1205 /* stick label in symbol table with following value */
1210 idx
= exp_parse (idx
, in
, &e
);
1211 exp_string (&e
, &acc
);
1212 hash_add_to_string_table (&assign_hash_table
, &label
, &acc
, again
);
1217 /* .radix [b|q|d|h] */
1224 int idx
= sb_skip_white (0, ptr
);
1225 switch (ptr
->ptr
[idx
])
1244 ERROR ((stderr
, "radix is %c must be one of b, q, d or h", radix
));
1249 /* Parse off a .b, .w or .l */
1252 get_opsize (idx
, in
, size
)
1258 if (in
->ptr
[idx
] == '.')
1262 switch (in
->ptr
[idx
])
1280 ERROR ((stderr
, "size must be one of b, w or l, is %c.\n", in
->ptr
[idx
]));
1293 idx
= sb_skip_white (idx
, line
);
1295 && ISCOMMENTCHAR(line
->ptr
[idx
]))
1297 if (idx
>= line
->len
)
1302 /* .data [.b|.w|.l] <data>*
1303 or d[bwl] <data>* */
1306 do_data (idx
, in
, size
)
1312 char *opname
= ".yikes!";
1318 idx
= get_opsize (idx
, in
, &opsize
);
1337 fprintf (outfile
, "%s\t", opname
);
1339 idx
= sb_skip_white (idx
, in
);
1343 && in
->ptr
[idx
] == '"')
1346 idx
= getstring (idx
, in
, &acc
);
1347 for (i
= 0; i
< acc
.len
; i
++)
1350 fprintf(outfile
,",");
1351 fprintf (outfile
, "%d", acc
.ptr
[i
]);
1356 while (!eol (idx
, in
))
1359 idx
= exp_parse (idx
, in
, &e
);
1360 exp_string (&e
, &acc
);
1361 sb_add_char (&acc
, 0);
1362 fprintf (outfile
, acc
.ptr
);
1363 if (idx
< in
->len
&& in
->ptr
[idx
] == ',')
1365 fprintf (outfile
, ",");
1371 sb_print_at (outfile
, idx
, in
);
1372 fprintf (outfile
, "\n");
1375 /* .datab [.b|.w|.l] <repeat>,<fill> */
1386 idx
= get_opsize (idx
, in
, &opsize
);
1388 idx
= exp_get_abs ("datab repeat must be constant.\n", idx
, in
, &repeat
);
1389 idx
= sb_skip_comma (idx
, in
);
1390 idx
= exp_get_abs ("datab data must be absolute.\n", idx
, in
, &fill
);
1392 fprintf (outfile
, ".fill\t%d,%d,%d\n", repeat
, opsize
, fill
);
1403 idx
= exp_get_abs ("align needs absolute expression.\n", idx
, in
, &al
);
1408 WARNING ((stderr
, "alignment must be one of 1, 2 or 4.\n"));
1410 fprintf (outfile
, ".align %d\n", al
);
1413 /* .res[.b|.w|.l] <size> */
1416 do_res (idx
, in
, type
)
1424 idx
= get_opsize (idx
, in
, &size
);
1425 while (!eol(idx
, in
))
1427 idx
= sb_skip_white (idx
, in
);
1428 if (in
->ptr
[idx
] == ',')
1430 idx
= exp_get_abs ("res needs absolute expression for fill count.\n", idx
, in
, &count
);
1432 if (type
== 'c' || type
== 'z')
1435 fprintf (outfile
, ".space %d\n", count
* size
);
1446 fprintf (outfile
, ".global %s\n", sb_name (in
));
1449 /* .print [list] [nolist] */
1456 idx
= sb_skip_white (idx
, in
);
1457 while (idx
< in
->len
)
1459 if (strncasecmp (in
->ptr
+ idx
, "LIST", 4) == 0)
1461 fprintf (outfile
, ".list\n");
1464 else if (strncasecmp (in
->ptr
+ idx
, "NOLIST", 6) == 0)
1466 fprintf (outfile
, ".nolist\n");
1475 do_heading (idx
, in
)
1481 idx
= getstring (idx
, in
, &head
);
1482 fprintf (outfile
, ".title \"%s\"\n", sb_name (&head
));
1491 fprintf (outfile
, ".eject\n");
1494 /* .form [lin=<value>] [col=<value>] */
1502 idx
= sb_skip_white (idx
, in
);
1504 while (idx
< in
->len
)
1507 if (strncasecmp (in
->ptr
+ idx
, "LIN=", 4) == 0)
1510 idx
= exp_get_abs ("form LIN= needs absolute expresssion.\n", idx
, in
, &lines
);
1513 if (strncasecmp (in
->ptr
+ idx
, "COL=", 4) == 0)
1516 idx
= exp_get_abs ("form COL= needs absolute expresssion.\n", idx
, in
, &columns
);
1521 fprintf (outfile
, ".psize %d,%d\n", lines
, columns
);
1526 /* Fetch string from the input stream,
1528 'Bxyx<whitespace> -> return 'Bxyza
1529 %<char> -> return string of decimal value of x
1530 "<string>" -> return string
1531 xyx<whitespace> -> return xyz
1534 get_any_string (idx
, in
, out
, expand
, pretend_quoted
)
1542 idx
= sb_skip_white (idx
, in
);
1546 if (in
->len
> 2 && in
->ptr
[idx
+1] == '\'' && ISBASE (in
->ptr
[idx
]))
1548 while (!ISSEP (in
->ptr
[idx
]))
1549 sb_add_char (out
, in
->ptr
[idx
++]);
1551 else if (in
->ptr
[idx
] == '%'
1557 /* Turns the next expression into a string */
1558 idx
= exp_get_abs ("% operator needs absolute expression",
1562 sprintf(buf
, "%d", val
);
1563 sb_add_string (out
, buf
);
1565 else if (in
->ptr
[idx
] == '"'
1566 || in
->ptr
[idx
] == '<'
1567 || (alternate
&& in
->ptr
[idx
] == '\''))
1569 if (alternate
&& expand
)
1571 /* Keep the quotes */
1572 sb_add_char (out
, '\"');
1574 idx
= getstring (idx
, in
, out
);
1575 sb_add_char (out
, '\"');
1579 idx
= getstring (idx
, in
, out
);
1584 while (idx
< in
->len
1585 && (in
->ptr
[idx
] == '"'
1586 || in
->ptr
[idx
] == '\''
1588 || !ISSEP (in
->ptr
[idx
])))
1590 if (in
->ptr
[idx
] == '"'
1591 || in
->ptr
[idx
] == '\'')
1593 char tchar
= in
->ptr
[idx
];
1594 sb_add_char (out
, in
->ptr
[idx
++]);
1595 while (idx
< in
->len
1596 && in
->ptr
[idx
] != tchar
)
1597 sb_add_char (out
, in
->ptr
[idx
++]);
1601 sb_add_char (out
, in
->ptr
[idx
++]);
1610 /* skip along sb in starting at idx, suck off whitespace a ( and more
1611 whitespace. return the idx of the next char */
1614 skip_openp (idx
, in
)
1618 idx
= sb_skip_white (idx
, in
);
1619 if (in
->ptr
[idx
] != '(')
1620 ERROR ((stderr
, "misplaced ( .\n"));
1621 idx
= sb_skip_white (idx
+ 1, in
);
1625 /* skip along sb in starting at idx, suck off whitespace a ) and more
1626 whitespace. return the idx of the next char */
1629 skip_closep (idx
, in
)
1633 idx
= sb_skip_white (idx
, in
);
1634 if (in
->ptr
[idx
] != ')')
1635 ERROR ((stderr
, "misplaced ).\n"));
1636 idx
= sb_skip_white (idx
+ 1, in
);
1643 dolen (idx
, in
, out
)
1652 sb_new (&stringout
);
1653 idx
= skip_openp (idx
, in
);
1654 idx
= get_and_process (idx
, in
, &stringout
);
1655 idx
= skip_closep (idx
, in
);
1656 sprintf (buffer
, "%d", stringout
.len
);
1657 sb_add_string (out
, buffer
);
1659 sb_kill (&stringout
);
1668 doinstr (idx
, in
, out
)
1682 idx
= skip_openp (idx
, in
);
1683 idx
= get_and_process (idx
, in
, &string
);
1684 idx
= sb_skip_comma (idx
, in
);
1685 idx
= get_and_process (idx
, in
, &search
);
1686 idx
= sb_skip_comma (idx
, in
);
1687 if (isdigit (in
->ptr
[idx
]))
1689 idx
= exp_get_abs (".instr needs absolute expresson.\n", idx
, in
, &start
);
1695 idx
= skip_closep (idx
, in
);
1697 for (i
= start
; i
< string
.len
; i
++)
1699 if (strncmp (string
.ptr
+ i
, search
.ptr
, search
.len
) == 0)
1705 sprintf (buffer
, "%d", res
);
1706 sb_add_string (out
, buffer
);
1714 dosubstr (idx
, in
, out
)
1724 idx
= skip_openp (idx
, in
);
1725 idx
= get_and_process (idx
, in
, &string
);
1726 idx
= sb_skip_comma (idx
, in
);
1727 idx
= exp_get_abs ("need absolute position.\n", idx
, in
, &pos
);
1728 idx
= sb_skip_comma (idx
, in
);
1729 idx
= exp_get_abs ("need absolute length.\n", idx
, in
, &len
);
1730 idx
= skip_closep (idx
, in
);
1733 if (len
< 0 || pos
< 0 ||
1735 || pos
+ len
> string
.len
)
1737 sb_add_string (out
, " ");
1741 sb_add_char (out
, '"');
1744 sb_add_char (out
, string
.ptr
[pos
++]);
1747 sb_add_char (out
, '"');
1753 /* scan line, change tokens in the hash table to their replacements */
1755 process_assigns (idx
, in
, buf
)
1760 while (idx
< in
->len
)
1763 if (in
->ptr
[idx
] == '\\'
1764 && in
->ptr
[idx
+ 1] == '&')
1766 idx
= condass_lookup_name (in
, idx
+ 2, buf
, 1);
1768 else if (in
->ptr
[idx
] == '\\'
1769 && in
->ptr
[idx
+ 1] == '$')
1771 idx
= condass_lookup_name (in
, idx
+ 2, buf
, 0);
1773 else if (idx
+ 3 < in
->len
1774 && in
->ptr
[idx
] == '.'
1775 && toupper ((unsigned char) in
->ptr
[idx
+ 1]) == 'L'
1776 && toupper ((unsigned char) in
->ptr
[idx
+ 2]) == 'E'
1777 && toupper ((unsigned char) in
->ptr
[idx
+ 3]) == 'N')
1778 idx
= dolen (idx
+ 4, in
, buf
);
1779 else if (idx
+ 6 < in
->len
1780 && in
->ptr
[idx
] == '.'
1781 && toupper ((unsigned char) in
->ptr
[idx
+ 1]) == 'I'
1782 && toupper ((unsigned char) in
->ptr
[idx
+ 2]) == 'N'
1783 && toupper ((unsigned char) in
->ptr
[idx
+ 3]) == 'S'
1784 && toupper ((unsigned char) in
->ptr
[idx
+ 4]) == 'T'
1785 && toupper ((unsigned char) in
->ptr
[idx
+ 5]) == 'R')
1786 idx
= doinstr (idx
+ 6, in
, buf
);
1787 else if (idx
+ 7 < in
->len
1788 && in
->ptr
[idx
] == '.'
1789 && toupper ((unsigned char) in
->ptr
[idx
+ 1]) == 'S'
1790 && toupper ((unsigned char) in
->ptr
[idx
+ 2]) == 'U'
1791 && toupper ((unsigned char) in
->ptr
[idx
+ 3]) == 'B'
1792 && toupper ((unsigned char) in
->ptr
[idx
+ 4]) == 'S'
1793 && toupper ((unsigned char) in
->ptr
[idx
+ 5]) == 'T'
1794 && toupper ((unsigned char) in
->ptr
[idx
+ 6]) == 'R')
1795 idx
= dosubstr (idx
+ 7, in
, buf
);
1796 else if (ISFIRSTCHAR (in
->ptr
[idx
]))
1798 /* may be a simple name subsitution, see if we have a word */
1801 while (cur
< in
->len
1802 && (ISNEXTCHAR (in
->ptr
[cur
])))
1806 sb_add_buffer (&acc
, in
->ptr
+ idx
, cur
- idx
);
1807 ptr
= hash_lookup (&assign_hash_table
, &acc
);
1810 /* Found a definition for it */
1811 sb_add_sb (buf
, &ptr
->value
.s
);
1815 /* No definition, just copy the word */
1816 sb_add_sb (buf
, &acc
);
1823 sb_add_char (buf
, in
->ptr
[idx
++]);
1829 get_and_process (idx
, in
, out
)
1836 idx
= get_any_string (idx
, in
, &t
, 1, 0);
1837 process_assigns (0, &t
, out
);
1858 more
= get_line (&line
);
1861 /* Find any label and pseudo op that we're intested in */
1866 fprintf (outfile
, "\n");
1869 && (line
.ptr
[0] == '*'
1870 || line
.ptr
[0] == '!'))
1872 /* MRI line comment. */
1873 fprintf (outfile
, sb_name (&line
));
1877 l
= grab_label (&line
, &label_in
);
1881 /* Munge any label */
1884 process_assigns (0, &label_in
, &label
);
1887 if (line
.ptr
[l
] == ':')
1889 while (ISWHITE (line
.ptr
[l
]) && l
< line
.len
)
1894 if (process_pseudo_op (l
, &line
, &acc
))
1900 else if (condass_on ())
1902 if (macro_op (l
, &line
))
1912 fprintf (outfile
, "%s:\t", sb_name (&label
));
1915 fprintf (outfile
, "\t");
1917 process_assigns (l
, &line
, &t1
);
1919 change_base (0, &t1
, &t2
);
1920 fprintf (outfile
, "%s\n", sb_name (&t2
));
1926 /* Only a label on this line */
1927 if (label
.len
&& condass_on())
1929 fprintf (outfile
, "%s:\n", sb_name (&label
));
1937 more
= get_line (&line
);
1940 if (!had_end
&& !mri
)
1941 WARNING ((stderr
, "END missing from end of file.\n"));
1949 free_old_entry (ptr
)
1954 if (ptr
->type
== hash_string
)
1955 sb_kill(&ptr
->value
.s
);
1959 /* name: .ASSIGNA <value> */
1962 do_assigna (idx
, in
)
1970 process_assigns (idx
, in
, &tmp
);
1971 idx
= exp_get_abs (".ASSIGNA needs constant expression argument.\n", 0, &tmp
, &val
);
1975 ERROR ((stderr
, ".ASSIGNA without label.\n"));
1979 hash_entry
*ptr
= hash_create (&vars
, &label
);
1980 free_old_entry (ptr
);
1981 ptr
->type
= hash_integer
;
1987 /* name: .ASSIGNC <string> */
1990 do_assignc (idx
, in
)
1996 idx
= getstring (idx
, in
, &acc
);
2000 ERROR ((stderr
, ".ASSIGNS without label.\n"));
2004 hash_entry
*ptr
= hash_create (&vars
, &label
);
2005 free_old_entry (ptr
);
2006 ptr
->type
= hash_string
;
2007 sb_new (&ptr
->value
.s
);
2008 sb_add_sb (&ptr
->value
.s
, &acc
);
2014 /* name: .REG (reg) */
2021 /* remove reg stuff from inside parens */
2024 idx
= skip_openp (idx
, in
);
2026 idx
= sb_skip_white (idx
, in
);
2028 while (idx
< in
->len
2031 : in
->ptr
[idx
] != ')'))
2033 sb_add_char (&what
, in
->ptr
[idx
]);
2036 hash_add_to_string_table (&assign_hash_table
, &label
, &what
, 1);
2042 condass_lookup_name (inbuf
, idx
, out
, warn
)
2050 sb_new (&condass_acc
);
2052 while (idx
< inbuf
->len
2053 && ISNEXTCHAR (inbuf
->ptr
[idx
]))
2055 sb_add_char (&condass_acc
, inbuf
->ptr
[idx
++]);
2058 if (inbuf
->ptr
[idx
] == '\'')
2060 ptr
= hash_lookup (&vars
, &condass_acc
);
2067 WARNING ((stderr
, "Can't find preprocessor variable %s.\n", sb_name (&condass_acc
)));
2071 sb_add_string (out
, "0");
2076 if (ptr
->type
== hash_integer
)
2079 sprintf (buffer
, "%d", ptr
->value
.i
);
2080 sb_add_string (out
, buffer
);
2084 sb_add_sb (out
, &ptr
->value
.s
);
2087 sb_kill (&condass_acc
);
2100 whatcond (idx
, in
, val
)
2107 idx
= sb_skip_white (idx
, in
);
2109 if (idx
+ 1 < in
->len
)
2115 a
= toupper ((unsigned char) p
[0]);
2116 b
= toupper ((unsigned char) p
[1]);
2117 if (a
== 'E' && b
== 'Q')
2119 else if (a
== 'N' && b
== 'E')
2121 else if (a
== 'L' && b
== 'T')
2123 else if (a
== 'L' && b
== 'E')
2125 else if (a
== 'G' && b
== 'T')
2127 else if (a
== 'G' && b
== 'E')
2132 ERROR ((stderr
, "Comparison operator must be one of EQ, NE, LT, LE, GT or GE.\n"));
2135 idx
= sb_skip_white (idx
+ 2, in
);
2152 idx
= sb_skip_white (idx
, in
);
2154 if (in
->ptr
[idx
] == '"')
2158 /* This is a string comparision */
2159 idx
= getstring (idx
, in
, &acc_a
);
2160 idx
= whatcond (idx
, in
, &cond
);
2161 idx
= getstring (idx
, in
, &acc_b
);
2162 same
= acc_a
.len
== acc_b
.len
&& (strncmp (acc_a
.ptr
, acc_b
.ptr
, acc_a
.len
) == 0);
2164 if (cond
!= EQ
&& cond
!= NE
)
2166 ERROR ((stderr
, "Comparison operator for strings must be EQ or NE\n"));
2170 res
= (cond
!= EQ
) ^ same
;
2173 /* This is a numeric expression */
2178 idx
= exp_get_abs ("Conditional operator must have absolute operands.\n", idx
, in
, &vala
);
2179 idx
= whatcond (idx
, in
, &cond
);
2180 idx
= sb_skip_white (idx
, in
);
2181 if (in
->ptr
[idx
] == '"')
2183 WARNING ((stderr
, "String compared against expression.\n"));
2188 idx
= exp_get_abs ("Conditional operator must have absolute operands.\n", idx
, in
, &valb
);
2231 if (ifi
>= IFNESTING
)
2233 FATAL ((stderr
, "AIF nesting unreasonable.\n"));
2236 ifstack
[ifi
].on
= ifstack
[ifi
-1].on
? istrue (idx
, in
) : 0;
2237 ifstack
[ifi
].hadelse
= 0;
2245 ifstack
[ifi
].on
= ifstack
[ifi
-1].on
? !ifstack
[ifi
].on
: 0;
2246 if (ifstack
[ifi
].hadelse
)
2248 ERROR ((stderr
, "Multiple AELSEs in AIF.\n"));
2250 ifstack
[ifi
].hadelse
= 1;
2264 ERROR ((stderr
, "AENDI without AIF.\n"));
2271 return ifstack
[ifi
].on
;
2274 /* MRI IFEQ, IFNE, IFLT, IFLE, IFGE, IFGT. */
2277 do_if (idx
, in
, cond
)
2285 if (ifi
>= IFNESTING
)
2287 FATAL ((stderr
, "IF nesting unreasonable.\n"));
2290 idx
= exp_get_abs ("Conditional operator must have absolute operands.\n",
2295 case EQ
: res
= val
== 0; break;
2296 case NE
: res
= val
!= 0; break;
2297 case LT
: res
= val
< 0; break;
2298 case LE
: res
= val
<= 0; break;
2299 case GE
: res
= val
>= 0; break;
2300 case GT
: res
= val
> 0; break;
2304 ifstack
[ifi
].on
= ifstack
[ifi
-1].on
? res
: 0;
2305 ifstack
[ifi
].hadelse
= 0;
2308 /* Get a string for the MRI IFC or IFNC pseudo-ops. */
2311 get_mri_string (idx
, in
, val
, terminator
)
2317 idx
= sb_skip_white (idx
, in
);
2320 && in
->ptr
[idx
] == '\'')
2322 sb_add_char (val
, '\'');
2323 for (++idx
; idx
< in
->len
; ++idx
)
2325 sb_add_char (val
, in
->ptr
[idx
]);
2326 if (in
->ptr
[idx
] == '\'')
2330 || in
->ptr
[idx
] != '\'')
2334 idx
= sb_skip_white (idx
, in
);
2340 while (idx
< in
->len
2341 && in
->ptr
[idx
] != terminator
)
2343 sb_add_char (val
, in
->ptr
[idx
]);
2347 while (i
>= 0 && ISWHITE (val
->ptr
[i
]))
2355 /* MRI IFC, IFNC. */
2358 do_ifc (idx
, in
, ifnc
)
2367 if (ifi
>= IFNESTING
)
2369 FATAL ((stderr
, "IF nesting unreasonable.\n"));
2375 idx
= get_mri_string (idx
, in
, &first
, ',');
2377 if (idx
>= in
->len
|| in
->ptr
[idx
] != ',')
2379 ERROR ((stderr
, "Bad format for IF or IFNC.\n"));
2383 idx
= get_mri_string (idx
+ 1, in
, &second
, ';');
2385 res
= (first
.len
== second
.len
2386 && strncmp (first
.ptr
, second
.ptr
, first
.len
) == 0);
2390 ifstack
[ifi
].on
= ifstack
[ifi
-1].on
? res
: 0;
2391 ifstack
[ifi
].hadelse
= 0;
2399 ERROR ((stderr
, "AENDR without a AREPEAT.\n"));
2401 ERROR ((stderr
, "ENDR without a REPT.\n"));
2412 int line
= linecount ();
2420 process_assigns (idx
, in
, &exp
);
2421 doit
= istrue (0, &exp
);
2423 if (! buffer_and_nest ("AWHILE", "AENDW", &sub
, get_line
))
2424 FATAL ((stderr
, "AWHILE without a AENDW at %d.\n", line
- 1));
2439 int index
= include_next_index ();
2443 sb_add_sb (©
, &sub
);
2444 sb_add_sb (©
, in
);
2445 sb_add_string (©
, "\n");
2446 sb_add_sb (©
, &sub
);
2447 sb_add_string (©
, "\t.AENDW\n");
2448 /* Push another WHILE */
2449 include_buf (&exp
, ©
, include_while
, index
);
2462 ERROR ((stderr
, "AENDW without a AENDW.\n"));
2468 Pop things off the include stack until the type and index changes */
2473 include_type type
= sp
->type
;
2474 if (type
== include_repeat
2475 || type
== include_while
2476 || type
== include_macro
)
2478 int index
= sp
->index
;
2480 while (sp
->index
== index
2481 && sp
->type
== type
)
2491 do_arepeat (idx
, in
)
2495 int line
= linecount ();
2496 sb exp
; /* buffer with expression in it */
2497 sb copy
; /* expanded repeat block */
2498 sb sub
; /* contents of AREPEAT */
2506 process_assigns (idx
, in
, &exp
);
2507 idx
= exp_get_abs ("AREPEAT must have absolute operand.\n", 0, &exp
, &rc
);
2509 ret
= buffer_and_nest ("AREPEAT", "AENDR", &sub
, get_line
);
2511 ret
= buffer_and_nest ("REPT", "ENDR", &sub
, get_line
);
2513 FATAL ((stderr
, "AREPEAT without a AENDR at %d.\n", line
- 1));
2516 /* Push back the text following the repeat, and another repeat block
2527 int index
= include_next_index ();
2528 sb_add_sb (©
, &sub
);
2532 sprintf (buffer
, "\t.AREPEAT %d\n", rc
- 1);
2534 sprintf (buffer
, "\tREPT %d\n", rc
- 1);
2535 sb_add_string (©
, buffer
);
2536 sb_add_sb (©
, &sub
);
2538 sb_add_string (©
, " .AENDR\n");
2540 sb_add_string (©
, " ENDR\n");
2543 include_buf (&exp
, ©
, include_repeat
, index
);
2555 ERROR ((stderr
, ".ENDM without a matching .MACRO.\n"));
2558 /* MRI IRP pseudo-op. */
2561 do_irp (idx
, in
, irpc
)
2571 err
= expand_irp (irpc
, idx
, in
, &out
, get_line
, comment_char
);
2573 ERROR ((stderr
, "%s\n", err
));
2575 fprintf (outfile
, "%s", sb_terminate (&out
));
2580 /* MACRO PROCESSING */
2582 /* Parse off LOCAL n1, n2,... Invent a label name for it */
2585 do_local (idx
, line
)
2589 ERROR ((stderr
, "LOCAL outside of MACRO"));
2598 int line
= linecount ();
2600 err
= define_macro (idx
, in
, &label
, get_line
);
2602 ERROR ((stderr
, "macro at line %d: %s\n", line
- 1, err
));
2614 if (! macro_defined
)
2618 if (! check_macro (in
->ptr
+ idx
, &out
, comment_char
, &err
))
2622 ERROR ((stderr
, "%s\n", err
));
2625 sb_add_string (&name
, "macro expansion");
2627 include_buf (&name
, &out
, include_macro
, include_next_index ());
2635 /* STRING HANDLING */
2638 getstring (idx
, in
, acc
)
2643 idx
= sb_skip_white (idx
, in
);
2645 while (idx
< in
->len
2646 && (in
->ptr
[idx
] == '"'
2647 || in
->ptr
[idx
] == '<'
2648 || (in
->ptr
[idx
] == '\'' && alternate
)))
2650 if (in
->ptr
[idx
] == '<')
2652 if (alternate
|| mri
)
2656 while ((in
->ptr
[idx
] != '>' || nest
)
2659 if (in
->ptr
[idx
] == '!')
2662 sb_add_char (acc
, in
->ptr
[idx
++]);
2665 if (in
->ptr
[idx
] == '>')
2667 if (in
->ptr
[idx
] == '<')
2669 sb_add_char (acc
, in
->ptr
[idx
++]);
2677 idx
= exp_get_abs ("Character code in string must be absolute expression.\n",
2679 sb_add_char (acc
, code
);
2681 if (in
->ptr
[idx
] != '>')
2682 ERROR ((stderr
, "Missing > for character code.\n"));
2686 else if (in
->ptr
[idx
] == '"' || in
->ptr
[idx
] == '\'')
2688 char tchar
= in
->ptr
[idx
];
2690 while (idx
< in
->len
)
2692 if (alternate
&& in
->ptr
[idx
] == '!')
2695 sb_add_char (acc
, in
->ptr
[idx
++]);
2698 if (in
->ptr
[idx
] == tchar
)
2701 if (idx
>= in
->len
|| in
->ptr
[idx
] != tchar
)
2704 sb_add_char (acc
, in
->ptr
[idx
]);
2714 /* .SDATA[C|Z] <string> */
2718 do_sdata (idx
, in
, type
)
2727 fprintf (outfile
, ".byte\t");
2729 while (!eol (idx
, in
))
2733 idx
= sb_skip_white (idx
, in
);
2734 while (!eol (idx
, in
))
2736 pidx
= idx
= get_any_string (idx
, in
, &acc
, 0, 1);
2741 ERROR ((stderr
, "string for SDATAC longer than 255 characters (%d).\n", acc
.len
));
2743 fprintf (outfile
, "%d", acc
.len
);
2747 for (i
= 0; i
< acc
.len
; i
++)
2751 fprintf (outfile
, ",");
2753 fprintf (outfile
, "%d", acc
.ptr
[i
]);
2760 fprintf (outfile
, ",");
2761 fprintf (outfile
, "0");
2763 idx
= sb_skip_comma (idx
, in
);
2764 if (idx
== pidx
) break;
2766 if (!alternate
&& in
->ptr
[idx
] != ',' && idx
!= in
->len
)
2768 fprintf (outfile
, "\n");
2769 ERROR ((stderr
, "illegal character in SDATA line (0x%x).\n", in
->ptr
[idx
]));
2775 fprintf (outfile
, "\n");
2778 /* .SDATAB <count> <string> */
2790 idx
= exp_get_abs ("Must have absolute SDATAB repeat count.\n", idx
, in
, &repeat
);
2793 ERROR ((stderr
, "Must have positive SDATAB repeat count (%d).\n", repeat
));
2797 idx
= sb_skip_comma (idx
, in
);
2798 idx
= getstring (idx
, in
, &acc
);
2800 for (i
= 0; i
< repeat
; i
++)
2803 fprintf (outfile
, "\t");
2804 fprintf (outfile
, ".byte\t");
2805 sb_print (outfile
, &acc
);
2806 fprintf (outfile
, "\n");
2816 FILE *newone
= fopen (name
, "r");
2820 if (isp
== MAX_INCLUDES
)
2821 FATAL ((stderr
, "Unreasonable include depth (%ld).\n", (long) isp
));
2824 sp
->handle
= newone
;
2827 sb_add_string (&sp
->name
, name
);
2830 sp
->pushback_index
= 0;
2831 sp
->type
= include_file
;
2833 sb_new (&sp
->pushback
);
2838 do_include (idx
, in
)
2844 include_path
*includes
;
2850 idx
= getstring (idx
, in
, &t
);
2853 idx
= sb_skip_white (idx
, in
);
2854 while (idx
< in
->len
&& ! ISWHITE (in
->ptr
[idx
]))
2856 sb_add_char (&t
, in
->ptr
[idx
]);
2861 for (includes
= paths_head
; includes
; includes
= includes
->next
)
2864 sb_add_sb (&cat
, &includes
->path
);
2865 sb_add_char (&cat
, '/');
2866 sb_add_sb (&cat
, &t
);
2867 if (new_file (sb_name (&cat
)))
2874 if (! new_file (sb_name (&t
)))
2875 FATAL ((stderr
, "Can't open include file `%s'.\n", sb_name (&t
)));
2884 if (sp
!= include_stack
)
2887 fclose (sp
->handle
);
2892 /* Get the next character from the include stack. If there's anything
2893 in the pushback buffer, take that first. If we're at eof, pop from
2894 the stack and try again. Keep the linecount up to date. */
2901 if (sp
->pushback
.len
!= sp
->pushback_index
)
2903 r
= (char) (sp
->pushback
.ptr
[sp
->pushback_index
++]);
2904 /* When they've all gone, reset the pointer */
2905 if (sp
->pushback_index
== sp
->pushback
.len
)
2907 sp
->pushback
.len
= 0;
2908 sp
->pushback_index
= 0;
2911 else if (sp
->handle
)
2913 r
= getc (sp
->handle
);
2918 if (r
== EOF
&& isp
)
2922 while (r
== EOF
&& isp
)
2940 return sp
->linecount
;
2944 include_next_index ()
2948 && index
> MAX_REASONABLE
)
2949 FATAL ((stderr
, "Unreasonable expansion (-u turns off check).\n"));
2954 /* Initialize the chartype vector. */
2960 for (x
= 0; x
< 256; x
++)
2962 if (isalpha (x
) || x
== '_' || x
== '$')
2963 chartype
[x
] |= FIRSTBIT
;
2965 if (mri
&& x
== '.')
2966 chartype
[x
] |= FIRSTBIT
;
2968 if (isdigit (x
) || isalpha (x
) || x
== '_' || x
== '$')
2969 chartype
[x
] |= NEXTBIT
;
2971 if (x
== ' ' || x
== '\t' || x
== ',' || x
== '"' || x
== ';'
2972 || x
== '"' || x
== '<' || x
== '>' || x
== ')' || x
== '(')
2973 chartype
[x
] |= SEPBIT
;
2975 if (x
== 'b' || x
== 'B'
2976 || x
== 'q' || x
== 'Q'
2977 || x
== 'h' || x
== 'H'
2978 || x
== 'd' || x
== 'D')
2979 chartype
[x
] |= BASEBIT
;
2981 if (x
== ' ' || x
== '\t')
2982 chartype
[x
] |= WHITEBIT
;
2984 if (x
== comment_char
)
2985 chartype
[x
] |= COMMENTBIT
;
2991 /* What to do with all the keywords */
2992 #define PROCESS 0x1000 /* Run substitution over the line */
2993 #define LAB 0x2000 /* Spit out the label */
2995 #define K_EQU (PROCESS|1)
2996 #define K_ASSIGN (PROCESS|2)
2997 #define K_REG (PROCESS|3)
2998 #define K_ORG (PROCESS|4)
2999 #define K_RADIX (PROCESS|5)
3000 #define K_DATA (LAB|PROCESS|6)
3001 #define K_DATAB (LAB|PROCESS|7)
3002 #define K_SDATA (LAB|PROCESS|8)
3003 #define K_SDATAB (LAB|PROCESS|9)
3004 #define K_SDATAC (LAB|PROCESS|10)
3005 #define K_SDATAZ (LAB|PROCESS|11)
3006 #define K_RES (LAB|PROCESS|12)
3007 #define K_SRES (LAB|PROCESS|13)
3008 #define K_SRESC (LAB|PROCESS|14)
3009 #define K_SRESZ (LAB|PROCESS|15)
3010 #define K_EXPORT (LAB|PROCESS|16)
3011 #define K_GLOBAL (LAB|PROCESS|17)
3012 #define K_PRINT (LAB|PROCESS|19)
3013 #define K_FORM (LAB|PROCESS|20)
3014 #define K_HEADING (LAB|PROCESS|21)
3015 #define K_PAGE (LAB|PROCESS|22)
3016 #define K_IMPORT (LAB|PROCESS|23)
3017 #define K_PROGRAM (LAB|PROCESS|24)
3018 #define K_END (PROCESS|25)
3019 #define K_INCLUDE (PROCESS|26)
3020 #define K_IGNORED (PROCESS|27)
3021 #define K_ASSIGNA (PROCESS|28)
3022 #define K_ASSIGNC (29)
3023 #define K_AIF (PROCESS|30)
3024 #define K_AELSE (PROCESS|31)
3025 #define K_AENDI (PROCESS|32)
3026 #define K_AREPEAT (PROCESS|33)
3027 #define K_AENDR (PROCESS|34)
3028 #define K_AWHILE (35)
3029 #define K_AENDW (PROCESS|36)
3030 #define K_EXITM (37)
3031 #define K_MACRO (PROCESS|38)
3033 #define K_ALIGN (PROCESS|LAB|40)
3034 #define K_ALTERNATE (41)
3035 #define K_DB (LAB|PROCESS|42)
3036 #define K_DW (LAB|PROCESS|43)
3037 #define K_DL (LAB|PROCESS|44)
3038 #define K_LOCAL (45)
3039 #define K_IFEQ (PROCESS|46)
3040 #define K_IFNE (PROCESS|47)
3041 #define K_IFLT (PROCESS|48)
3042 #define K_IFLE (PROCESS|49)
3043 #define K_IFGE (PROCESS|50)
3044 #define K_IFGT (PROCESS|51)
3045 #define K_IFC (PROCESS|52)
3046 #define K_IFNC (PROCESS|53)
3047 #define K_IRP (PROCESS|54)
3048 #define K_IRPC (PROCESS|55)
3058 static struct keyword kinfo
[] =
3060 { "EQU", K_EQU
, 0 },
3061 { "ALTERNATE", K_ALTERNATE
, 0 },
3062 { "ASSIGN", K_ASSIGN
, 0 },
3063 { "REG", K_REG
, 0 },
3064 { "ORG", K_ORG
, 0 },
3065 { "RADIX", K_RADIX
, 0 },
3066 { "DATA", K_DATA
, 0 },
3070 { "DATAB", K_DATAB
, 0 },
3071 { "SDATA", K_SDATA
, 0 },
3072 { "SDATAB", K_SDATAB
, 0 },
3073 { "SDATAZ", K_SDATAZ
, 0 },
3074 { "SDATAC", K_SDATAC
, 0 },
3075 { "RES", K_RES
, 0 },
3076 { "SRES", K_SRES
, 0 },
3077 { "SRESC", K_SRESC
, 0 },
3078 { "SRESZ", K_SRESZ
, 0 },
3079 { "EXPORT", K_EXPORT
, 0 },
3080 { "GLOBAL", K_GLOBAL
, 0 },
3081 { "PRINT", K_PRINT
, 0 },
3082 { "FORM", K_FORM
, 0 },
3083 { "HEADING", K_HEADING
, 0 },
3084 { "PAGE", K_PAGE
, 0 },
3085 { "PROGRAM", K_IGNORED
, 0 },
3086 { "END", K_END
, 0 },
3087 { "INCLUDE", K_INCLUDE
, 0 },
3088 { "ASSIGNA", K_ASSIGNA
, 0 },
3089 { "ASSIGNC", K_ASSIGNC
, 0 },
3090 { "AIF", K_AIF
, 0 },
3091 { "AELSE", K_AELSE
, 0 },
3092 { "AENDI", K_AENDI
, 0 },
3093 { "AREPEAT", K_AREPEAT
, 0 },
3094 { "AENDR", K_AENDR
, 0 },
3095 { "EXITM", K_EXITM
, 0 },
3096 { "MACRO", K_MACRO
, 0 },
3097 { "ENDM", K_ENDM
, 0 },
3098 { "AWHILE", K_AWHILE
, 0 },
3099 { "ALIGN", K_ALIGN
, 0 },
3100 { "AENDW", K_AENDW
, 0 },
3101 { "ALTERNATE", K_ALTERNATE
, 0 },
3102 { "LOCAL", K_LOCAL
, 0 },
3106 /* Although the conditional operators are handled by gas, we need to
3107 handle them here as well, in case they are used in a recursive
3108 macro to end the recursion. */
3110 static struct keyword mrikinfo
[] =
3112 { "IFEQ", K_IFEQ
, 0 },
3113 { "IFNE", K_IFNE
, 0 },
3114 { "IFLT", K_IFLT
, 0 },
3115 { "IFLE", K_IFLE
, 0 },
3116 { "IFGE", K_IFGE
, 0 },
3117 { "IFGT", K_IFGT
, 0 },
3118 { "IFC", K_IFC
, 0 },
3119 { "IFNC", K_IFNC
, 0 },
3120 { "ELSEC", K_AELSE
, 0 },
3121 { "ENDC", K_AENDI
, 0 },
3122 { "MEXIT", K_EXITM
, 0 },
3123 { "REPT", K_AREPEAT
, 0 },
3124 { "IRP", K_IRP
, 0 },
3125 { "IRPC", K_IRPC
, 0 },
3126 { "ENDR", K_AENDR
, 0 },
3130 /* Look for a pseudo op on the line. If one's there then call
3134 process_pseudo_op (idx
, line
, acc
)
3141 if (line
->ptr
[idx
] == '.' || alternate
|| mri
)
3143 /* Scan forward and find pseudo name */
3149 if (line
->ptr
[idx
] == '.')
3151 in
= line
->ptr
+ idx
;
3156 while (idx
< line
->len
&& *e
&& ISFIRSTCHAR (*e
))
3158 sb_add_char (acc
, *e
);
3163 ptr
= hash_lookup (&keyword_hash_table
, acc
);
3168 /* This one causes lots of pain when trying to preprocess
3170 WARNING ((stderr
, "Unrecognised pseudo op `%s'.\n", sb_name (acc
)));
3174 if (ptr
->value
.i
& LAB
)
3175 { /* output the label */
3178 fprintf (outfile
, "%s:\t", sb_name (&label
));
3181 fprintf (outfile
, "\t");
3184 if (mri
&& ptr
->value
.i
== K_END
)
3189 sb_add_buffer (&t
, line
->ptr
+ oidx
, idx
- oidx
);
3190 fprintf (outfile
, "\t%s", sb_name (&t
));
3194 if (ptr
->value
.i
& PROCESS
)
3196 /* Polish the rest of the line before handling the pseudo op */
3198 strip_comments(line
);
3201 process_assigns (idx
, line
, acc
);
3203 change_base (0, acc
, line
);
3208 switch (ptr
->value
.i
)
3224 switch (ptr
->value
.i
)
3228 macro_init (1, mri
, 0, exp_get_abs
);
3237 ERROR ((stderr
, "ORG command not allowed.\n"));
3243 do_data (idx
, line
, 1);
3246 do_data (idx
, line
, 2);
3249 do_data (idx
, line
, 4);
3252 do_data (idx
, line
, 0);
3255 do_datab (idx
, line
);
3258 do_sdata (idx
, line
, 0);
3261 do_sdatab (idx
, line
);
3264 do_sdata (idx
, line
, 'c');
3267 do_sdata (idx
, line
, 'z');
3270 do_assign (1, 0, line
);
3276 do_arepeat (idx
, line
);
3282 do_awhile (idx
, line
);
3288 do_assign (0, idx
, line
);
3291 do_align (idx
, line
);
3294 do_res (idx
, line
, 0);
3297 do_res (idx
, line
, 's');
3300 do_include (idx
, line
);
3303 do_local (idx
, line
);
3306 do_macro (idx
, line
);
3312 do_res (idx
, line
, 'c');
3315 do_print (idx
, line
);
3318 do_form (idx
, line
);
3321 do_heading (idx
, line
);
3333 do_res (idx
, line
, 'z');
3341 do_assigna (idx
, line
);
3344 do_assignc (idx
, line
);
3353 do_if (idx
, line
, EQ
);
3356 do_if (idx
, line
, NE
);
3359 do_if (idx
, line
, LT
);
3362 do_if (idx
, line
, LE
);
3365 do_if (idx
, line
, GE
);
3368 do_if (idx
, line
, GT
);
3371 do_ifc (idx
, line
, 0);
3374 do_ifc (idx
, line
, 1);
3377 do_irp (idx
, line
, 0);
3380 do_irp (idx
, line
, 1);
3390 /* Add a keyword to the hash table. */
3393 add_keyword (name
, code
)
3401 sb_add_string (&label
, name
);
3403 hash_add_to_int_table (&keyword_hash_table
, &label
, code
);
3406 for (j
= 0; name
[j
]; j
++)
3407 sb_add_char (&label
, name
[j
] - 'A' + 'a');
3408 hash_add_to_int_table (&keyword_hash_table
, &label
, code
);
3413 /* Build the keyword hash table - put each keyword in the table twice,
3414 once upper and once lower case.*/
3421 for (i
= 0; kinfo
[i
].name
; i
++)
3422 add_keyword (kinfo
[i
].name
, kinfo
[i
].code
);
3426 for (i
= 0; mrikinfo
[i
].name
; i
++)
3427 add_keyword (mrikinfo
[i
].name
, mrikinfo
[i
].code
);
3451 sb_add_char (&value
, *string
);
3454 exp_get_abs ("Invalid expression on command line.\n", 0, &value
, &res
);
3458 sb_add_char (&label
, *string
);
3463 ptr
= hash_create (&vars
, &label
);
3464 free_old_entry (ptr
);
3465 ptr
->type
= hash_integer
;
3471 /* The list of long options. */
3472 static struct option long_options
[] =
3474 { "alternate", no_argument
, 0, 'a' },
3475 { "include", required_argument
, 0, 'I' },
3476 { "commentchar", required_argument
, 0, 'c' },
3477 { "copysource", no_argument
, 0, 's' },
3478 { "debug", no_argument
, 0, 'd' },
3479 { "help", no_argument
, 0, 'h' },
3480 { "mri", no_argument
, 0, 'M' },
3481 { "output", required_argument
, 0, 'o' },
3482 { "print", no_argument
, 0, 'p' },
3483 { "unreasonable", no_argument
, 0, 'u' },
3484 { "version", no_argument
, 0, 'v' },
3485 { "define", required_argument
, 0, 'd' },
3486 { NULL
, no_argument
, 0, 0 }
3489 /* Show a usage message and exit. */
3491 show_usage (file
, status
)
3497 [-a] [--alternate] enter alternate macro mode\n\
3498 [-c char] [--commentchar char] change the comment character from !\n\
3499 [-d] [--debug] print some debugging info\n\
3500 [-h] [--help] print this message\n\
3501 [-M] [--mri] enter MRI compatibility mode\n\
3502 [-o out] [--output out] set the output file\n\
3503 [-p] [--print] print line numbers\n", program_name
);
3505 [-s] [--copysource] copy source through as comments \n\
3506 [-u] [--unreasonable] allow unreasonable nesting\n\
3507 [-v] [--version] print the program version\n\
3508 [-Dname=value] create preprocessor variable called name, with value\n\
3509 [-Ipath] add to include path list\n\
3514 /* Display a help message and exit. */
3518 printf ("%s: Gnu Assembler Macro Preprocessor\n",
3520 show_usage (stdout
, 0);
3537 program_name
= argv
[0];
3538 xmalloc_set_program_name (program_name
);
3540 hash_new_table (101, &keyword_hash_table
);
3541 hash_new_table (101, &assign_hash_table
);
3542 hash_new_table (101, &vars
);
3546 while ((opt
= getopt_long (argc
, argv
, "I:sdhavc:upo:D:M", long_options
,
3560 include_path
*p
= (include_path
*) xmalloc (sizeof (include_path
));
3562 sb_add_string (&p
->path
, optarg
);
3564 paths_tail
->next
= p
;
3571 print_line_number
= 1;
3574 comment_char
= optarg
[0];
3596 printf ("GNU %s version %s\n", program_name
, program_version
);
3602 show_usage (stderr
, 1);
3609 macro_init (alternate
, mri
, 0, exp_get_abs
);
3612 outfile
= fopen (out_name
, "w");
3615 fprintf (stderr
, "%s: Can't open output file `%s'.\n",
3616 program_name
, out_name
);
3628 /* Process all the input files */
3630 while (optind
< argc
)
3632 if (new_file (argv
[optind
]))
3638 fprintf (stderr
, "%s: Can't open input file `%s'.\n",
3639 program_name
, argv
[optind
]);
3649 /* This function is used because an abort in some of the other files
3650 may be compiled into as_abort because they include as.h. */
3653 as_abort (file
, line
, fn
)
3654 const char *file
, *fn
;
3657 fprintf (stderr
, "Internal error, aborting at %s line %d", file
, line
);
3659 fprintf (stderr
, " in %s", fn
);
3660 fprintf (stderr
, "\nPlease report this bug.\n");