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"
69 char *program_version
= "1.2";
71 #define MAX_INCLUDES 30 /* Maximum include depth */
72 #define MAX_REASONABLE 1000 /* Maximum number of expansions */
74 int unreasonable
; /* -u on command line */
75 int stats
; /* -d on command line */
76 int print_line_number
; /* -p flag on command line */
77 int copysource
; /* -c flag on command line */
78 int warnings
; /* Number of WARNINGs generated so far. */
79 int errors
; /* Number of ERRORs generated so far. */
80 int fatals
; /* Number of fatal ERRORs generated so far (either 0 or 1). */
81 int alternate
= 0; /* -a on command line */
82 int mri
= 0; /* -M on command line */
83 char comment_char
= '!';
84 int radix
= 10; /* Default radix */
86 int had_end
; /* Seen .END */
88 /* The output stream */
93 I had a couple of choices when deciding upon this data structure.
94 gas uses null terminated strings for all its internal work. This
95 often means that parts of the program that want to examine
96 substrings have to manipulate the data in the string to do the
97 right thing (a common operation is to single out a bit of text by
98 saving away the character after it, nulling it out, operating on
99 the substring and then replacing the character which was under the
100 null). This is a pain and I remember a load of problems that I had with
101 code in gas which almost got this right. Also, it's harder to grow and
102 allocate null terminated strings efficiently.
104 Obstacks provide all the functionality needed, but are too
105 complicated, hence the sb.
107 An sb is allocated by the caller, and is initialzed to point to an
108 sb_element. sb_elements are kept on a free lists, and used when
109 needed, replaced onto the free list when unused.
112 #define max_power_two 30 /* don't allow strings more than
113 2^max_power_two long */
114 /* structure of an sb */
117 char *ptr
; /* points to the current block. */
118 int len
; /* how much is used. */
119 int pot
; /* the maximum length is 1<<pot */
124 /* Structure of the free list object of an sb */
136 sb_element
*size
[max_power_two
];
139 sb_list_vector free_list
;
141 int string_count
[max_power_two
];
143 /* the attributes of each character are stored as a bit pattern
144 chartype, which gives us quick tests. */
151 #define COMMENTBIT 16
153 #define ISCOMMENTCHAR(x) (chartype[(unsigned)(x)] & COMMENTBIT)
154 #define ISFIRSTCHAR(x) (chartype[(unsigned)(x)] & FIRSTBIT)
155 #define ISNEXTCHAR(x) (chartype[(unsigned)(x)] & NEXTBIT)
156 #define ISSEP(x) (chartype[(unsigned)(x)] & SEPBIT)
157 #define ISWHITE(x) (chartype[(unsigned)(x)] & WHITEBIT)
158 #define ISBASE(x) (chartype[(unsigned)(x)] & BASEBIT)
159 static char chartype
[256];
162 /* Conditional assembly uses the `ifstack'. Each aif pushes another
163 entry onto the stack, and sets the on flag if it should. The aelse
164 sets hadelse, and toggles on. An aend pops a level. We limit to
165 100 levels of nesting, not because we're facists pigs with read
166 only minds, but because more than 100 levels of nesting is probably
167 a bug in the user's macro structure. */
169 #define IFNESTING 100
172 int on
; /* is the level being output */
173 int hadelse
; /* has an aelse been seen */
178 /* The final and intermediate results of expression evaluation are kept in
179 exp_t's. Note that a symbol is not an sb, but a pointer into the input
180 line. It must be coped somewhere safe before the next line is read in. */
191 int value
; /* constant part */
192 symbol add_symbol
; /* name part */
193 symbol sub_symbol
; /* name part */
198 /* Hashing is done in a pretty standard way. A hash_table has a
199 pointer to a vector of pointers to hash_entrys, and the size of the
200 vector. A hash_entry contains a union of all the info we like to
201 store in hash table. If there is a hash collision, hash_entries
202 with the same hash are kept in a chain. */
204 /* What the data in a hash_entry means */
207 hash_integer
, /* name->integer mapping */
208 hash_string
, /* name->string mapping */
209 hash_macro
, /* name is a macro */
210 hash_formal
/* name is a formal argument */
215 sb key
; /* symbol name */
216 hash_type type
; /* symbol meaning */
221 struct macro_struct
*m
;
222 struct formal_struct
*f
;
224 struct hs
*next
; /* next hash_entry with same hash key */
234 /* Structures used to store macros.
236 Each macro knows its name and included text. It gets built with a
237 list of formal arguments, and also keeps a hash table which points
238 into the list to speed up formal search. Each formal knows its
239 name and its default value. Each time the macro is expanded, the
240 formals get the actual values attatched to them. */
242 /* describe the formal arguments to a macro */
244 typedef struct formal_struct
246 struct formal_struct
*next
; /* next formal in list */
247 sb name
; /* name of the formal */
248 sb def
; /* the default value */
249 sb actual
; /* the actual argument (changed on each expansion) */
250 int index
; /* the index of the formal 0..formal_count-1 */
254 /* describe the macro. */
256 typedef struct macro_struct
258 sb sub
; /* substitution text. */
259 int formal_count
; /* number of formal args. */
260 formal_entry
*formals
; /* pointer to list of formal_structs */
261 hash_table formal_hash
; /* hash table of formals. */
265 /* how we nest files and expand macros etc.
267 we keep a stack of of include_stack structs. each include file
268 pushes a new level onto the stack. we keep an sb with a pushback
269 too. unget chars are pushed onto the pushback sb, getchars first
270 checks the pushback sb before reading from the input stream.
272 small things are expanded by adding the text of the item onto the
273 pushback sb. larger items are grown by pushing a new level and
274 allocating the entire pushback buf for the item. each time
275 something like a macro is expanded, the stack index is changed. we
276 can then perform an exitm by popping all entries off the stack with
277 the same stack index. if we're being reasonable, we can detect
278 recusive expansion by checking the index is reasonably small.
283 include_file
, include_repeat
, include_while
, include_macro
288 sb pushback
; /* current pushback stream */
289 int pushback_index
; /* next char to read from stream */
290 FILE *handle
; /* open file */
291 sb name
; /* name of file */
292 int linecount
; /* number of lines read so far */
294 int index
; /* index of this layer */
296 include_stack
[MAX_INCLUDES
];
298 struct include_stack
*sp
;
299 #define isp (sp - include_stack)
305 /* Include file list */
307 typedef struct include_path
309 struct include_path
*next
;
313 include_path
*paths_head
;
314 include_path
*paths_tail
;
317 static void quit
PARAMS ((void));
318 static void sb_build
PARAMS ((sb
*, int));
319 static void sb_new
PARAMS ((sb
*));
320 static void sb_kill
PARAMS ((sb
*));
321 static void sb_add_sb
PARAMS ((sb
*, sb
*));
322 static void sb_check
PARAMS ((sb
*, int));
323 static void sb_reset
PARAMS ((sb
*));
324 static void sb_add_char
PARAMS ((sb
*, int));
325 static void sb_add_string
PARAMS ((sb
*, const char *));
326 static void sb_add_buffer
PARAMS ((sb
*, const char *, int));
327 static void sb_print
PARAMS ((sb
*));
328 static void sb_print_at
PARAMS ((int, sb
*));
329 static char *sb_name
PARAMS ((sb
*));
330 static int sb_skip_white
PARAMS ((int, sb
*));
331 static int sb_skip_comma
PARAMS ((int, sb
*));
332 static void hash_new_table
PARAMS ((int, hash_table
*));
333 static int hash
PARAMS ((sb
*));
334 static hash_entry
*hash_create
PARAMS ((hash_table
*, sb
*));
335 static void hash_add_to_string_table
PARAMS ((hash_table
*, sb
*, sb
*, int));
336 static void hash_add_to_int_table
PARAMS ((hash_table
*, sb
*, int));
337 static hash_entry
*hash_lookup
PARAMS ((hash_table
*, sb
*));
338 static void checkconst
PARAMS ((int, exp_t
*));
339 static int sb_strtol
PARAMS ((int, sb
*, int, int *));
340 static int level_0
PARAMS ((int, sb
*, exp_t
*));
341 static int level_1
PARAMS ((int, sb
*, exp_t
*));
342 static int level_2
PARAMS ((int, sb
*, exp_t
*));
343 static int level_3
PARAMS ((int, sb
*, exp_t
*));
344 static int level_4
PARAMS ((int, sb
*, exp_t
*));
345 static int level_5
PARAMS ((int, sb
*, exp_t
*));
346 static int exp_parse
PARAMS ((int, sb
*, exp_t
*));
347 static void exp_string
PARAMS ((exp_t
*, sb
*));
348 static int exp_get_abs
PARAMS ((const char *, int, sb
*, int *));
350 static void strip_comments
PARAMS ((sb
*));
352 static void unget
PARAMS ((int));
353 static void include_buf
PARAMS ((sb
*, sb
*, include_type
, int));
354 static void include_print_where_line
PARAMS ((FILE *));
355 static void include_print_line
PARAMS ((FILE *));
356 static int get_line
PARAMS ((sb
*));
357 static int grab_label
PARAMS ((sb
*, sb
*));
358 static void change_base
PARAMS ((int, sb
*, sb
*));
359 static void do_end
PARAMS ((sb
*));
360 static void do_assign
PARAMS ((int, int, sb
*));
361 static void do_radix
PARAMS ((sb
*));
362 static int get_opsize
PARAMS ((int, sb
*, int *));
363 static int eol
PARAMS ((int, sb
*));
364 static void do_data
PARAMS ((int, sb
*, int));
365 static void do_datab
PARAMS ((int, sb
*));
366 static void do_align
PARAMS ((int, sb
*));
367 static void do_res
PARAMS ((int, sb
*, int));
368 static void do_export
PARAMS ((sb
*));
369 static void do_print
PARAMS ((int, sb
*));
370 static void do_heading
PARAMS ((int, sb
*));
371 static void do_page
PARAMS ((void));
372 static void do_form
PARAMS ((int, sb
*));
373 static int get_any_string
PARAMS ((int, sb
*, sb
*, int, int));
374 static int skip_openp
PARAMS ((int, sb
*));
375 static int skip_closep
PARAMS ((int, sb
*));
376 static int dolen
PARAMS ((int, sb
*, sb
*));
377 static int doinstr
PARAMS ((int, sb
*, sb
*));
378 static int dosubstr
PARAMS ((int, sb
*, sb
*));
379 static void process_assigns
PARAMS ((int, sb
*, sb
*));
380 static int get_and_process
PARAMS ((int, sb
*, sb
*));
381 static void process_file
PARAMS ((void));
382 static void free_old_entry
PARAMS ((hash_entry
*));
383 static void do_assigna
PARAMS ((int, sb
*));
384 static void do_assignc
PARAMS ((int, sb
*));
385 static void do_reg
PARAMS ((int, sb
*));
386 static int condass_lookup_name
PARAMS ((sb
*, int, sb
*, int));
387 static int whatcond
PARAMS ((int, sb
*, int *));
388 static int istrue
PARAMS ((int, sb
*));
389 static void do_aif
PARAMS ((int, sb
*));
390 static void do_aelse
PARAMS ((void));
391 static void do_aendi
PARAMS ((void));
392 static int condass_on
PARAMS ((void));
393 static void do_if
PARAMS ((int, sb
*, int));
394 static int get_mri_string
PARAMS ((int, sb
*, sb
*, int));
395 static void do_ifc
PARAMS ((int, sb
*, int));
396 static void buffer_and_nest
PARAMS ((const char *, const char *, sb
*));
397 static void do_aendr
PARAMS ((void));
398 static void do_awhile
PARAMS ((int, sb
*));
399 static void do_aendw
PARAMS ((void));
400 static void do_exitm
PARAMS ((void));
401 static void do_arepeat
PARAMS ((int, sb
*));
402 static void do_endm
PARAMS ((void));
403 static void do_irp
PARAMS ((int, sb
*, int));
404 static int do_formals
PARAMS ((macro_entry
*, int, sb
*));
405 static void do_local
PARAMS ((int, sb
*));
406 static void do_macro
PARAMS ((int, sb
*));
407 static int get_token
PARAMS ((int, sb
*, sb
*));
408 static int get_apost_token
PARAMS ((int, sb
*, sb
*, int));
409 static int sub_actual
410 PARAMS ((int, sb
*, sb
*, hash_table
*, int, sb
*, int));
411 static void macro_expand_body
412 PARAMS ((sb
*, sb
*, sb
*, formal_entry
*, hash_table
*));
413 static void macro_expand
PARAMS ((sb
*, int, sb
*, macro_entry
*));
414 static int macro_op
PARAMS ((int, sb
*));
415 static int getstring
PARAMS ((int, sb
*, sb
*));
416 static void do_sdata
PARAMS ((int, sb
*, int));
417 static void do_sdatab
PARAMS ((int, sb
*));
418 static int new_file
PARAMS ((const char *));
419 static void do_include
PARAMS ((int, sb
*));
420 static void include_pop
PARAMS ((void));
421 static int get
PARAMS ((void));
422 static int linecount
PARAMS ((void));
423 static int include_next_index
PARAMS ((void));
424 static void chartype_init
PARAMS ((void));
425 static int process_pseudo_op
PARAMS ((int, sb
*, sb
*));
426 static void add_keyword
PARAMS ((const char *, int));
427 static void process_init
PARAMS ((void));
428 static void do_define
PARAMS ((const char *));
429 static void show_usage
PARAMS ((FILE *, int));
430 static void show_help
PARAMS ((void));
433 do { include_print_where_line (stderr); fprintf x ; fatals++; quit(); } while(0)
435 do { include_print_where_line (stderr); fprintf x; errors++; } while(0)
437 do { include_print_where_line (stderr); fprintf x; warnings++;} while(0)
441 /* exit the program and return the right ERROR code. */
454 for (i
= 0; i
< max_power_two
; i
++)
456 fprintf (stderr
, "strings size %8d : %d\n", 1<<i
, string_count
[i
]);
463 /* this program is about manipulating strings.
464 they are managed in things called `sb's which is an abbreviation
465 for string buffers. an sb has to be created, things can be glued
466 on to it, and at the end of it's life it should be freed. the
467 contents should never be pointed at whilst it is still growing,
468 since it could be moved at any time
472 sb_grow... (&foo,...);
478 /* initializes an sb. */
485 /* see if we can find one to allocate */
488 if (size
> max_power_two
)
490 FATAL ((stderr
, "string longer than %d bytes requested.\n",
491 1 << max_power_two
));
493 e
= free_list
.size
[size
];
496 /* nothing there, allocate one and stick into the free list */
497 e
= (sb_element
*) xmalloc (sizeof (sb_element
) + (1 << size
));
498 e
->next
= free_list
.size
[size
];
500 free_list
.size
[size
] = e
;
501 string_count
[size
]++;
504 /* remove from free list */
506 free_list
.size
[size
] = e
->next
;
508 /* copy into callers world */
520 sb_build (ptr
, dsize
);
523 /* deallocate the sb at ptr */
530 /* return item to free list */
531 ptr
->item
->next
= free_list
.size
[ptr
->pot
];
532 free_list
.size
[ptr
->pot
] = ptr
->item
;
535 /* add the sb at s to the end of the sb at ptr */
537 static void sb_check ();
545 sb_check (ptr
, s
->len
);
546 memcpy (ptr
->ptr
+ ptr
->len
, s
->ptr
, s
->len
);
550 /* make sure that the sb at ptr has room for another len characters,
551 and grow it if it doesn't. */
558 if (ptr
->len
+ len
>= 1 << ptr
->pot
)
562 while (ptr
->len
+ len
>= 1 << pot
)
564 sb_build (&tmp
, pot
);
565 sb_add_sb (&tmp
, ptr
);
571 /* make the sb at ptr point back to the beginning. */
580 /* add character c to the end of the sb at ptr. */
588 ptr
->ptr
[ptr
->len
++] = c
;
591 /* add null terminated string s to the end of sb at ptr. */
594 sb_add_string (ptr
, s
)
598 int len
= strlen (s
);
600 memcpy (ptr
->ptr
+ ptr
->len
, s
, len
);
604 /* add string at s of length len to sb at ptr */
607 sb_add_buffer (ptr
, s
, len
)
613 memcpy (ptr
->ptr
+ ptr
->len
, s
, len
);
618 /* print the sb at ptr to the output file */
628 for (i
= 0; i
< ptr
->len
; i
++)
632 fprintf (outfile
, ",");
634 fprintf (outfile
, "%d", ptr
->ptr
[i
]);
640 sb_print_at (idx
, ptr
)
645 for (i
= idx
; i
< ptr
->len
; i
++)
646 putc (ptr
->ptr
[i
], outfile
);
648 /* put a null at the end of the sb at in and return the start of the
649 string, so that it can be used as an arg to printf %s. */
656 /* stick a null on the end of the string */
661 /* start at the index idx into the string in sb at ptr and skip
662 whitespace. return the index of the first non whitespace character */
665 sb_skip_white (idx
, ptr
)
669 while (idx
< ptr
->len
&& ISWHITE (ptr
->ptr
[idx
]))
674 /* start at the index idx into the sb at ptr. skips whitespace,
675 a comma and any following whitespace. returnes the index of the
679 sb_skip_comma (idx
, ptr
)
683 while (idx
< ptr
->len
&& ISWHITE (ptr
->ptr
[idx
]))
687 && ptr
->ptr
[idx
] == ',')
690 while (idx
< ptr
->len
&& ISWHITE (ptr
->ptr
[idx
]))
697 /* hash table maintenance. */
699 /* build a new hash table with size buckets, and fill in the info at ptr. */
702 hash_new_table (size
, ptr
)
708 ptr
->table
= (hash_entry
**) xmalloc (size
* (sizeof (hash_entry
*)));
709 /* Fill with null-pointer, not zero-bit-pattern. */
710 for (i
= 0; i
< size
; i
++)
714 /* calculate and return the hash value of the sb at key. */
723 for (i
= 0; i
< key
->len
; i
++)
731 /* lookup key in hash_table tab, if present, then return it, otherwise
732 build a new one and fill it with hash_integer. */
736 hash_create (tab
, key
)
740 int k
= hash (key
) % tab
->size
;
742 hash_entry
**table
= tab
->table
;
750 hash_entry
*n
= (hash_entry
*) xmalloc (sizeof (hash_entry
));
753 sb_add_sb (&n
->key
, key
);
755 n
->type
= hash_integer
;
758 if (strncmp (table
[k
]->key
.ptr
, key
->ptr
, key
->len
) == 0)
766 /* add sb name with key into hash_table tab. if replacing old value
767 and again, then ERROR. */
771 hash_add_to_string_table (tab
, key
, name
, again
)
777 hash_entry
*ptr
= hash_create (tab
, key
);
778 if (ptr
->type
== hash_integer
)
780 sb_new (&ptr
->value
.s
);
782 if (ptr
->value
.s
.len
)
785 ERROR ((stderr
, "redefintion not allowed"));
788 ptr
->type
= hash_string
;
789 sb_reset (&ptr
->value
.s
);
791 sb_add_sb (&ptr
->value
.s
, name
);
794 /* add integer name to hash_table tab with sb key. */
798 hash_add_to_int_table (tab
, key
, name
)
803 hash_entry
*ptr
= hash_create (tab
, key
);
807 /* lookup sb key in hash_table tab. if found return hash_entry result,
812 hash_lookup (tab
, key
)
816 int k
= hash (key
) % tab
->size
;
817 hash_entry
**table
= tab
->table
;
818 hash_entry
*p
= table
[k
];
821 if (p
->key
.len
== key
->len
822 && strncmp (p
->key
.ptr
, key
->ptr
, key
->len
) == 0)
832 are handled in a really simple recursive decent way. each bit of
833 the machine takes an index into an sb and a pointer to an exp_t,
834 modifies the *exp_t and returns the index of the first character
835 past the part of the expression parsed.
837 expression precedence:
848 /* make sure that the exp_t at term is constant, if not the give the op ERROR. */
852 checkconst (op
, term
)
856 if (term
->add_symbol
.len
857 || term
->sub_symbol
.len
)
859 ERROR ((stderr
, "the %c operator cannot take non-absolute arguments.\n", op
));
863 /* turn the number in string at idx into a number of base,
864 fill in ptr and return the index of the first character not in the
869 sb_strtol (idx
, string
, base
, ptr
)
876 idx
= sb_skip_white (idx
, string
);
878 while (idx
< string
->len
)
880 int ch
= string
->ptr
[idx
];
884 else if (ch
>= 'a' && ch
<= 'f')
886 else if (ch
>= 'A' && ch
<= 'F')
894 value
= value
* base
+ dig
;
902 level_0 (idx
, string
, lhs
)
907 lhs
->add_symbol
.len
= 0;
908 lhs
->add_symbol
.name
= 0;
910 lhs
->sub_symbol
.len
= 0;
911 lhs
->sub_symbol
.name
= 0;
913 idx
= sb_skip_white (idx
, string
);
917 if (isdigit (string
->ptr
[idx
]))
919 idx
= sb_strtol (idx
, string
, 10, &lhs
->value
);
921 else if (ISFIRSTCHAR (string
->ptr
[idx
]))
924 lhs
->add_symbol
.name
= string
->ptr
+ idx
;
925 while (idx
< string
->len
&& ISNEXTCHAR (string
->ptr
[idx
]))
930 lhs
->add_symbol
.len
= len
;
932 else if (string
->ptr
[idx
] == '"')
936 ERROR ((stderr
, "string where expression expected.\n"));
937 idx
= getstring (idx
, string
, &acc
);
942 ERROR ((stderr
, "can't find primary in expression.\n"));
945 return sb_skip_white (idx
, string
);
951 level_1 (idx
, string
, lhs
)
956 idx
= sb_skip_white (idx
, string
);
958 switch (string
->ptr
[idx
])
961 idx
= level_1 (idx
+ 1, string
, lhs
);
964 idx
= level_1 (idx
+ 1, string
, lhs
);
965 checkconst ('~', lhs
);
966 lhs
->value
= ~lhs
->value
;
971 idx
= level_1 (idx
+ 1, string
, lhs
);
972 lhs
->value
= -lhs
->value
;
974 lhs
->add_symbol
= lhs
->sub_symbol
;
980 idx
= level_5 (sb_skip_white (idx
, string
), string
, lhs
);
981 if (string
->ptr
[idx
] != ')')
982 ERROR ((stderr
, "misplaced closing parens.\n"));
987 idx
= level_0 (idx
, string
, lhs
);
990 return sb_skip_white (idx
, string
);
994 level_2 (idx
, string
, lhs
)
1001 idx
= level_1 (idx
, string
, lhs
);
1003 while (idx
< string
->len
&& (string
->ptr
[idx
] == '*'
1004 || string
->ptr
[idx
] == '/'))
1006 char op
= string
->ptr
[idx
++];
1007 idx
= level_1 (idx
, string
, &rhs
);
1011 checkconst ('*', lhs
);
1012 checkconst ('*', &rhs
);
1013 lhs
->value
*= rhs
.value
;
1016 checkconst ('/', lhs
);
1017 checkconst ('/', &rhs
);
1019 ERROR ((stderr
, "attempt to divide by zero.\n"));
1021 lhs
->value
/= rhs
.value
;
1025 return sb_skip_white (idx
, string
);
1030 level_3 (idx
, string
, lhs
)
1037 idx
= level_2 (idx
, string
, lhs
);
1039 while (idx
< string
->len
1040 && (string
->ptr
[idx
] == '+'
1041 || string
->ptr
[idx
] == '-'))
1043 char op
= string
->ptr
[idx
++];
1044 idx
= level_2 (idx
, string
, &rhs
);
1048 lhs
->value
+= rhs
.value
;
1049 if (lhs
->add_symbol
.name
&& rhs
.add_symbol
.name
)
1051 ERROR ((stderr
, "can't add two relocatable expressions\n"));
1053 /* change nn+symbol to symbol + nn */
1054 if (rhs
.add_symbol
.name
)
1056 lhs
->add_symbol
= rhs
.add_symbol
;
1060 lhs
->value
-= rhs
.value
;
1061 lhs
->sub_symbol
= rhs
.add_symbol
;
1065 return sb_skip_white (idx
, string
);
1069 level_4 (idx
, string
, lhs
)
1076 idx
= level_3 (idx
, string
, lhs
);
1078 while (idx
< string
->len
&&
1079 string
->ptr
[idx
] == '&')
1081 char op
= string
->ptr
[idx
++];
1082 idx
= level_3 (idx
, string
, &rhs
);
1086 checkconst ('&', lhs
);
1087 checkconst ('&', &rhs
);
1088 lhs
->value
&= rhs
.value
;
1092 return sb_skip_white (idx
, string
);
1096 level_5 (idx
, string
, lhs
)
1103 idx
= level_4 (idx
, string
, lhs
);
1105 while (idx
< string
->len
1106 && (string
->ptr
[idx
] == '|' || string
->ptr
[idx
] == '~'))
1108 char op
= string
->ptr
[idx
++];
1109 idx
= level_4 (idx
, string
, &rhs
);
1113 checkconst ('|', lhs
);
1114 checkconst ('|', &rhs
);
1115 lhs
->value
|= rhs
.value
;
1118 checkconst ('~', lhs
);
1119 checkconst ('~', &rhs
);
1120 lhs
->value
^= rhs
.value
;
1124 return sb_skip_white (idx
, string
);
1128 /* parse the expression at offset idx into string, fill up res with
1129 the result. return the index of the first char past the expression.
1133 exp_parse (idx
, string
, res
)
1138 return level_5 (sb_skip_white (idx
, string
), string
, res
);
1142 /* turn the expression at exp into text and glue it onto the end of
1146 exp_string (exp
, string
)
1154 if (exp
->add_symbol
.len
)
1156 sb_add_buffer (string
, exp
->add_symbol
.name
, exp
->add_symbol
.len
);
1164 sb_add_char (string
, '+');
1165 sprintf (buf
, "%d", exp
->value
);
1166 sb_add_string (string
, buf
);
1170 if (exp
->sub_symbol
.len
)
1172 sb_add_char (string
, '-');
1173 sb_add_buffer (string
, exp
->add_symbol
.name
, exp
->add_symbol
.len
);
1179 sb_add_char (string
, '0');
1183 /* parse the expression at offset idx into sb in, return the value in val.
1184 if the expression is not constant, give ERROR emsg. returns the index
1185 of the first character past the end of the expression. */
1188 exp_get_abs (emsg
, idx
, in
, val
)
1195 idx
= exp_parse (idx
, in
, &res
);
1196 if (res
.add_symbol
.len
|| res
.sub_symbol
.len
)
1197 ERROR ((stderr
, emsg
));
1203 sb label
; /* current label parsed from line */
1204 hash_table assign_hash_table
; /* hash table for all assigned variables */
1205 hash_table keyword_hash_table
; /* hash table for keyword */
1206 hash_table vars
; /* hash table for eq variables */
1208 #define in_comment ';'
1212 strip_comments (out
)
1217 for (i
= 0; i
< out
->len
; i
++)
1219 if (ISCOMMENTCHAR(s
[i
]))
1228 /* push back character ch so that it can be read again. */
1238 if (sp
->pushback_index
)
1239 sp
->pushback_index
--;
1241 sb_add_char (&sp
->pushback
, ch
);
1244 /* push the sb ptr onto the include stack, with the given name, type and index. */
1248 include_buf (name
, ptr
, type
, index
)
1255 if (sp
- include_stack
>= MAX_INCLUDES
)
1256 FATAL ((stderr
, "unreasonable nesting.\n"));
1258 sb_add_sb (&sp
->name
, name
);
1261 sp
->pushback_index
= 0;
1264 sb_new (&sp
->pushback
);
1265 sb_add_sb (&sp
->pushback
, ptr
);
1269 /* used in ERROR messages, print info on where the include stack is onto file. */
1272 include_print_where_line (file
)
1275 struct include_stack
*p
= include_stack
+ 1;
1279 fprintf (file
, "%s:%d ", sb_name (&p
->name
), p
->linecount
- ((p
== sp
) ? 1 : 0));
1284 /* used in listings, print the line number onto file. */
1286 include_print_line (file
)
1290 struct include_stack
*p
= include_stack
+ 1;
1292 n
= fprintf (file
, "%4d", p
->linecount
);
1296 n
+= fprintf (file
, ".%d", p
->linecount
);
1301 fprintf (file
, " ");
1307 /* read a line from the top of the include stack into sb in. */
1318 putc (comment_char
, outfile
);
1319 if (print_line_number
)
1320 include_print_line (outfile
);
1334 WARNING ((stderr
, "End of file not at start of line.\n"));
1336 putc ('\n', outfile
);
1355 /* continued line */
1358 putc (comment_char
, outfile
);
1359 putc ('+', outfile
);
1372 sb_add_char (in
, ch
);
1380 /* find a label from sb in and put it in out. */
1383 grab_label (in
, out
)
1389 if (ISFIRSTCHAR (in
->ptr
[i
]))
1391 sb_add_char (out
, in
->ptr
[i
]);
1393 while ((ISNEXTCHAR (in
->ptr
[i
])
1394 || in
->ptr
[i
] == '\\'
1395 || in
->ptr
[i
] == '&')
1398 sb_add_char (out
, in
->ptr
[i
]);
1405 /* find all strange base stuff and turn into decimal. also
1406 find all the other numbers and convert them from the default radix */
1409 change_base (idx
, in
, out
)
1416 while (idx
< in
->len
)
1418 if (idx
< in
->len
- 1 && in
->ptr
[idx
+ 1] == '\'' && ! mri
)
1422 switch (in
->ptr
[idx
])
1441 ERROR ((stderr
, "Illegal base character %c.\n", in
->ptr
[idx
]));
1446 idx
= sb_strtol (idx
+ 2, in
, base
, &value
);
1447 sprintf (buffer
, "%d", value
);
1448 sb_add_string (out
, buffer
);
1450 else if (ISFIRSTCHAR (in
->ptr
[idx
]))
1452 /* copy entire names through quickly */
1453 sb_add_char (out
, in
->ptr
[idx
]);
1455 while (idx
< in
->len
&& ISNEXTCHAR (in
->ptr
[idx
]))
1457 sb_add_char (out
, in
->ptr
[idx
]);
1461 else if (isdigit (in
->ptr
[idx
]))
1464 /* all numbers must start with a digit, let's chew it and
1466 idx
= sb_strtol (idx
, in
, radix
, &value
);
1467 sprintf (buffer
, "%d", value
);
1468 sb_add_string (out
, buffer
);
1470 /* skip all undigsested letters */
1471 while (idx
< in
->len
&& ISNEXTCHAR (in
->ptr
[idx
]))
1473 sb_add_char (out
, in
->ptr
[idx
]);
1477 else if (in
->ptr
[idx
] == '"' || in
->ptr
[idx
] == '\'')
1479 char tchar
= in
->ptr
[idx
];
1480 /* copy entire names through quickly */
1481 sb_add_char (out
, in
->ptr
[idx
]);
1483 while (idx
< in
->len
&& in
->ptr
[idx
] != tchar
)
1485 sb_add_char (out
, in
->ptr
[idx
]);
1491 /* nothing special, just pass it through */
1492 sb_add_char (out
, in
->ptr
[idx
]);
1506 fprintf (outfile
, "%s\n", sb_name (in
));
1512 do_assign (again
, idx
, in
)
1517 /* stick label in symbol table with following value */
1522 idx
= exp_parse (idx
, in
, &e
);
1523 exp_string (&e
, &acc
);
1524 hash_add_to_string_table (&assign_hash_table
, &label
, &acc
, again
);
1529 /* .radix [b|q|d|h] */
1536 int idx
= sb_skip_white (0, ptr
);
1537 switch (ptr
->ptr
[idx
])
1556 ERROR ((stderr
, "radix is %c must be one of b, q, d or h", radix
));
1561 /* Parse off a .b, .w or .l */
1564 get_opsize (idx
, in
, size
)
1570 if (in
->ptr
[idx
] == '.')
1574 switch (in
->ptr
[idx
])
1592 ERROR ((stderr
, "size must be one of b, w or l, is %c.\n", in
->ptr
[idx
]));
1605 idx
= sb_skip_white (idx
, line
);
1607 && ISCOMMENTCHAR(line
->ptr
[idx
]))
1609 if (idx
>= line
->len
)
1614 /* .data [.b|.w|.l] <data>*
1615 or d[bwl] <data>* */
1618 do_data (idx
, in
, size
)
1624 char *opname
= ".yikes!";
1630 idx
= get_opsize (idx
, in
, &opsize
);
1649 fprintf (outfile
, "%s\t", opname
);
1651 idx
= sb_skip_white (idx
, in
);
1655 && in
->ptr
[idx
] == '"')
1658 idx
= getstring (idx
, in
, &acc
);
1659 for (i
= 0; i
< acc
.len
; i
++)
1662 fprintf(outfile
,",");
1663 fprintf (outfile
, "%d", acc
.ptr
[i
]);
1668 while (!eol (idx
, in
))
1671 idx
= exp_parse (idx
, in
, &e
);
1672 exp_string (&e
, &acc
);
1673 sb_add_char (&acc
, 0);
1674 fprintf (outfile
, acc
.ptr
);
1675 if (idx
< in
->len
&& in
->ptr
[idx
] == ',')
1677 fprintf (outfile
, ",");
1683 sb_print_at (idx
, in
);
1684 fprintf (outfile
, "\n");
1687 /* .datab [.b|.w|.l] <repeat>,<fill> */
1698 idx
= get_opsize (idx
, in
, &opsize
);
1700 idx
= exp_get_abs ("datab repeat must be constant.\n", idx
, in
, &repeat
);
1701 idx
= sb_skip_comma (idx
, in
);
1702 idx
= exp_get_abs ("datab data must be absolute.\n", idx
, in
, &fill
);
1704 fprintf (outfile
, ".fill\t%d,%d,%d\n", repeat
, opsize
, fill
);
1715 idx
= exp_get_abs ("align needs absolute expression.\n", idx
, in
, &al
);
1720 WARNING ((stderr
, "alignment must be one of 1, 2 or 4.\n"));
1722 fprintf (outfile
, ".align %d\n", al
);
1725 /* .res[.b|.w|.l] <size> */
1728 do_res (idx
, in
, type
)
1736 idx
= get_opsize (idx
, in
, &size
);
1737 while (!eol(idx
, in
))
1739 idx
= sb_skip_white (idx
, in
);
1740 if (in
->ptr
[idx
] == ',')
1742 idx
= exp_get_abs ("res needs absolute expression for fill count.\n", idx
, in
, &count
);
1744 if (type
== 'c' || type
== 'z')
1747 fprintf (outfile
, ".space %d\n", count
* size
);
1758 fprintf (outfile
, ".global %s\n", sb_name (in
));
1761 /* .print [list] [nolist] */
1768 idx
= sb_skip_white (idx
, in
);
1769 while (idx
< in
->len
)
1771 if (strncasecmp (in
->ptr
+ idx
, "LIST", 4) == 0)
1773 fprintf (outfile
, ".list\n");
1776 else if (strncasecmp (in
->ptr
+ idx
, "NOLIST", 6) == 0)
1778 fprintf (outfile
, ".nolist\n");
1787 do_heading (idx
, in
)
1793 idx
= getstring (idx
, in
, &head
);
1794 fprintf (outfile
, ".title \"%s\"\n", sb_name (&head
));
1803 fprintf (outfile
, ".eject\n");
1806 /* .form [lin=<value>] [col=<value>] */
1814 idx
= sb_skip_white (idx
, in
);
1816 while (idx
< in
->len
)
1819 if (strncasecmp (in
->ptr
+ idx
, "LIN=", 4) == 0)
1822 idx
= exp_get_abs ("form LIN= needs absolute expresssion.\n", idx
, in
, &lines
);
1825 if (strncasecmp (in
->ptr
+ idx
, "COL=", 4) == 0)
1828 idx
= exp_get_abs ("form COL= needs absolute expresssion.\n", idx
, in
, &columns
);
1833 fprintf (outfile
, ".psize %d,%d\n", lines
, columns
);
1838 /* Fetch string from the input stream,
1840 'Bxyx<whitespace> -> return 'Bxyza
1841 %<char> -> return string of decimal value of x
1842 "<string>" -> return string
1843 xyx<whitespace> -> return xyz
1846 get_any_string (idx
, in
, out
, expand
, pretend_quoted
)
1854 idx
= sb_skip_white (idx
, in
);
1858 if (in
->len
> 2 && in
->ptr
[idx
+1] == '\'' && ISBASE (in
->ptr
[idx
]))
1860 while (!ISSEP (in
->ptr
[idx
]))
1861 sb_add_char (out
, in
->ptr
[idx
++]);
1863 else if (in
->ptr
[idx
] == '%'
1869 /* Turns the next expression into a string */
1870 idx
= exp_get_abs ("% operator needs absolute expression",
1874 sprintf(buf
, "%d", val
);
1875 sb_add_string (out
, buf
);
1877 else if (in
->ptr
[idx
] == '"'
1878 || in
->ptr
[idx
] == '<'
1879 || (alternate
&& in
->ptr
[idx
] == '\''))
1881 if (alternate
&& expand
)
1883 /* Keep the quotes */
1884 sb_add_char (out
, '\"');
1886 idx
= getstring (idx
, in
, out
);
1887 sb_add_char (out
, '\"');
1891 idx
= getstring (idx
, in
, out
);
1896 while (idx
< in
->len
1897 && (in
->ptr
[idx
] == '"'
1898 || in
->ptr
[idx
] == '\''
1900 || !ISSEP (in
->ptr
[idx
])))
1902 if (in
->ptr
[idx
] == '"'
1903 || in
->ptr
[idx
] == '\'')
1905 char tchar
= in
->ptr
[idx
];
1906 sb_add_char (out
, in
->ptr
[idx
++]);
1907 while (idx
< in
->len
1908 && in
->ptr
[idx
] != tchar
)
1909 sb_add_char (out
, in
->ptr
[idx
++]);
1913 sb_add_char (out
, in
->ptr
[idx
++]);
1922 /* skip along sb in starting at idx, suck off whitespace a ( and more
1923 whitespace. return the idx of the next char */
1926 skip_openp (idx
, in
)
1930 idx
= sb_skip_white (idx
, in
);
1931 if (in
->ptr
[idx
] != '(')
1932 ERROR ((stderr
, "misplaced ( .\n"));
1933 idx
= sb_skip_white (idx
+ 1, in
);
1937 /* skip along sb in starting at idx, suck off whitespace a ) and more
1938 whitespace. return the idx of the next char */
1941 skip_closep (idx
, in
)
1945 idx
= sb_skip_white (idx
, in
);
1946 if (in
->ptr
[idx
] != ')')
1947 ERROR ((stderr
, "misplaced ).\n"));
1948 idx
= sb_skip_white (idx
+ 1, in
);
1955 dolen (idx
, in
, out
)
1964 sb_new (&stringout
);
1965 idx
= skip_openp (idx
, in
);
1966 idx
= get_and_process (idx
, in
, &stringout
);
1967 idx
= skip_closep (idx
, in
);
1968 sprintf (buffer
, "%d", stringout
.len
);
1969 sb_add_string (out
, buffer
);
1971 sb_kill (&stringout
);
1980 doinstr (idx
, in
, out
)
1994 idx
= skip_openp (idx
, in
);
1995 idx
= get_and_process (idx
, in
, &string
);
1996 idx
= sb_skip_comma (idx
, in
);
1997 idx
= get_and_process (idx
, in
, &search
);
1998 idx
= sb_skip_comma (idx
, in
);
1999 if (isdigit (in
->ptr
[idx
]))
2001 idx
= exp_get_abs (".instr needs absolute expresson.\n", idx
, in
, &start
);
2007 idx
= skip_closep (idx
, in
);
2009 for (i
= start
; i
< string
.len
; i
++)
2011 if (strncmp (string
.ptr
+ i
, search
.ptr
, search
.len
) == 0)
2017 sprintf (buffer
, "%d", res
);
2018 sb_add_string (out
, buffer
);
2026 dosubstr (idx
, in
, out
)
2036 idx
= skip_openp (idx
, in
);
2037 idx
= get_and_process (idx
, in
, &string
);
2038 idx
= sb_skip_comma (idx
, in
);
2039 idx
= exp_get_abs ("need absolute position.\n", idx
, in
, &pos
);
2040 idx
= sb_skip_comma (idx
, in
);
2041 idx
= exp_get_abs ("need absolute length.\n", idx
, in
, &len
);
2042 idx
= skip_closep (idx
, in
);
2045 if (len
< 0 || pos
< 0 ||
2047 || pos
+ len
> string
.len
)
2049 sb_add_string (out
, " ");
2053 sb_add_char (out
, '"');
2056 sb_add_char (out
, string
.ptr
[pos
++]);
2059 sb_add_char (out
, '"');
2065 /* scan line, change tokens in the hash table to their replacements */
2067 process_assigns (idx
, in
, buf
)
2072 while (idx
< in
->len
)
2075 if (in
->ptr
[idx
] == '\\'
2076 && in
->ptr
[idx
+ 1] == '&')
2078 idx
= condass_lookup_name (in
, idx
+ 2, buf
, 1);
2080 else if (in
->ptr
[idx
] == '\\'
2081 && in
->ptr
[idx
+ 1] == '$')
2083 idx
= condass_lookup_name (in
, idx
+ 2, buf
, 0);
2085 else if (idx
+ 3 < in
->len
2086 && in
->ptr
[idx
] == '.'
2087 && toupper ((unsigned char) in
->ptr
[idx
+ 1]) == 'L'
2088 && toupper ((unsigned char) in
->ptr
[idx
+ 2]) == 'E'
2089 && toupper ((unsigned char) in
->ptr
[idx
+ 3]) == 'N')
2090 idx
= dolen (idx
+ 4, in
, buf
);
2091 else if (idx
+ 6 < in
->len
2092 && in
->ptr
[idx
] == '.'
2093 && toupper ((unsigned char) in
->ptr
[idx
+ 1]) == 'I'
2094 && toupper ((unsigned char) in
->ptr
[idx
+ 2]) == 'N'
2095 && toupper ((unsigned char) in
->ptr
[idx
+ 3]) == 'S'
2096 && toupper ((unsigned char) in
->ptr
[idx
+ 4]) == 'T'
2097 && toupper ((unsigned char) in
->ptr
[idx
+ 5]) == 'R')
2098 idx
= doinstr (idx
+ 6, in
, buf
);
2099 else if (idx
+ 7 < in
->len
2100 && in
->ptr
[idx
] == '.'
2101 && toupper ((unsigned char) in
->ptr
[idx
+ 1]) == 'S'
2102 && toupper ((unsigned char) in
->ptr
[idx
+ 2]) == 'U'
2103 && toupper ((unsigned char) in
->ptr
[idx
+ 3]) == 'B'
2104 && toupper ((unsigned char) in
->ptr
[idx
+ 4]) == 'S'
2105 && toupper ((unsigned char) in
->ptr
[idx
+ 5]) == 'T'
2106 && toupper ((unsigned char) in
->ptr
[idx
+ 6]) == 'R')
2107 idx
= dosubstr (idx
+ 7, in
, buf
);
2108 else if (ISFIRSTCHAR (in
->ptr
[idx
]))
2110 /* may be a simple name subsitution, see if we have a word */
2113 while (cur
< in
->len
2114 && (ISNEXTCHAR (in
->ptr
[cur
])))
2118 sb_add_buffer (&acc
, in
->ptr
+ idx
, cur
- idx
);
2119 ptr
= hash_lookup (&assign_hash_table
, &acc
);
2122 /* Found a definition for it */
2123 sb_add_sb (buf
, &ptr
->value
.s
);
2127 /* No definition, just copy the word */
2128 sb_add_sb (buf
, &acc
);
2135 sb_add_char (buf
, in
->ptr
[idx
++]);
2141 get_and_process (idx
, in
, out
)
2148 idx
= get_any_string (idx
, in
, &t
, 1, 0);
2149 process_assigns (0, &t
, out
);
2170 more
= get_line (&line
);
2173 /* Find any label and pseudo op that we're intested in */
2178 fprintf (outfile
, "\n");
2182 l
= grab_label (&line
, &label_in
);
2186 /* Munge any label */
2189 process_assigns (0, &label_in
, &label
);
2192 if (line
.ptr
[l
] == ':')
2194 while (ISWHITE (line
.ptr
[l
]) && l
< line
.len
)
2199 if (process_pseudo_op (l
, &line
, &acc
))
2205 else if (condass_on ())
2207 if (macro_op (l
, &line
))
2217 fprintf (outfile
, "%s:\t", sb_name (&label
));
2220 fprintf (outfile
, "\t");
2222 process_assigns (l
, &line
, &t1
);
2224 change_base (0, &t1
, &t2
);
2225 fprintf (outfile
, "%s\n", sb_name (&t2
));
2231 /* Only a label on this line */
2232 if (label
.len
&& condass_on())
2234 fprintf (outfile
, "%s:\n", sb_name (&label
));
2242 more
= get_line (&line
);
2245 if (!had_end
&& !mri
)
2246 WARNING ((stderr
, "END missing from end of file.\n"));
2254 free_old_entry (ptr
)
2259 if (ptr
->type
== hash_string
)
2260 sb_kill(&ptr
->value
.s
);
2264 /* name: .ASSIGNA <value> */
2267 do_assigna (idx
, in
)
2275 process_assigns (idx
, in
, &tmp
);
2276 idx
= exp_get_abs (".ASSIGNA needs constant expression argument.\n", 0, &tmp
, &val
);
2280 ERROR ((stderr
, ".ASSIGNA without label.\n"));
2284 hash_entry
*ptr
= hash_create (&vars
, &label
);
2285 free_old_entry (ptr
);
2286 ptr
->type
= hash_integer
;
2292 /* name: .ASSIGNC <string> */
2295 do_assignc (idx
, in
)
2301 idx
= getstring (idx
, in
, &acc
);
2305 ERROR ((stderr
, ".ASSIGNS without label.\n"));
2309 hash_entry
*ptr
= hash_create (&vars
, &label
);
2310 free_old_entry (ptr
);
2311 ptr
->type
= hash_string
;
2312 sb_new (&ptr
->value
.s
);
2313 sb_add_sb (&ptr
->value
.s
, &acc
);
2319 /* name: .REG (reg) */
2326 /* remove reg stuff from inside parens */
2328 idx
= skip_openp (idx
, in
);
2330 while (idx
< in
->len
&& in
->ptr
[idx
] != ')')
2332 sb_add_char (&what
, in
->ptr
[idx
]);
2335 hash_add_to_string_table (&assign_hash_table
, &label
, &what
, 1);
2341 condass_lookup_name (inbuf
, idx
, out
, warn
)
2349 sb_new (&condass_acc
);
2351 while (idx
< inbuf
->len
2352 && ISNEXTCHAR (inbuf
->ptr
[idx
]))
2354 sb_add_char (&condass_acc
, inbuf
->ptr
[idx
++]);
2357 if (inbuf
->ptr
[idx
] == '\'')
2359 ptr
= hash_lookup (&vars
, &condass_acc
);
2366 WARNING ((stderr
, "Can't find preprocessor variable %s.\n", sb_name (&condass_acc
)));
2370 sb_add_string (out
, "0");
2375 if (ptr
->type
== hash_integer
)
2378 sprintf (buffer
, "%d", ptr
->value
.i
);
2379 sb_add_string (out
, buffer
);
2383 sb_add_sb (out
, &ptr
->value
.s
);
2386 sb_kill (&condass_acc
);
2399 whatcond (idx
, in
, val
)
2406 idx
= sb_skip_white (idx
, in
);
2408 if (idx
+ 1 < in
->len
)
2414 a
= toupper ((unsigned char) p
[0]);
2415 b
= toupper ((unsigned char) p
[1]);
2416 if (a
== 'E' && b
== 'Q')
2418 else if (a
== 'N' && b
== 'E')
2420 else if (a
== 'L' && b
== 'T')
2422 else if (a
== 'L' && b
== 'E')
2424 else if (a
== 'G' && b
== 'T')
2426 else if (a
== 'G' && b
== 'E')
2431 ERROR ((stderr
, "Comparison operator must be one of EQ, NE, LT, LE, GT or GE.\n"));
2434 idx
= sb_skip_white (idx
+ 2, in
);
2451 idx
= sb_skip_white (idx
, in
);
2453 if (in
->ptr
[idx
] == '"')
2457 /* This is a string comparision */
2458 idx
= getstring (idx
, in
, &acc_a
);
2459 idx
= whatcond (idx
, in
, &cond
);
2460 idx
= getstring (idx
, in
, &acc_b
);
2461 same
= acc_a
.len
== acc_b
.len
&& (strncmp (acc_a
.ptr
, acc_b
.ptr
, acc_a
.len
) == 0);
2463 if (cond
!= EQ
&& cond
!= NE
)
2465 ERROR ((stderr
, "Comparison operator for strings must be EQ or NE\n"));
2469 res
= (cond
!= EQ
) ^ same
;
2472 /* This is a numeric expression */
2477 idx
= exp_get_abs ("Conditional operator must have absolute operands.\n", idx
, in
, &vala
);
2478 idx
= whatcond (idx
, in
, &cond
);
2479 idx
= sb_skip_white (idx
, in
);
2480 if (in
->ptr
[idx
] == '"')
2482 WARNING ((stderr
, "String compared against expression.\n"));
2487 idx
= exp_get_abs ("Conditional operator must have absolute operands.\n", idx
, in
, &valb
);
2530 if (ifi
>= IFNESTING
)
2532 FATAL ((stderr
, "AIF nesting unreasonable.\n"));
2535 ifstack
[ifi
].on
= ifstack
[ifi
-1].on
? istrue (idx
, in
) : 0;
2536 ifstack
[ifi
].hadelse
= 0;
2544 ifstack
[ifi
].on
= ifstack
[ifi
-1].on
? !ifstack
[ifi
].on
: 0;
2545 if (ifstack
[ifi
].hadelse
)
2547 ERROR ((stderr
, "Multiple AELSEs in AIF.\n"));
2549 ifstack
[ifi
].hadelse
= 1;
2563 ERROR ((stderr
, "AENDI without AIF.\n"));
2570 return ifstack
[ifi
].on
;
2573 /* MRI IFEQ, IFNE, IFLT, IFLE, IFGE, IFGT. */
2576 do_if (idx
, in
, cond
)
2584 if (ifi
>= IFNESTING
)
2586 FATAL ((stderr
, "IF nesting unreasonable.\n"));
2589 idx
= exp_get_abs ("Conditional operator must have absolute operands.\n",
2594 case EQ
: res
= val
== 0; break;
2595 case NE
: res
= val
!= 0; break;
2596 case LT
: res
= val
< 0; break;
2597 case LE
: res
= val
<= 0; break;
2598 case GE
: res
= val
>= 0; break;
2599 case GT
: res
= val
> 0; break;
2603 ifstack
[ifi
].on
= ifstack
[ifi
-1].on
? res
: 0;
2604 ifstack
[ifi
].hadelse
= 0;
2607 /* Get a string for the MRI IFC or IFNC pseudo-ops. */
2610 get_mri_string (idx
, in
, val
, terminator
)
2616 idx
= sb_skip_white (idx
, in
);
2619 && in
->ptr
[idx
] == '\'')
2621 sb_add_char (val
, '\'');
2622 for (++idx
; idx
< in
->len
; ++idx
)
2624 sb_add_char (val
, in
->ptr
[idx
]);
2625 if (in
->ptr
[idx
] == '\'')
2629 || in
->ptr
[idx
] != '\'')
2633 idx
= sb_skip_white (idx
, in
);
2639 while (idx
< in
->len
2640 && in
->ptr
[idx
] != terminator
)
2642 sb_add_char (val
, in
->ptr
[idx
]);
2646 while (i
>= 0 && ISWHITE (val
->ptr
[i
]))
2654 /* MRI IFC, IFNC. */
2657 do_ifc (idx
, in
, ifnc
)
2666 if (ifi
>= IFNESTING
)
2668 FATAL ((stderr
, "IF nesting unreasonable.\n"));
2674 idx
= get_mri_string (idx
, in
, &first
, ',');
2676 if (idx
>= in
->len
|| in
->ptr
[idx
] != ',')
2678 ERROR ((stderr
, "Bad format for IF or IFNC.\n"));
2682 idx
= get_mri_string (idx
+ 1, in
, &second
, ';');
2684 res
= (first
.len
== second
.len
2685 && strncmp (first
.ptr
, second
.ptr
, first
.len
) == 0);
2689 ifstack
[ifi
].on
= ifstack
[ifi
-1].on
? res
: 0;
2690 ifstack
[ifi
].hadelse
= 0;
2693 /* Read input lines till we get to a TO string.
2694 Increase nesting depth if we geta FROM string.
2695 Put the results into sb at PTR. */
2698 buffer_and_nest (from
, to
, ptr
)
2703 int from_len
= strlen (from
);
2704 int to_len
= strlen (to
);
2706 int line_start
= ptr
->len
;
2707 int line
= linecount ();
2709 int more
= get_line (ptr
);
2713 /* Try and find the first pseudo op on the line */
2716 if (!alternate
&& !mri
)
2718 /* With normal syntax we can suck what we want till we get
2719 to the dot. With the alternate, labels have to start in
2720 the first column, since we cant tell what's a label and
2723 /* Skip leading whitespace */
2725 && ISWHITE (ptr
->ptr
[i
]))
2728 /* Skip over a label */
2730 && ISNEXTCHAR (ptr
->ptr
[i
]))
2735 && ptr
->ptr
[i
] == ':')
2739 /* Skip trailing whitespace */
2741 && ISWHITE (ptr
->ptr
[i
]))
2744 if (i
< ptr
->len
&& (ptr
->ptr
[i
] == '.'
2748 if (ptr
->ptr
[i
] == '.')
2750 if (strncasecmp (ptr
->ptr
+ i
, from
, from_len
) == 0)
2752 if (strncasecmp (ptr
->ptr
+ i
, to
, to_len
) == 0)
2757 /* Reset the string to not include the ending rune */
2758 ptr
->len
= line_start
;
2764 /* Add a CR to the end and keep running */
2765 sb_add_char (ptr
, '\n');
2766 line_start
= ptr
->len
;
2767 more
= get_line (ptr
);
2772 FATAL ((stderr
, "End of file whilst inside %s, started on line %d.\n", from
, line
));
2781 ERROR ((stderr
, "AENDR without a AREPEAT.\n"));
2783 ERROR ((stderr
, "ENDR without a REPT.\n"));
2802 process_assigns (idx
, in
, &exp
);
2803 doit
= istrue (0, &exp
);
2805 buffer_and_nest ("AWHILE", "AENDW", &sub
);
2820 int index
= include_next_index ();
2824 sb_add_sb (©
, &sub
);
2825 sb_add_sb (©
, in
);
2826 sb_add_string (©
, "\n");
2827 sb_add_sb (©
, &sub
);
2828 sb_add_string (©
, "\t.AENDW\n");
2829 /* Push another WHILE */
2830 include_buf (&exp
, ©
, include_while
, index
);
2843 ERROR ((stderr
, "AENDW without a AENDW.\n"));
2849 Pop things off the include stack until the type and index changes */
2854 include_type type
= sp
->type
;
2855 if (type
== include_repeat
2856 || type
== include_while
2857 || type
== include_macro
)
2859 int index
= sp
->index
;
2861 while (sp
->index
== index
2862 && sp
->type
== type
)
2872 do_arepeat (idx
, in
)
2876 sb exp
; /* buffer with expression in it */
2877 sb copy
; /* expanded repeat block */
2878 sb sub
; /* contents of AREPEAT */
2884 process_assigns (idx
, in
, &exp
);
2885 idx
= exp_get_abs ("AREPEAT must have absolute operand.\n", 0, &exp
, &rc
);
2887 buffer_and_nest ("AREPEAT", "AENDR", &sub
);
2889 buffer_and_nest ("REPT", "ENDR", &sub
);
2892 /* Push back the text following the repeat, and another repeat block
2903 int index
= include_next_index ();
2904 sb_add_sb (©
, &sub
);
2908 sprintf (buffer
, "\t.AREPEAT %d\n", rc
- 1);
2910 sprintf (buffer
, "\tREPT %d\n", rc
- 1);
2911 sb_add_string (©
, buffer
);
2912 sb_add_sb (©
, &sub
);
2914 sb_add_string (©
, " .AENDR\n");
2916 sb_add_string (©
, " ENDR\n");
2919 include_buf (&exp
, ©
, include_repeat
, index
);
2931 ERROR ((stderr
, ".ENDM without a matching .MACRO.\n"));
2934 /* MRI IRP pseudo-op. */
2937 do_irp (idx
, in
, irpc
)
2955 idx
= sb_skip_white (idx
, in
);
2958 buffer_and_nest (mn
, "ENDR", &sub
);
2964 idx
= get_token (idx
, in
, &f
.name
);
2965 if (f
.name
.len
== 0)
2967 ERROR ((stderr
, "Missing model parameter in %s", mn
));
2971 hash_new_table (1, &h
);
2972 p
= hash_create (&h
, &f
.name
);
2973 p
->type
= hash_formal
;
2980 sb_add_string (&name
, mn
);
2984 idx
= sb_skip_comma (idx
, in
);
2987 /* Expand once with a null string. */
2988 macro_expand_body (&name
, &sub
, &out
, &f
, &h
);
2989 fprintf (outfile
, "%s", sb_name (&out
));
2993 while (!eol (idx
, in
))
2996 idx
= get_any_string (idx
, in
, &f
.actual
, 1, 0);
2999 sb_reset (&f
.actual
);
3000 sb_add_char (&f
.actual
, in
->ptr
[idx
]);
3004 macro_expand_body (&name
, &sub
, &out
, &f
, &h
);
3005 fprintf (outfile
, "%s", sb_name (&out
));
3007 idx
= sb_skip_comma (idx
, in
);
3009 idx
= sb_skip_white (idx
, in
);
3018 /* MACRO PROCESSING */
3021 hash_table macro_table
;
3031 do_formals (macro
, idx
, in
)
3036 formal_entry
**p
= ¯o
->formals
;
3037 macro
->formal_count
= 0;
3038 hash_new_table (5, ¯o
->formal_hash
);
3039 while (idx
< in
->len
)
3041 formal_entry
*formal
;
3043 formal
= (formal_entry
*) xmalloc (sizeof (formal_entry
));
3045 sb_new (&formal
->name
);
3046 sb_new (&formal
->def
);
3047 sb_new (&formal
->actual
);
3049 idx
= sb_skip_white (idx
, in
);
3050 idx
= get_token (idx
, in
, &formal
->name
);
3051 if (formal
->name
.len
== 0)
3053 idx
= sb_skip_white (idx
, in
);
3054 if (formal
->name
.len
)
3056 /* This is a formal */
3057 if (idx
< in
->len
&& in
->ptr
[idx
] == '=')
3060 idx
= get_any_string (idx
+ 1, in
, &formal
->def
, 1, 0);
3065 /* Add to macro's hash table */
3067 hash_entry
*p
= hash_create (¯o
->formal_hash
, &formal
->name
);
3068 p
->type
= hash_formal
;
3069 p
->value
.f
= formal
;
3072 formal
->index
= macro
->formal_count
;
3073 idx
= sb_skip_comma (idx
, in
);
3074 macro
->formal_count
++;
3082 formal_entry
*formal
;
3084 /* Add a special NARG formal, which macro_expand will set to the
3085 number of arguments. */
3086 formal
= (formal_entry
*) xmalloc (sizeof (formal_entry
));
3088 sb_new (&formal
->name
);
3089 sb_new (&formal
->def
);
3090 sb_new (&formal
->actual
);
3092 sb_add_string (&formal
->name
, "NARG");
3095 /* Add to macro's hash table */
3097 hash_entry
*p
= hash_create (¯o
->formal_hash
, &formal
->name
);
3098 p
->type
= hash_formal
;
3099 p
->value
.f
= formal
;
3104 formal
->next
= NULL
;
3110 /* Parse off LOCAL n1, n2,... Invent a label name for it */
3113 do_local (idx
, line
)
3123 idx
= sb_skip_white (idx
, line
);
3124 while (!eol(idx
, line
))
3129 sprintf(subs
, "LL%04x", ln
);
3130 idx
= get_token(idx
, line
, &acc
);
3131 sb_add_string (&sub
, subs
);
3132 hash_add_to_string_table (&assign_hash_table
, &acc
, &sub
, 1);
3133 idx
= sb_skip_comma (idx
, line
);
3148 macro
= (macro_entry
*) xmalloc (sizeof (macro_entry
));
3149 sb_new (¯o
->sub
);
3152 macro
->formal_count
= 0;
3155 idx
= sb_skip_white (idx
, in
);
3156 buffer_and_nest ("MACRO", "ENDM", ¯o
->sub
);
3160 sb_add_sb (&name
, &label
);
3161 if (in
->ptr
[idx
] == '(')
3163 /* It's the label: MACRO (formals,...) sort */
3164 idx
= do_formals (macro
, idx
+ 1, in
);
3165 if (in
->ptr
[idx
] != ')')
3166 ERROR ((stderr
, "Missing ) after formals.\n"));
3169 /* It's the label: MACRO formals,... sort */
3170 idx
= do_formals (macro
, idx
, in
);
3175 idx
= get_token (idx
, in
, &name
);
3176 idx
= sb_skip_white (idx
, in
);
3177 idx
= do_formals (macro
, idx
, in
);
3180 /* and stick it in the macro hash table */
3181 hash_create (¯o_table
, &name
)->value
.m
= macro
;
3186 get_token (idx
, in
, name
)
3192 && ISFIRSTCHAR (in
->ptr
[idx
]))
3194 sb_add_char (name
, in
->ptr
[idx
++]);
3195 while (idx
< in
->len
3196 && ISNEXTCHAR (in
->ptr
[idx
]))
3198 sb_add_char (name
, in
->ptr
[idx
++]);
3201 /* Ignore trailing & */
3202 if (alternate
&& idx
< in
->len
&& in
->ptr
[idx
] == '&')
3207 /* Scan a token, but stop if a ' is seen */
3209 get_apost_token (idx
, in
, name
, kind
)
3215 idx
= get_token (idx
, in
, name
);
3216 if (idx
< in
->len
&& in
->ptr
[idx
] == kind
)
3222 sub_actual (src
, in
, t
, formal_hash
, kind
, out
, copyifnotthere
)
3226 hash_table
*formal_hash
;
3231 /* This is something to take care of */
3233 src
= get_apost_token (src
, in
, t
, kind
);
3234 /* See if it's in the macro's hash table */
3235 ptr
= hash_lookup (formal_hash
, t
);
3238 if (ptr
->value
.f
->actual
.len
)
3240 sb_add_sb (out
, &ptr
->value
.f
->actual
);
3244 sb_add_sb (out
, &ptr
->value
.f
->def
);
3247 else if (copyifnotthere
)
3253 sb_add_char (out
, '\\');
3259 /* Copy the body from the macro buffer into a safe place and
3260 substitute any args. */
3263 macro_expand_body (name
, in
, out
, formals
, formal_hash
)
3267 formal_entry
*formals
;
3268 hash_table
*formal_hash
;
3276 while (src
< in
->len
)
3278 if (in
->ptr
[src
] == '&')
3281 if (mri
&& src
+ 1 < in
->len
&& in
->ptr
[src
+ 1] == '&')
3283 src
= sub_actual (src
+ 2, in
, &t
, formal_hash
, '\'', out
, 1);
3287 src
= sub_actual (src
+ 1, in
, &t
, formal_hash
, '&', out
, 0);
3290 else if (in
->ptr
[src
] == '\\')
3293 if (in
->ptr
[src
] == comment_char
)
3295 /* This is a comment, just drop the rest of the line */
3296 while (src
< in
->len
3297 && in
->ptr
[src
] != '\n')
3301 else if (in
->ptr
[src
] == '(')
3303 /* Sub in till the next ')' literally */
3305 while (src
< in
->len
&& in
->ptr
[src
] != ')')
3307 sb_add_char (out
, in
->ptr
[src
++]);
3309 if (in
->ptr
[src
] == ')')
3312 ERROR ((stderr
, "Missplaced ).\n"));
3314 else if (in
->ptr
[src
] == '@')
3316 /* Sub in the macro invocation number */
3320 sprintf (buffer
, "%05d", number
);
3321 sb_add_string (out
, buffer
);
3323 else if (in
->ptr
[src
] == '&')
3325 /* This is a preprocessor variable name, we don't do them
3327 sb_add_char (out
, '\\');
3328 sb_add_char (out
, '&');
3332 && isalnum ((unsigned char) in
->ptr
[src
]))
3337 if (isdigit ((unsigned char) in
->ptr
[src
]))
3338 ind
= in
->ptr
[src
] - '0';
3339 else if (isupper ((unsigned char) in
->ptr
[src
]))
3340 ind
= in
->ptr
[src
] - 'A' + 10;
3342 ind
= in
->ptr
[src
] - 'a' + 10;
3344 for (f
= formals
; f
!= NULL
; f
= f
->next
)
3346 if (f
->index
== ind
- 1)
3348 if (f
->actual
.len
!= 0)
3349 sb_add_sb (out
, &f
->actual
);
3351 sb_add_sb (out
, &f
->def
);
3359 src
= sub_actual (src
, in
, &t
, formal_hash
, '\'', out
, 0);
3362 else if (ISFIRSTCHAR (in
->ptr
[src
]) && (alternate
|| mri
))
3365 src
= sub_actual (src
, in
, &t
, formal_hash
, '\'', out
, 1);
3367 else if (ISCOMMENTCHAR (in
->ptr
[src
])
3368 && src
+ 1 < in
->len
3369 && ISCOMMENTCHAR (in
->ptr
[src
+1])
3372 /* Two comment chars in a row cause the rest of the line to
3374 while (src
< in
->len
&& in
->ptr
[src
] != '\n')
3377 else if (in
->ptr
[src
] == '"'
3378 || (mri
&& in
->ptr
[src
] == '\''))
3381 sb_add_char (out
, in
->ptr
[src
++]);
3384 && in
->ptr
[src
] == '='
3385 && src
+ 1 < in
->len
3386 && in
->ptr
[src
+ 1] == '=')
3391 src
= get_token (src
+ 2, in
, &t
);
3392 ptr
= hash_lookup (formal_hash
, &t
);
3395 ERROR ((stderr
, "MACRO formal argument %s does not exist.\n",
3400 if (ptr
->value
.f
->actual
.len
)
3402 sb_add_string (out
, "-1");
3406 sb_add_char (out
, '0');
3412 sb_add_char (out
, in
->ptr
[src
++]);
3420 macro_expand (name
, idx
, in
, m
)
3430 int is_positional
= 0;
3437 /* Reset any old value the actuals may have */
3438 for (f
= m
->formals
; f
; f
= f
->next
)
3439 sb_reset (&f
->actual
);
3444 /* The macro may be called with an optional qualifier, which may
3445 be referred to in the macro body as \0. */
3446 if (idx
< in
->len
&& in
->ptr
[idx
] == '.')
3450 n
= (formal_entry
*) xmalloc (sizeof (formal_entry
));
3453 sb_new (&n
->actual
);
3456 n
->next
= m
->formals
;
3459 idx
= get_any_string (idx
+ 1, in
, &n
->actual
, 1, 0);
3463 /* Peel off the actuals and store them away in the hash tables' actuals */
3464 while (!eol(idx
, in
))
3467 idx
= sb_skip_white (idx
, in
);
3468 /* Look and see if it's a positional or keyword arg */
3470 while (scan
< in
->len
3471 && !ISSEP (in
->ptr
[scan
])
3472 && (!alternate
&& in
->ptr
[scan
] != '='))
3474 if (scan
< in
->len
&& (!alternate
) && in
->ptr
[scan
] == '=')
3479 ERROR ((stderr
, "Can't mix positional and keyword arguments.\n"));
3482 /* This is a keyword arg, fetch the formal name and
3483 then the actual stuff */
3485 idx
= get_token (idx
, in
, &t
);
3486 if (in
->ptr
[idx
] != '=')
3487 ERROR ((stderr
, "confused about formal params.\n"));
3489 /* Lookup the formal in the macro's list */
3490 ptr
= hash_lookup (&m
->formal_hash
, &t
);
3493 ERROR ((stderr
, "MACRO formal argument %s does not exist.\n", sb_name (&t
)));
3498 /* Insert this value into the right place */
3499 sb_reset (&ptr
->value
.f
->actual
);
3500 idx
= get_any_string (idx
+ 1, in
, &ptr
->value
.f
->actual
, 0, 0);
3501 if (ptr
->value
.f
->actual
.len
> 0)
3507 /* This is a positional arg */
3511 ERROR ((stderr
, "Can't mix positional and keyword arguments.\n"));
3521 ERROR ((stderr
, "Too many positional arguments.\n"));
3524 f
= (formal_entry
*) xmalloc (sizeof (formal_entry
));
3527 sb_new (&f
->actual
);
3531 for (pf
= &m
->formals
; *pf
!= NULL
; pf
= &(*pf
)->next
)
3532 if ((*pf
)->index
>= c
)
3533 c
= (*pf
)->index
+ 1;
3538 sb_reset (&f
->actual
);
3539 idx
= get_any_string (idx
, in
, &f
->actual
, 1, 0);
3540 if (f
->actual
.len
> 0)
3546 while (f
!= NULL
&& f
->index
< 0);
3549 idx
= sb_skip_comma (idx
, in
);
3557 sb_add_string (&t
, "NARG");
3558 ptr
= hash_lookup (&m
->formal_hash
, &t
);
3559 sb_reset (&ptr
->value
.f
->actual
);
3560 sprintf (buffer
, "%d", narg
);
3561 sb_add_string (&ptr
->value
.f
->actual
, buffer
);
3564 macro_expand_body (name
, &m
->sub
, &out
, m
->formals
, &m
->formal_hash
);
3566 include_buf (name
, &out
, include_macro
, include_next_index ());
3572 /* Discard any unnamed formal arguments. */
3576 if ((*pf
)->name
.len
!= 0)
3580 sb_kill (&(*pf
)->name
);
3581 sb_kill (&(*pf
)->def
);
3582 sb_kill (&(*pf
)->actual
);
3601 /* The macro name must be the first thing on the line */
3607 idx
= get_token (idx
, in
, &name
);
3611 /* Got a name, look it up */
3613 ptr
= hash_lookup (¯o_table
, &name
);
3617 /* It's in the table, copy out the stuff and convert any macro args */
3618 macro_expand (&name
, idx
, in
, ptr
->value
.m
);
3630 /* STRING HANDLING */
3633 getstring (idx
, in
, acc
)
3638 idx
= sb_skip_white (idx
, in
);
3640 while (idx
< in
->len
3641 && (in
->ptr
[idx
] == '"'
3642 || in
->ptr
[idx
] == '<'
3643 || (in
->ptr
[idx
] == '\'' && alternate
)))
3645 if (in
->ptr
[idx
] == '<')
3647 if (alternate
|| mri
)
3651 while ((in
->ptr
[idx
] != '>' || nest
)
3654 if (in
->ptr
[idx
] == '!')
3657 sb_add_char (acc
, in
->ptr
[idx
++]);
3660 if (in
->ptr
[idx
] == '>')
3662 if (in
->ptr
[idx
] == '<')
3664 sb_add_char (acc
, in
->ptr
[idx
++]);
3672 idx
= exp_get_abs ("Character code in string must be absolute expression.\n",
3674 sb_add_char (acc
, code
);
3676 if (in
->ptr
[idx
] != '>')
3677 ERROR ((stderr
, "Missing > for character code.\n"));
3681 else if (in
->ptr
[idx
] == '"' || in
->ptr
[idx
] == '\'')
3683 char tchar
= in
->ptr
[idx
];
3685 while (idx
< in
->len
)
3687 if (alternate
&& in
->ptr
[idx
] == '!')
3690 sb_add_char (acc
, in
->ptr
[idx
++]);
3693 if (in
->ptr
[idx
] == tchar
)
3696 if (idx
>= in
->len
|| in
->ptr
[idx
] != tchar
)
3699 sb_add_char (acc
, in
->ptr
[idx
]);
3709 /* .SDATA[C|Z] <string> */
3713 do_sdata (idx
, in
, type
)
3722 fprintf (outfile
, ".byte\t");
3724 while (!eol (idx
, in
))
3728 idx
= sb_skip_white (idx
, in
);
3729 while (!eol (idx
, in
))
3731 pidx
= idx
= get_any_string (idx
, in
, &acc
, 0, 1);
3736 ERROR ((stderr
, "string for SDATAC longer than 255 characters (%d).\n", acc
.len
));
3738 fprintf (outfile
, "%d", acc
.len
);
3742 for (i
= 0; i
< acc
.len
; i
++)
3746 fprintf (outfile
, ",");
3748 fprintf (outfile
, "%d", acc
.ptr
[i
]);
3755 fprintf (outfile
, ",");
3756 fprintf (outfile
, "0");
3758 idx
= sb_skip_comma (idx
, in
);
3759 if (idx
== pidx
) break;
3761 if (!alternate
&& in
->ptr
[idx
] != ',' && idx
!= in
->len
)
3763 fprintf (outfile
, "\n");
3764 ERROR ((stderr
, "illegal character in SDATA line (0x%x).\n", in
->ptr
[idx
]));
3770 fprintf (outfile
, "\n");
3773 /* .SDATAB <count> <string> */
3785 idx
= exp_get_abs ("Must have absolute SDATAB repeat count.\n", idx
, in
, &repeat
);
3788 ERROR ((stderr
, "Must have positive SDATAB repeat count (%d).\n", repeat
));
3792 idx
= sb_skip_comma (idx
, in
);
3793 idx
= getstring (idx
, in
, &acc
);
3795 for (i
= 0; i
< repeat
; i
++)
3798 fprintf (outfile
, "\t");
3799 fprintf (outfile
, ".byte\t");
3801 fprintf (outfile
, "\n");
3811 FILE *newone
= fopen (name
, "r");
3815 if (isp
== MAX_INCLUDES
)
3816 FATAL ((stderr
, "Unreasonable include depth (%ld).\n", (long) isp
));
3819 sp
->handle
= newone
;
3822 sb_add_string (&sp
->name
, name
);
3825 sp
->pushback_index
= 0;
3826 sp
->type
= include_file
;
3828 sb_new (&sp
->pushback
);
3833 do_include (idx
, in
)
3840 include_path
*includes
;
3844 idx
= getstring (idx
, in
, &t
);
3846 for (includes
= paths_head
; includes
; includes
= includes
->next
)
3849 sb_add_sb (&cat
, &includes
->path
);
3850 sb_add_char (&cat
, '/');
3851 sb_add_sb (&cat
, &t
);
3852 if (new_file (sb_name (&cat
)))
3859 FATAL ((stderr
, "Can't open include file `%s'.\n", text
));
3868 if (sp
!= include_stack
)
3871 fclose (sp
->handle
);
3876 /* Get the next character from the include stack. If there's anything
3877 in the pushback buffer, take that first. If we're at eof, pop from
3878 the stack and try again. Keep the linecount up to date. */
3885 if (sp
->pushback
.len
!= sp
->pushback_index
)
3887 r
= (char) (sp
->pushback
.ptr
[sp
->pushback_index
++]);
3888 /* When they've all gone, reset the pointer */
3889 if (sp
->pushback_index
== sp
->pushback
.len
)
3891 sp
->pushback
.len
= 0;
3892 sp
->pushback_index
= 0;
3895 else if (sp
->handle
)
3897 r
= getc (sp
->handle
);
3902 if (r
== EOF
&& isp
)
3906 while (r
== EOF
&& isp
)
3924 return sp
->linecount
;
3928 include_next_index ()
3932 && index
> MAX_REASONABLE
)
3933 FATAL ((stderr
, "Unreasonable expansion (-u turns off check).\n"));
3938 /* Initialize the chartype vector. */
3944 for (x
= 0; x
< 256; x
++)
3946 if (isalpha (x
) || x
== '_' || x
== '$')
3947 chartype
[x
] |= FIRSTBIT
;
3949 if (isdigit (x
) || isalpha (x
) || x
== '_' || x
== '$')
3950 chartype
[x
] |= NEXTBIT
;
3952 if (x
== ' ' || x
== '\t' || x
== ',' || x
== '"' || x
== ';'
3953 || x
== '"' || x
== '<' || x
== '>' || x
== ')' || x
== '(')
3954 chartype
[x
] |= SEPBIT
;
3956 if (x
== 'b' || x
== 'B'
3957 || x
== 'q' || x
== 'Q'
3958 || x
== 'h' || x
== 'H'
3959 || x
== 'd' || x
== 'D')
3960 chartype
[x
] |= BASEBIT
;
3962 if (x
== ' ' || x
== '\t')
3963 chartype
[x
] |= WHITEBIT
;
3965 if (x
== comment_char
)
3966 chartype
[x
] |= COMMENTBIT
;
3972 /* What to do with all the keywords */
3973 #define PROCESS 0x1000 /* Run substitution over the line */
3974 #define LAB 0x2000 /* Spit out the label */
3976 #define K_EQU (PROCESS|1)
3977 #define K_ASSIGN (PROCESS|2)
3978 #define K_REG (PROCESS|3)
3979 #define K_ORG (PROCESS|4)
3980 #define K_RADIX (PROCESS|5)
3981 #define K_DATA (LAB|PROCESS|6)
3982 #define K_DATAB (LAB|PROCESS|7)
3983 #define K_SDATA (LAB|PROCESS|8)
3984 #define K_SDATAB (LAB|PROCESS|9)
3985 #define K_SDATAC (LAB|PROCESS|10)
3986 #define K_SDATAZ (LAB|PROCESS|11)
3987 #define K_RES (LAB|PROCESS|12)
3988 #define K_SRES (LAB|PROCESS|13)
3989 #define K_SRESC (LAB|PROCESS|14)
3990 #define K_SRESZ (LAB|PROCESS|15)
3991 #define K_EXPORT (LAB|PROCESS|16)
3992 #define K_GLOBAL (LAB|PROCESS|17)
3993 #define K_PRINT (LAB|PROCESS|19)
3994 #define K_FORM (LAB|PROCESS|20)
3995 #define K_HEADING (LAB|PROCESS|21)
3996 #define K_PAGE (LAB|PROCESS|22)
3997 #define K_IMPORT (LAB|PROCESS|23)
3998 #define K_PROGRAM (LAB|PROCESS|24)
3999 #define K_END (PROCESS|25)
4000 #define K_INCLUDE (PROCESS|26)
4001 #define K_IGNORED (PROCESS|27)
4002 #define K_ASSIGNA (PROCESS|28)
4003 #define K_ASSIGNC (29)
4004 #define K_AIF (PROCESS|30)
4005 #define K_AELSE (PROCESS|31)
4006 #define K_AENDI (PROCESS|32)
4007 #define K_AREPEAT (PROCESS|33)
4008 #define K_AENDR (PROCESS|34)
4009 #define K_AWHILE (35)
4010 #define K_AENDW (PROCESS|36)
4011 #define K_EXITM (37)
4012 #define K_MACRO (PROCESS|38)
4014 #define K_ALIGN (PROCESS|LAB|40)
4015 #define K_ALTERNATE (41)
4016 #define K_DB (LAB|PROCESS|42)
4017 #define K_DW (LAB|PROCESS|43)
4018 #define K_DL (LAB|PROCESS|44)
4019 #define K_LOCAL (45)
4020 #define K_IFEQ (PROCESS|46)
4021 #define K_IFNE (PROCESS|47)
4022 #define K_IFLT (PROCESS|48)
4023 #define K_IFLE (PROCESS|49)
4024 #define K_IFGE (PROCESS|50)
4025 #define K_IFGT (PROCESS|51)
4026 #define K_IFC (PROCESS|52)
4027 #define K_IFNC (PROCESS|53)
4028 #define K_IRP (PROCESS|54)
4029 #define K_IRPC (PROCESS|55)
4039 static struct keyword kinfo
[] =
4041 { "EQU", K_EQU
, 0 },
4042 { "ALTERNATE", K_ALTERNATE
, 0 },
4043 { "ASSIGN", K_ASSIGN
, 0 },
4044 { "REG", K_REG
, 0 },
4045 { "ORG", K_ORG
, 0 },
4046 { "RADIX", K_RADIX
, 0 },
4047 { "DATA", K_DATA
, 0 },
4051 { "DATAB", K_DATAB
, 0 },
4052 { "SDATA", K_SDATA
, 0 },
4053 { "SDATAB", K_SDATAB
, 0 },
4054 { "SDATAZ", K_SDATAZ
, 0 },
4055 { "SDATAC", K_SDATAC
, 0 },
4056 { "RES", K_RES
, 0 },
4057 { "SRES", K_SRES
, 0 },
4058 { "SRESC", K_SRESC
, 0 },
4059 { "SRESZ", K_SRESZ
, 0 },
4060 { "EXPORT", K_EXPORT
, 0 },
4061 { "GLOBAL", K_GLOBAL
, 0 },
4062 { "PRINT", K_PRINT
, 0 },
4063 { "FORM", K_FORM
, 0 },
4064 { "HEADING", K_HEADING
, 0 },
4065 { "PAGE", K_PAGE
, 0 },
4066 { "PROGRAM", K_IGNORED
, 0 },
4067 { "END", K_END
, 0 },
4068 { "INCLUDE", K_INCLUDE
, 0 },
4069 { "ASSIGNA", K_ASSIGNA
, 0 },
4070 { "ASSIGNC", K_ASSIGNC
, 0 },
4071 { "AIF", K_AIF
, 0 },
4072 { "AELSE", K_AELSE
, 0 },
4073 { "AENDI", K_AENDI
, 0 },
4074 { "AREPEAT", K_AREPEAT
, 0 },
4075 { "AENDR", K_AENDR
, 0 },
4076 { "EXITM", K_EXITM
, 0 },
4077 { "MACRO", K_MACRO
, 0 },
4078 { "ENDM", K_ENDM
, 0 },
4079 { "AWHILE", K_AWHILE
, 0 },
4080 { "ALIGN", K_ALIGN
, 0 },
4081 { "AENDW", K_AENDW
, 0 },
4082 { "ALTERNATE", K_ALTERNATE
, 0 },
4083 { "LOCAL", K_LOCAL
, 0 },
4087 /* Although the conditional operators are handled by gas, we need to
4088 handle them here as well, in case they are used in a recursive
4089 macro to end the recursion. */
4091 static struct keyword mrikinfo
[] =
4093 { "IFEQ", K_IFEQ
, 0 },
4094 { "IFNE", K_IFNE
, 0 },
4095 { "IFLT", K_IFLT
, 0 },
4096 { "IFLE", K_IFLE
, 0 },
4097 { "IFGE", K_IFGE
, 0 },
4098 { "IFGT", K_IFGT
, 0 },
4099 { "IFC", K_IFC
, 0 },
4100 { "IFNC", K_IFNC
, 0 },
4101 { "ELSEC", K_AELSE
, 0 },
4102 { "ENDC", K_AENDI
, 0 },
4103 { "MEXIT", K_EXITM
, 0 },
4104 { "REPT", K_AREPEAT
, 0 },
4105 { "IRP", K_IRP
, 0 },
4106 { "IRPC", K_IRPC
, 0 },
4107 { "ENDR", K_AENDR
, 0 },
4111 /* Look for a pseudo op on the line. If one's there then call
4115 process_pseudo_op (idx
, line
, acc
)
4122 if (line
->ptr
[idx
] == '.' || alternate
|| mri
)
4124 /* Scan forward and find pseudo name */
4130 if (line
->ptr
[idx
] == '.')
4132 in
= line
->ptr
+ idx
;
4137 while (idx
< line
->len
&& *e
&& ISFIRSTCHAR (*e
))
4139 sb_add_char (acc
, *e
);
4144 ptr
= hash_lookup (&keyword_hash_table
, acc
);
4149 /* This one causes lots of pain when trying to preprocess
4151 WARNING ((stderr
, "Unrecognised pseudo op `%s'.\n", sb_name (acc
)));
4155 if (ptr
->value
.i
& LAB
)
4156 { /* output the label */
4159 fprintf (outfile
, "%s:\t", sb_name (&label
));
4162 fprintf (outfile
, "\t");
4165 if (mri
&& ptr
->value
.i
== K_END
)
4170 sb_add_buffer (&t
, line
->ptr
+ oidx
, idx
- oidx
);
4171 fprintf (outfile
, "\t%s", sb_name (&t
));
4175 if (ptr
->value
.i
& PROCESS
)
4177 /* Polish the rest of the line before handling the pseudo op */
4179 strip_comments(line
);
4182 process_assigns (idx
, line
, acc
);
4184 change_base (0, acc
, line
);
4189 switch (ptr
->value
.i
)
4205 switch (ptr
->value
.i
)
4217 ERROR ((stderr
, "ORG command not allowed.\n"));
4223 do_data (idx
, line
, 1);
4226 do_data (idx
, line
, 2);
4229 do_data (idx
, line
, 4);
4232 do_data (idx
, line
, 0);
4235 do_datab (idx
, line
);
4238 do_sdata (idx
, line
, 0);
4241 do_sdatab (idx
, line
);
4244 do_sdata (idx
, line
, 'c');
4247 do_sdata (idx
, line
, 'z');
4250 do_assign (1, 0, line
);
4256 do_arepeat (idx
, line
);
4262 do_awhile (idx
, line
);
4268 do_assign (0, idx
, line
);
4271 do_align (idx
, line
);
4274 do_res (idx
, line
, 0);
4277 do_res (idx
, line
, 's');
4280 do_include (idx
, line
);
4283 do_local (idx
, line
);
4286 do_macro (idx
, line
);
4292 do_res (idx
, line
, 'c');
4295 do_print (idx
, line
);
4298 do_form (idx
, line
);
4301 do_heading (idx
, line
);
4313 do_res (idx
, line
, 'z');
4321 do_assigna (idx
, line
);
4324 do_assignc (idx
, line
);
4333 do_if (idx
, line
, EQ
);
4336 do_if (idx
, line
, NE
);
4339 do_if (idx
, line
, LT
);
4342 do_if (idx
, line
, LE
);
4345 do_if (idx
, line
, GE
);
4348 do_if (idx
, line
, GT
);
4351 do_ifc (idx
, line
, 0);
4354 do_ifc (idx
, line
, 1);
4357 do_irp (idx
, line
, 0);
4360 do_irp (idx
, line
, 1);
4370 /* Add a keyword to the hash table. */
4373 add_keyword (name
, code
)
4381 sb_add_string (&label
, name
);
4383 hash_add_to_int_table (&keyword_hash_table
, &label
, code
);
4386 for (j
= 0; name
[j
]; j
++)
4387 sb_add_char (&label
, name
[j
] - 'A' + 'a');
4388 hash_add_to_int_table (&keyword_hash_table
, &label
, code
);
4393 /* Build the keyword hash table - put each keyword in the table twice,
4394 once upper and once lower case.*/
4401 for (i
= 0; kinfo
[i
].name
; i
++)
4402 add_keyword (kinfo
[i
].name
, kinfo
[i
].code
);
4406 for (i
= 0; mrikinfo
[i
].name
; i
++)
4407 add_keyword (mrikinfo
[i
].name
, mrikinfo
[i
].code
);
4431 sb_add_char (&value
, *string
);
4434 exp_get_abs ("Invalid expression on command line.\n", 0, &value
, &res
);
4438 sb_add_char (&label
, *string
);
4443 ptr
= hash_create (&vars
, &label
);
4444 free_old_entry (ptr
);
4445 ptr
->type
= hash_integer
;
4451 /* The list of long options. */
4452 static struct option long_options
[] =
4454 { "alternate", no_argument
, 0, 'a' },
4455 { "include", required_argument
, 0, 'I' },
4456 { "commentchar", required_argument
, 0, 'c' },
4457 { "copysource", no_argument
, 0, 's' },
4458 { "debug", no_argument
, 0, 'd' },
4459 { "help", no_argument
, 0, 'h' },
4460 { "mri", no_argument
, 0, 'M' },
4461 { "output", required_argument
, 0, 'o' },
4462 { "print", no_argument
, 0, 'p' },
4463 { "unreasonable", no_argument
, 0, 'u' },
4464 { "version", no_argument
, 0, 'v' },
4465 { "define", required_argument
, 0, 'd' },
4466 { NULL
, no_argument
, 0, 0 }
4469 /* Show a usage message and exit. */
4471 show_usage (file
, status
)
4477 [-a] [--alternate] enter alternate macro mode\n\
4478 [-c char] [--commentchar char] change the comment character from !\n\
4479 [-d] [--debug] print some debugging info\n\
4480 [-h] [--help] print this message\n\
4481 [-M] [--mri] enter MRI compatibility mode\n\
4482 [-o out] [--output out] set the output file\n\
4483 [-p] [--print] print line numbers\n\
4484 [-s] [--copysource] copy source through as comments \n\
4485 [-u] [--unreasonable] allow unreasonable nesting\n\
4486 [-v] [--version] print the program version\n\
4487 [-Dname=value] create preprocessor variable called name, with value\n\
4488 [-Ipath] add to include path list\n\
4489 [in-file]\n", program_name
);
4493 /* Display a help message and exit. */
4497 printf ("%s: Gnu Assembler Macro Preprocessor\n",
4499 show_usage (stdout
, 0);
4516 program_name
= argv
[0];
4517 xmalloc_set_program_name (program_name
);
4519 hash_new_table (101, ¯o_table
);
4520 hash_new_table (101, &keyword_hash_table
);
4521 hash_new_table (101, &assign_hash_table
);
4522 hash_new_table (101, &vars
);
4526 while ((opt
= getopt_long (argc
, argv
, "I:sdhavc:upo:D:M", long_options
,
4540 include_path
*p
= (include_path
*) xmalloc (sizeof (include_path
));
4542 sb_add_string (&p
->path
, optarg
);
4544 paths_tail
->next
= p
;
4551 print_line_number
= 1;
4554 comment_char
= optarg
[0];
4575 printf ("GNU %s version %s\n", program_name
, program_version
);
4581 show_usage (stderr
, 1);
4589 outfile
= fopen (out_name
, "w");
4592 fprintf (stderr
, "%s: Can't open output file `%s'.\n",
4593 program_name
, out_name
);
4605 /* Process all the input files */
4607 while (optind
< argc
)
4609 if (new_file (argv
[optind
]))
4615 fprintf (stderr
, "%s: Can't open input file `%s'.\n",
4616 program_name
, argv
[optind
]);