* gasp.c (include_print_where_line): Always subtract 1 from
[binutils-gdb.git] / gas / gasp.c
1 /* gasp.c - Gnu assembler preprocessor main program.
2 Copyright (C) 1994, 1995 Free Software Foundation, Inc.
3
4 Written by Steve and Judy Chamberlain of Cygnus Support,
5 sac@cygnus.com
6
7 This file is part of GASP, the GNU Assembler Preprocessor.
8
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)
12 any later version.
13
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.
18
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
22 02111-1307, USA. */
23
24 /*
25
26 This program translates the input macros and stuff into a form
27 suitable for gas to consume.
28
29
30 gasp [-sdhau] [-c char] [-o <outfile>] <infile>*
31
32 -s copy source to output
33 -c <char> comments are started with <char> instead of !
34 -u allow unreasonable stuff
35 -p print line numbers
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 !
47
48
49 */
50
51 #include "config.h"
52
53 #include <stdio.h>
54 #include <string.h>
55 #include <getopt.h>
56 #include <ctype.h>
57
58 #ifdef HAVE_STDLIB_H
59 #include <stdlib.h>
60 #endif
61
62 #ifdef NEED_MALLOC_DECLARATION
63 extern char *malloc ();
64 #endif
65
66 #include "ansidecl.h"
67 #include "libiberty.h"
68
69 char *program_version = "1.2";
70
71 #define MAX_INCLUDES 30 /* Maximum include depth */
72 #define MAX_REASONABLE 1000 /* Maximum number of expansions */
73
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 */
85
86 int had_end; /* Seen .END */
87
88 /* The output stream */
89 FILE *outfile;
90
91 /* string blocks
92
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.
103
104 Obstacks provide all the functionality needed, but are too
105 complicated, hence the sb.
106
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.
110 */
111
112 #define max_power_two 30 /* don't allow strings more than
113 2^max_power_two long */
114 /* structure of an sb */
115 typedef struct sb
116 {
117 char *ptr; /* points to the current block. */
118 int len; /* how much is used. */
119 int pot; /* the maximum length is 1<<pot */
120 struct le *item;
121 }
122 sb;
123
124 /* Structure of the free list object of an sb */
125 typedef struct le
126 {
127 struct le *next;
128 int size;
129 char data[1];
130 }
131 sb_element;
132
133 /* The free list */
134 typedef struct
135 {
136 sb_element *size[max_power_two];
137 } sb_list_vector;
138
139 sb_list_vector free_list;
140
141 int string_count[max_power_two];
142
143 /* the attributes of each character are stored as a bit pattern
144 chartype, which gives us quick tests. */
145
146
147 #define FIRSTBIT 1
148 #define NEXTBIT 2
149 #define SEPBIT 4
150 #define WHITEBIT 8
151 #define COMMENTBIT 16
152 #define BASEBIT 32
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];
160
161
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. */
168
169 #define IFNESTING 100
170 struct
171 {
172 int on; /* is the level being output */
173 int hadelse; /* has an aelse been seen */
174 }
175 ifstack[IFNESTING];
176 int ifi;
177
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. */
181
182 typedef struct
183 {
184 char *name;
185 int len;
186 }
187 symbol;
188
189 typedef struct
190 {
191 int value; /* constant part */
192 symbol add_symbol; /* name part */
193 symbol sub_symbol; /* name part */
194 }
195 exp_t;
196
197
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. */
203
204 /* What the data in a hash_entry means */
205 typedef enum
206 {
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 */
211 } hash_type;
212
213 typedef struct hs
214 {
215 sb key; /* symbol name */
216 hash_type type; /* symbol meaning */
217 union
218 {
219 sb s;
220 int i;
221 struct macro_struct *m;
222 struct formal_struct *f;
223 } value;
224 struct hs *next; /* next hash_entry with same hash key */
225 } hash_entry;
226
227 typedef struct
228 {
229 hash_entry **table;
230 int size;
231 } hash_table;
232
233
234 /* Structures used to store macros.
235
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. */
241
242 /* describe the formal arguments to a macro */
243
244 typedef struct formal_struct
245 {
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 */
251 }
252 formal_entry;
253
254 /* describe the macro. */
255
256 typedef struct macro_struct
257 {
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. */
262 }
263 macro_entry;
264
265 /* how we nest files and expand macros etc.
266
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.
271
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.
279 */
280
281 typedef enum
282 {
283 include_file, include_repeat, include_while, include_macro
284 } include_type;
285
286 struct include_stack
287 {
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 */
293 include_type type;
294 int index; /* index of this layer */
295 }
296 include_stack[MAX_INCLUDES];
297
298 struct include_stack *sp;
299 #define isp (sp - include_stack)
300
301 #define dsize 5
302
303
304
305 /* Include file list */
306
307 typedef struct include_path
308 {
309 struct include_path *next;
310 sb path;
311 } include_path;
312
313 include_path *paths_head;
314 include_path *paths_tail;
315
316
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 *));
349 #if 0
350 static void strip_comments PARAMS ((sb *));
351 #endif
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));
431
432 #define FATAL(x) \
433 do { include_print_where_line (stderr); fprintf x ; fatals++; quit(); } while(0)
434 #define ERROR(x) \
435 do { include_print_where_line (stderr); fprintf x; errors++; } while(0)
436 #define WARNING(x) \
437 do { include_print_where_line (stderr); fprintf x; warnings++;} while(0)
438
439
440
441 /* exit the program and return the right ERROR code. */
442 static void
443 quit ()
444 {
445 int exitcode;
446 if (fatals + errors)
447 exitcode = 1;
448 else
449 exitcode = 0;
450
451 if (stats)
452 {
453 int i;
454 for (i = 0; i < max_power_two; i++)
455 {
456 fprintf (stderr, "strings size %8d : %d\n", 1<<i, string_count[i]);
457 }
458 }
459 exit (exitcode);
460 }
461
462
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
469
470 eg:
471 sb_new (&foo);
472 sb_grow... (&foo,...);
473 use foo->ptr[*];
474 sb_kill (&foo);
475
476 */
477
478 /* initializes an sb. */
479
480 static void
481 sb_build (ptr, size)
482 sb *ptr;
483 int size;
484 {
485 /* see if we can find one to allocate */
486 sb_element *e;
487
488 if (size > max_power_two)
489 {
490 FATAL ((stderr, "string longer than %d bytes requested.\n",
491 1 << max_power_two));
492 }
493 e = free_list.size[size];
494 if (!e)
495 {
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];
499 e->size = 1 << size;
500 free_list.size[size] = e;
501 string_count[size]++;
502 }
503
504 /* remove from free list */
505
506 free_list.size[size] = e->next;
507
508 /* copy into callers world */
509 ptr->ptr = e->data;
510 ptr->pot = size;
511 ptr->len = 0;
512 ptr->item = e;
513 }
514
515
516 static void
517 sb_new (ptr)
518 sb *ptr;
519 {
520 sb_build (ptr, dsize);
521 }
522
523 /* deallocate the sb at ptr */
524
525 static
526 void
527 sb_kill (ptr)
528 sb *ptr;
529 {
530 /* return item to free list */
531 ptr->item->next = free_list.size[ptr->pot];
532 free_list.size[ptr->pot] = ptr->item;
533 }
534
535 /* add the sb at s to the end of the sb at ptr */
536
537 static void sb_check ();
538
539 static
540 void
541 sb_add_sb (ptr, s)
542 sb *ptr;
543 sb *s;
544 {
545 sb_check (ptr, s->len);
546 memcpy (ptr->ptr + ptr->len, s->ptr, s->len);
547 ptr->len += s->len;
548 }
549
550 /* make sure that the sb at ptr has room for another len characters,
551 and grow it if it doesn't. */
552
553 static void
554 sb_check (ptr, len)
555 sb *ptr;
556 int len;
557 {
558 if (ptr->len + len >= 1 << ptr->pot)
559 {
560 sb tmp;
561 int pot = ptr->pot;
562 while (ptr->len + len >= 1 << pot)
563 pot++;
564 sb_build (&tmp, pot);
565 sb_add_sb (&tmp, ptr);
566 sb_kill (ptr);
567 *ptr = tmp;
568 }
569 }
570
571 /* make the sb at ptr point back to the beginning. */
572
573 static void
574 sb_reset (ptr)
575 sb *ptr;
576 {
577 ptr->len = 0;
578 }
579
580 /* add character c to the end of the sb at ptr. */
581
582 static void
583 sb_add_char (ptr, c)
584 sb *ptr;
585 int c;
586 {
587 sb_check (ptr, 1);
588 ptr->ptr[ptr->len++] = c;
589 }
590
591 /* add null terminated string s to the end of sb at ptr. */
592
593 static void
594 sb_add_string (ptr, s)
595 sb *ptr;
596 const char *s;
597 {
598 int len = strlen (s);
599 sb_check (ptr, len);
600 memcpy (ptr->ptr + ptr->len, s, len);
601 ptr->len += len;
602 }
603
604 /* add string at s of length len to sb at ptr */
605
606 static void
607 sb_add_buffer (ptr, s, len)
608 sb *ptr;
609 const char *s;
610 int len;
611 {
612 sb_check (ptr, len);
613 memcpy (ptr->ptr + ptr->len, s, len);
614 ptr->len += len;
615 }
616
617
618 /* print the sb at ptr to the output file */
619
620 static
621 void
622 sb_print (ptr)
623 sb *ptr;
624 {
625 int i;
626 int nc = 0;
627
628 for (i = 0; i < ptr->len; i++)
629 {
630 if (nc)
631 {
632 fprintf (outfile, ",");
633 }
634 fprintf (outfile, "%d", ptr->ptr[i]);
635 nc = 1;
636 }
637 }
638
639 static void
640 sb_print_at (idx, ptr)
641 int idx;
642 sb *ptr;
643 {
644 int i;
645 for (i = idx; i < ptr->len; i++)
646 putc (ptr->ptr[i], outfile);
647 }
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. */
650
651 static
652 char *
653 sb_name (in)
654 sb *in;
655 {
656 /* stick a null on the end of the string */
657 sb_add_char (in, 0);
658 return in->ptr;
659 }
660
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 */
663
664 static int
665 sb_skip_white (idx, ptr)
666 int idx;
667 sb *ptr;
668 {
669 while (idx < ptr->len && ISWHITE (ptr->ptr[idx]))
670 idx++;
671 return idx;
672 }
673
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
676 next character. */
677
678 static int
679 sb_skip_comma (idx, ptr)
680 int idx;
681 sb *ptr;
682 {
683 while (idx < ptr->len && ISWHITE (ptr->ptr[idx]))
684 idx++;
685
686 if (idx < ptr->len
687 && ptr->ptr[idx] == ',')
688 idx++;
689
690 while (idx < ptr->len && ISWHITE (ptr->ptr[idx]))
691 idx++;
692
693 return idx;
694 }
695
696
697 /* hash table maintenance. */
698
699 /* build a new hash table with size buckets, and fill in the info at ptr. */
700
701 static void
702 hash_new_table (size, ptr)
703 int size;
704 hash_table *ptr;
705 {
706 int i;
707 ptr->size = size;
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++)
711 ptr->table[i] = 0;
712 }
713
714 /* calculate and return the hash value of the sb at key. */
715
716 static int
717 hash (key)
718 sb *key;
719 {
720 int k = 0x1234;
721 int i;
722 char *p = key->ptr;
723 for (i = 0; i < key->len; i++)
724 {
725 k ^= (k << 2) ^ *p;
726 p++;
727 }
728 return k & 0xf0fff;
729 }
730
731 /* lookup key in hash_table tab, if present, then return it, otherwise
732 build a new one and fill it with hash_integer. */
733
734 static
735 hash_entry *
736 hash_create (tab, key)
737 hash_table *tab;
738 sb *key;
739 {
740 int k = hash (key) % tab->size;
741 hash_entry *p;
742 hash_entry **table = tab->table;
743
744 p = table[k];
745
746 while (1)
747 {
748 if (!p)
749 {
750 hash_entry *n = (hash_entry *) xmalloc (sizeof (hash_entry));
751 n->next = table[k];
752 sb_new (&n->key);
753 sb_add_sb (&n->key, key);
754 table[k] = n;
755 n->type = hash_integer;
756 return n;
757 }
758 if (strncmp (table[k]->key.ptr, key->ptr, key->len) == 0)
759 {
760 return p;
761 }
762 p = p->next;
763 }
764 }
765
766 /* add sb name with key into hash_table tab. if replacing old value
767 and again, then ERROR. */
768
769 static
770 void
771 hash_add_to_string_table (tab, key, name, again)
772 hash_table *tab;
773 sb *key;
774 sb *name;
775 int again;
776 {
777 hash_entry *ptr = hash_create (tab, key);
778 if (ptr->type == hash_integer)
779 {
780 sb_new (&ptr->value.s);
781 }
782 if (ptr->value.s.len)
783 {
784 if (!again)
785 ERROR ((stderr, "redefintion not allowed"));
786 }
787
788 ptr->type = hash_string;
789 sb_reset (&ptr->value.s);
790
791 sb_add_sb (&ptr->value.s, name);
792 }
793
794 /* add integer name to hash_table tab with sb key. */
795
796 static
797 void
798 hash_add_to_int_table (tab, key, name)
799 hash_table *tab;
800 sb *key;
801 int name;
802 {
803 hash_entry *ptr = hash_create (tab, key);
804 ptr->value.i = name;
805 }
806
807 /* lookup sb key in hash_table tab. if found return hash_entry result,
808 else 0. */
809
810 static
811 hash_entry *
812 hash_lookup (tab, key)
813 hash_table *tab;
814 sb *key;
815 {
816 int k = hash (key) % tab->size;
817 hash_entry **table = tab->table;
818 hash_entry *p = table[k];
819 while (p)
820 {
821 if (p->key.len == key->len
822 && strncmp (p->key.ptr, key->ptr, key->len) == 0)
823 return p;
824 p = p->next;
825 }
826 return 0;
827 }
828
829
830 /* expressions
831
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.
836
837 expression precedence:
838 ( )
839 unary + - ~
840 * /
841 + -
842 &
843 | ~
844
845 */
846
847
848 /* make sure that the exp_t at term is constant, if not the give the op ERROR. */
849
850 static
851 void
852 checkconst (op, term)
853 int op;
854 exp_t *term;
855 {
856 if (term->add_symbol.len
857 || term->sub_symbol.len)
858 {
859 ERROR ((stderr, "the %c operator cannot take non-absolute arguments.\n", op));
860 }
861 }
862
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
865 number. */
866
867 static
868 int
869 sb_strtol (idx, string, base, ptr)
870 int idx;
871 sb *string;
872 int base;
873 int *ptr;
874 {
875 int value = 0;
876 idx = sb_skip_white (idx, string);
877
878 while (idx < string->len)
879 {
880 int ch = string->ptr[idx];
881 int dig = 0;
882 if (isdigit (ch))
883 dig = ch - '0';
884 else if (ch >= 'a' && ch <= 'f')
885 dig = ch - 'a' + 10;
886 else if (ch >= 'A' && ch <= 'F')
887 dig = ch - 'A' + 10;
888 else
889 break;
890
891 if (dig >= base)
892 break;
893
894 value = value * base + dig;
895 idx++;
896 }
897 *ptr = value;
898 return idx;
899 }
900
901 static int
902 level_0 (idx, string, lhs)
903 int idx;
904 sb *string;
905 exp_t *lhs;
906 {
907 lhs->add_symbol.len = 0;
908 lhs->add_symbol.name = 0;
909
910 lhs->sub_symbol.len = 0;
911 lhs->sub_symbol.name = 0;
912
913 idx = sb_skip_white (idx, string);
914
915 lhs->value = 0;
916
917 if (isdigit (string->ptr[idx]))
918 {
919 idx = sb_strtol (idx, string, 10, &lhs->value);
920 }
921 else if (ISFIRSTCHAR (string->ptr[idx]))
922 {
923 int len = 0;
924 lhs->add_symbol.name = string->ptr + idx;
925 while (idx < string->len && ISNEXTCHAR (string->ptr[idx]))
926 {
927 idx++;
928 len++;
929 }
930 lhs->add_symbol.len = len;
931 }
932 else if (string->ptr[idx] == '"')
933 {
934 sb acc;
935 sb_new (&acc);
936 ERROR ((stderr, "string where expression expected.\n"));
937 idx = getstring (idx, string, &acc);
938 sb_kill (&acc);
939 }
940 else
941 {
942 ERROR ((stderr, "can't find primary in expression.\n"));
943 idx++;
944 }
945 return sb_skip_white (idx, string);
946 }
947
948
949
950 static int
951 level_1 (idx, string, lhs)
952 int idx;
953 sb *string;
954 exp_t *lhs;
955 {
956 idx = sb_skip_white (idx, string);
957
958 switch (string->ptr[idx])
959 {
960 case '+':
961 idx = level_1 (idx + 1, string, lhs);
962 break;
963 case '~':
964 idx = level_1 (idx + 1, string, lhs);
965 checkconst ('~', lhs);
966 lhs->value = ~lhs->value;
967 break;
968 case '-':
969 {
970 symbol t;
971 idx = level_1 (idx + 1, string, lhs);
972 lhs->value = -lhs->value;
973 t = lhs->add_symbol;
974 lhs->add_symbol = lhs->sub_symbol;
975 lhs->sub_symbol = t;
976 break;
977 }
978 case '(':
979 idx++;
980 idx = level_5 (sb_skip_white (idx, string), string, lhs);
981 if (string->ptr[idx] != ')')
982 ERROR ((stderr, "misplaced closing parens.\n"));
983 else
984 idx++;
985 break;
986 default:
987 idx = level_0 (idx, string, lhs);
988 break;
989 }
990 return sb_skip_white (idx, string);
991 }
992
993 static int
994 level_2 (idx, string, lhs)
995 int idx;
996 sb *string;
997 exp_t *lhs;
998 {
999 exp_t rhs;
1000
1001 idx = level_1 (idx, string, lhs);
1002
1003 while (idx < string->len && (string->ptr[idx] == '*'
1004 || string->ptr[idx] == '/'))
1005 {
1006 char op = string->ptr[idx++];
1007 idx = level_1 (idx, string, &rhs);
1008 switch (op)
1009 {
1010 case '*':
1011 checkconst ('*', lhs);
1012 checkconst ('*', &rhs);
1013 lhs->value *= rhs.value;
1014 break;
1015 case '/':
1016 checkconst ('/', lhs);
1017 checkconst ('/', &rhs);
1018 if (rhs.value == 0)
1019 ERROR ((stderr, "attempt to divide by zero.\n"));
1020 else
1021 lhs->value /= rhs.value;
1022 break;
1023 }
1024 }
1025 return sb_skip_white (idx, string);
1026 }
1027
1028
1029 static int
1030 level_3 (idx, string, lhs)
1031 int idx;
1032 sb *string;
1033 exp_t *lhs;
1034 {
1035 exp_t rhs;
1036
1037 idx = level_2 (idx, string, lhs);
1038
1039 while (idx < string->len
1040 && (string->ptr[idx] == '+'
1041 || string->ptr[idx] == '-'))
1042 {
1043 char op = string->ptr[idx++];
1044 idx = level_2 (idx, string, &rhs);
1045 switch (op)
1046 {
1047 case '+':
1048 lhs->value += rhs.value;
1049 if (lhs->add_symbol.name && rhs.add_symbol.name)
1050 {
1051 ERROR ((stderr, "can't add two relocatable expressions\n"));
1052 }
1053 /* change nn+symbol to symbol + nn */
1054 if (rhs.add_symbol.name)
1055 {
1056 lhs->add_symbol = rhs.add_symbol;
1057 }
1058 break;
1059 case '-':
1060 lhs->value -= rhs.value;
1061 lhs->sub_symbol = rhs.add_symbol;
1062 break;
1063 }
1064 }
1065 return sb_skip_white (idx, string);
1066 }
1067
1068 static int
1069 level_4 (idx, string, lhs)
1070 int idx;
1071 sb *string;
1072 exp_t *lhs;
1073 {
1074 exp_t rhs;
1075
1076 idx = level_3 (idx, string, lhs);
1077
1078 while (idx < string->len &&
1079 string->ptr[idx] == '&')
1080 {
1081 char op = string->ptr[idx++];
1082 idx = level_3 (idx, string, &rhs);
1083 switch (op)
1084 {
1085 case '&':
1086 checkconst ('&', lhs);
1087 checkconst ('&', &rhs);
1088 lhs->value &= rhs.value;
1089 break;
1090 }
1091 }
1092 return sb_skip_white (idx, string);
1093 }
1094
1095 static int
1096 level_5 (idx, string, lhs)
1097 int idx;
1098 sb *string;
1099 exp_t *lhs;
1100 {
1101 exp_t rhs;
1102
1103 idx = level_4 (idx, string, lhs);
1104
1105 while (idx < string->len
1106 && (string->ptr[idx] == '|' || string->ptr[idx] == '~'))
1107 {
1108 char op = string->ptr[idx++];
1109 idx = level_4 (idx, string, &rhs);
1110 switch (op)
1111 {
1112 case '|':
1113 checkconst ('|', lhs);
1114 checkconst ('|', &rhs);
1115 lhs->value |= rhs.value;
1116 break;
1117 case '~':
1118 checkconst ('~', lhs);
1119 checkconst ('~', &rhs);
1120 lhs->value ^= rhs.value;
1121 break;
1122 }
1123 }
1124 return sb_skip_white (idx, string);
1125 }
1126
1127
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.
1130 */
1131
1132 static int
1133 exp_parse (idx, string, res)
1134 int idx;
1135 sb *string;
1136 exp_t *res;
1137 {
1138 return level_5 (sb_skip_white (idx, string), string, res);
1139 }
1140
1141
1142 /* turn the expression at exp into text and glue it onto the end of
1143 string. */
1144
1145 static void
1146 exp_string (exp, string)
1147 exp_t *exp;
1148 sb *string;
1149 {
1150 int np = 0;
1151 int ad = 0;
1152 sb_reset (string);
1153
1154 if (exp->add_symbol.len)
1155 {
1156 sb_add_buffer (string, exp->add_symbol.name, exp->add_symbol.len);
1157 np = 1;
1158 ad = 1;
1159 }
1160 if (exp->value)
1161 {
1162 char buf[20];
1163 if (np)
1164 sb_add_char (string, '+');
1165 sprintf (buf, "%d", exp->value);
1166 sb_add_string (string, buf);
1167 np = 1;
1168 ad = 1;
1169 }
1170 if (exp->sub_symbol.len)
1171 {
1172 sb_add_char (string, '-');
1173 sb_add_buffer (string, exp->add_symbol.name, exp->add_symbol.len);
1174 np = 0;
1175 ad = 1;
1176 }
1177
1178 if (!ad)
1179 sb_add_char (string, '0');
1180 }
1181
1182
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. */
1186
1187 static int
1188 exp_get_abs (emsg, idx, in, val)
1189 const char *emsg;
1190 int idx;
1191 sb *in;
1192 int *val;
1193 {
1194 exp_t res;
1195 idx = exp_parse (idx, in, &res);
1196 if (res.add_symbol.len || res.sub_symbol.len)
1197 ERROR ((stderr, emsg));
1198 *val = res.value;
1199 return idx;
1200 }
1201
1202
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 */
1207
1208 #define in_comment ';'
1209
1210 #if 0
1211 static void
1212 strip_comments (out)
1213 sb *out;
1214 {
1215 char *s = out->ptr;
1216 int i = 0;
1217 for (i = 0; i < out->len; i++)
1218 {
1219 if (ISCOMMENTCHAR(s[i]))
1220 {
1221 out->len = i;
1222 return;
1223 }
1224 }
1225 }
1226 #endif
1227
1228 /* push back character ch so that it can be read again. */
1229
1230 static void
1231 unget (ch)
1232 int ch;
1233 {
1234 if (ch == '\n')
1235 {
1236 sp->linecount--;
1237 }
1238 if (sp->pushback_index)
1239 sp->pushback_index--;
1240 else
1241 sb_add_char (&sp->pushback, ch);
1242 }
1243
1244 /* push the sb ptr onto the include stack, with the given name, type and index. */
1245
1246 static
1247 void
1248 include_buf (name, ptr, type, index)
1249 sb *name;
1250 sb *ptr;
1251 include_type type;
1252 int index;
1253 {
1254 sp++;
1255 if (sp - include_stack >= MAX_INCLUDES)
1256 FATAL ((stderr, "unreasonable nesting.\n"));
1257 sb_new (&sp->name);
1258 sb_add_sb (&sp->name, name);
1259 sp->handle = 0;
1260 sp->linecount = 1;
1261 sp->pushback_index = 0;
1262 sp->type = type;
1263 sp->index = index;
1264 sb_new (&sp->pushback);
1265 sb_add_sb (&sp->pushback, ptr);
1266 }
1267
1268
1269 /* used in ERROR messages, print info on where the include stack is onto file. */
1270 static
1271 void
1272 include_print_where_line (file)
1273 FILE *file;
1274 {
1275 struct include_stack *p = include_stack + 1;
1276
1277 while (p <= sp)
1278 {
1279 fprintf (file, "%s:%d ", sb_name (&p->name), p->linecount - 1);
1280 p++;
1281 }
1282 }
1283
1284 /* used in listings, print the line number onto file. */
1285 static void
1286 include_print_line (file)
1287 FILE *file;
1288 {
1289 int n;
1290 struct include_stack *p = include_stack + 1;
1291
1292 n = fprintf (file, "%4d", p->linecount);
1293 p++;
1294 while (p <= sp)
1295 {
1296 n += fprintf (file, ".%d", p->linecount);
1297 p++;
1298 }
1299 while (n < 8 * 3)
1300 {
1301 fprintf (file, " ");
1302 n++;
1303 }
1304 }
1305
1306
1307 /* read a line from the top of the include stack into sb in. */
1308
1309 static int
1310 get_line (in)
1311 sb *in;
1312 {
1313 int online = 0;
1314 int more = 1;
1315
1316 if (copysource)
1317 {
1318 putc (comment_char, outfile);
1319 if (print_line_number)
1320 include_print_line (outfile);
1321 }
1322
1323 while (1)
1324 {
1325 int ch = get ();
1326
1327 while (ch == '\r')
1328 ch = get ();
1329
1330 if (ch == EOF)
1331 {
1332 if (online)
1333 {
1334 WARNING ((stderr, "End of file not at start of line.\n"));
1335 if (copysource)
1336 putc ('\n', outfile);
1337 ch = '\n';
1338 }
1339 else
1340 more = 0;
1341 break;
1342 }
1343
1344 if (copysource)
1345 {
1346 putc (ch, outfile);
1347 }
1348
1349 if (ch == '\n')
1350 {
1351 ch = get ();
1352 online = 0;
1353 if (ch == '+')
1354 {
1355 /* continued line */
1356 if (copysource)
1357 {
1358 putc (comment_char, outfile);
1359 putc ('+', outfile);
1360 }
1361 ch = get ();
1362 }
1363 else
1364 {
1365 if (ch != EOF)
1366 unget (ch);
1367 break;
1368 }
1369 }
1370 else
1371 {
1372 sb_add_char (in, ch);
1373 }
1374 online++;
1375 }
1376
1377 return more;
1378 }
1379
1380 /* find a label from sb in and put it in out. */
1381
1382 static int
1383 grab_label (in, out)
1384 sb *in;
1385 sb *out;
1386 {
1387 int i = 0;
1388 sb_reset (out);
1389 if (ISFIRSTCHAR (in->ptr[i]))
1390 {
1391 sb_add_char (out, in->ptr[i]);
1392 i++;
1393 while ((ISNEXTCHAR (in->ptr[i])
1394 || in->ptr[i] == '\\'
1395 || in->ptr[i] == '&')
1396 && i < in->len)
1397 {
1398 sb_add_char (out, in->ptr[i]);
1399 i++;
1400 }
1401 }
1402 return i;
1403 }
1404
1405 /* find all strange base stuff and turn into decimal. also
1406 find all the other numbers and convert them from the default radix */
1407
1408 static void
1409 change_base (idx, in, out)
1410 int idx;
1411 sb *in;
1412 sb *out;
1413 {
1414 char buffer[20];
1415
1416 while (idx < in->len)
1417 {
1418 if (idx < in->len - 1 && in->ptr[idx + 1] == '\'' && ! mri)
1419 {
1420 int base;
1421 int value;
1422 switch (in->ptr[idx])
1423 {
1424 case 'b':
1425 case 'B':
1426 base = 2;
1427 break;
1428 case 'q':
1429 case 'Q':
1430 base = 8;
1431 break;
1432 case 'h':
1433 case 'H':
1434 base = 16;
1435 break;
1436 case 'd':
1437 case 'D':
1438 base = 10;
1439 break;
1440 default:
1441 ERROR ((stderr, "Illegal base character %c.\n", in->ptr[idx]));
1442 base = 10;
1443 break;
1444 }
1445
1446 idx = sb_strtol (idx + 2, in, base, &value);
1447 sprintf (buffer, "%d", value);
1448 sb_add_string (out, buffer);
1449 }
1450 else if (ISFIRSTCHAR (in->ptr[idx]))
1451 {
1452 /* copy entire names through quickly */
1453 sb_add_char (out, in->ptr[idx]);
1454 idx++;
1455 while (idx < in->len && ISNEXTCHAR (in->ptr[idx]))
1456 {
1457 sb_add_char (out, in->ptr[idx]);
1458 idx++;
1459 }
1460 }
1461 else if (isdigit (in->ptr[idx]))
1462 {
1463 int value;
1464 /* all numbers must start with a digit, let's chew it and
1465 spit out decimal */
1466 idx = sb_strtol (idx, in, radix, &value);
1467 sprintf (buffer, "%d", value);
1468 sb_add_string (out, buffer);
1469
1470 /* skip all undigsested letters */
1471 while (idx < in->len && ISNEXTCHAR (in->ptr[idx]))
1472 {
1473 sb_add_char (out, in->ptr[idx]);
1474 idx++;
1475 }
1476 }
1477 else if (in->ptr[idx] == '"' || in->ptr[idx] == '\'')
1478 {
1479 char tchar = in->ptr[idx];
1480 /* copy entire names through quickly */
1481 sb_add_char (out, in->ptr[idx]);
1482 idx++;
1483 while (idx < in->len && in->ptr[idx] != tchar)
1484 {
1485 sb_add_char (out, in->ptr[idx]);
1486 idx++;
1487 }
1488 }
1489 else
1490 {
1491 /* nothing special, just pass it through */
1492 sb_add_char (out, in->ptr[idx]);
1493 idx++;
1494 }
1495 }
1496
1497 }
1498
1499 /* .end */
1500 static void
1501 do_end (in)
1502 sb *in;
1503 {
1504 had_end = 1;
1505 if (mri)
1506 fprintf (outfile, "%s\n", sb_name (in));
1507 }
1508
1509 /* .assign */
1510
1511 static void
1512 do_assign (again, idx, in)
1513 int again;
1514 int idx;
1515 sb *in;
1516 {
1517 /* stick label in symbol table with following value */
1518 exp_t e;
1519 sb acc;
1520
1521 sb_new (&acc);
1522 idx = exp_parse (idx, in, &e);
1523 exp_string (&e, &acc);
1524 hash_add_to_string_table (&assign_hash_table, &label, &acc, again);
1525 sb_kill (&acc);
1526 }
1527
1528
1529 /* .radix [b|q|d|h] */
1530
1531 static
1532 void
1533 do_radix (ptr)
1534 sb *ptr;
1535 {
1536 int idx = sb_skip_white (0, ptr);
1537 switch (ptr->ptr[idx])
1538 {
1539 case 'B':
1540 case 'b':
1541 radix = 2;
1542 break;
1543 case 'q':
1544 case 'Q':
1545 radix = 8;
1546 break;
1547 case 'd':
1548 case 'D':
1549 radix = 10;
1550 break;
1551 case 'h':
1552 case 'H':
1553 radix = 16;
1554 break;
1555 default:
1556 ERROR ((stderr, "radix is %c must be one of b, q, d or h", radix));
1557 }
1558 }
1559
1560
1561 /* Parse off a .b, .w or .l */
1562
1563 static int
1564 get_opsize (idx, in, size)
1565 int idx;
1566 sb *in;
1567 int *size;
1568 {
1569 *size = 4;
1570 if (in->ptr[idx] == '.')
1571 {
1572 idx++;
1573 }
1574 switch (in->ptr[idx])
1575 {
1576 case 'b':
1577 case 'B':
1578 *size = 1;
1579 break;
1580 case 'w':
1581 case 'W':
1582 *size = 2;
1583 break;
1584 case 'l':
1585 case 'L':
1586 *size = 4;
1587 break;
1588 case ' ':
1589 case '\t':
1590 break;
1591 default:
1592 ERROR ((stderr, "size must be one of b, w or l, is %c.\n", in->ptr[idx]));
1593 break;
1594 }
1595 idx++;
1596
1597 return idx;
1598 }
1599
1600 static
1601 int eol(idx, line)
1602 int idx;
1603 sb *line;
1604 {
1605 idx = sb_skip_white (idx, line);
1606 if (idx < line->len
1607 && ISCOMMENTCHAR(line->ptr[idx]))
1608 return 1;
1609 if (idx >= line->len)
1610 return 1;
1611 return 0;
1612 }
1613
1614 /* .data [.b|.w|.l] <data>*
1615 or d[bwl] <data>* */
1616
1617 static void
1618 do_data (idx, in, size)
1619 int idx;
1620 sb *in;
1621 int size;
1622 {
1623 int opsize = 4;
1624 char *opname = ".yikes!";
1625 sb acc;
1626 sb_new (&acc);
1627
1628 if (!size)
1629 {
1630 idx = get_opsize (idx, in, &opsize);
1631 }
1632 else {
1633 opsize = size;
1634 }
1635 switch (opsize)
1636 {
1637 case 4:
1638 opname = ".long";
1639 break;
1640 case 2:
1641 opname = ".short";
1642 break;
1643 case 1:
1644 opname = ".byte";
1645 break;
1646 }
1647
1648
1649 fprintf (outfile, "%s\t", opname);
1650
1651 idx = sb_skip_white (idx, in);
1652
1653 if (alternate
1654 && idx < in->len
1655 && in->ptr[idx] == '"')
1656 {
1657 int i;
1658 idx = getstring (idx, in, &acc);
1659 for (i = 0; i < acc.len; i++)
1660 {
1661 if (i)
1662 fprintf(outfile,",");
1663 fprintf (outfile, "%d", acc.ptr[i]);
1664 }
1665 }
1666 else
1667 {
1668 while (!eol (idx, in))
1669 {
1670 exp_t e;
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] == ',')
1676 {
1677 fprintf (outfile, ",");
1678 idx++;
1679 }
1680 }
1681 }
1682 sb_kill (&acc);
1683 sb_print_at (idx, in);
1684 fprintf (outfile, "\n");
1685 }
1686
1687 /* .datab [.b|.w|.l] <repeat>,<fill> */
1688
1689 static void
1690 do_datab (idx, in)
1691 int idx;
1692 sb *in;
1693 {
1694 int opsize;
1695 int repeat;
1696 int fill;
1697
1698 idx = get_opsize (idx, in, &opsize);
1699
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);
1703
1704 fprintf (outfile, ".fill\t%d,%d,%d\n", repeat, opsize, fill);
1705 }
1706
1707 /* .align <size> */
1708
1709 static void
1710 do_align (idx, in)
1711 int idx;
1712 sb *in;
1713 {
1714 int al;
1715 idx = exp_get_abs ("align needs absolute expression.\n", idx, in, &al);
1716
1717 if (al != 1
1718 && al != 2
1719 && al != 4)
1720 WARNING ((stderr, "alignment must be one of 1, 2 or 4.\n"));
1721
1722 fprintf (outfile, ".align %d\n", al);
1723 }
1724
1725 /* .res[.b|.w|.l] <size> */
1726
1727 static void
1728 do_res (idx, in, type)
1729 int idx;
1730 sb *in;
1731 int type;
1732 {
1733 int size = 4;
1734 int count = 0;
1735
1736 idx = get_opsize (idx, in, &size);
1737 while (!eol(idx, in))
1738 {
1739 idx = sb_skip_white (idx, in);
1740 if (in->ptr[idx] == ',')
1741 idx++;
1742 idx = exp_get_abs ("res needs absolute expression for fill count.\n", idx, in, &count);
1743
1744 if (type == 'c' || type == 'z')
1745 count++;
1746
1747 fprintf (outfile, ".space %d\n", count * size);
1748 }
1749 }
1750
1751
1752 /* .export */
1753
1754 static void
1755 do_export (in)
1756 sb *in;
1757 {
1758 fprintf (outfile, ".global %s\n", sb_name (in));
1759 }
1760
1761 /* .print [list] [nolist] */
1762
1763 static void
1764 do_print (idx, in)
1765 int idx;
1766 sb *in;
1767 {
1768 idx = sb_skip_white (idx, in);
1769 while (idx < in->len)
1770 {
1771 if (strncasecmp (in->ptr + idx, "LIST", 4) == 0)
1772 {
1773 fprintf (outfile, ".list\n");
1774 idx += 4;
1775 }
1776 else if (strncasecmp (in->ptr + idx, "NOLIST", 6) == 0)
1777 {
1778 fprintf (outfile, ".nolist\n");
1779 idx += 6;
1780 }
1781 idx++;
1782 }
1783 }
1784
1785 /* .head */
1786 static void
1787 do_heading (idx, in)
1788 int idx;
1789 sb *in;
1790 {
1791 sb head;
1792 sb_new (&head);
1793 idx = getstring (idx, in, &head);
1794 fprintf (outfile, ".title \"%s\"\n", sb_name (&head));
1795 sb_kill (&head);
1796 }
1797
1798 /* .page */
1799
1800 static void
1801 do_page ()
1802 {
1803 fprintf (outfile, ".eject\n");
1804 }
1805
1806 /* .form [lin=<value>] [col=<value>] */
1807 static void
1808 do_form (idx, in)
1809 int idx;
1810 sb *in;
1811 {
1812 int lines = 60;
1813 int columns = 132;
1814 idx = sb_skip_white (idx, in);
1815
1816 while (idx < in->len)
1817 {
1818
1819 if (strncasecmp (in->ptr + idx, "LIN=", 4) == 0)
1820 {
1821 idx += 4;
1822 idx = exp_get_abs ("form LIN= needs absolute expresssion.\n", idx, in, &lines);
1823 }
1824
1825 if (strncasecmp (in->ptr + idx, "COL=", 4) == 0)
1826 {
1827 idx += 4;
1828 idx = exp_get_abs ("form COL= needs absolute expresssion.\n", idx, in, &columns);
1829 }
1830
1831 idx++;
1832 }
1833 fprintf (outfile, ".psize %d,%d\n", lines, columns);
1834
1835 }
1836
1837
1838 /* Fetch string from the input stream,
1839 rules:
1840 'Bxyx<whitespace> -> return 'Bxyza
1841 %<char> -> return string of decimal value of x
1842 "<string>" -> return string
1843 xyx<whitespace> -> return xyz
1844 */
1845 static int
1846 get_any_string (idx, in, out, expand, pretend_quoted)
1847 int idx;
1848 sb *in;
1849 sb *out;
1850 int expand;
1851 int pretend_quoted;
1852 {
1853 sb_reset (out);
1854 idx = sb_skip_white (idx, in);
1855
1856 if (idx < in->len)
1857 {
1858 if (in->len > 2 && in->ptr[idx+1] == '\'' && ISBASE (in->ptr[idx]))
1859 {
1860 while (!ISSEP (in->ptr[idx]))
1861 sb_add_char (out, in->ptr[idx++]);
1862 }
1863 else if (in->ptr[idx] == '%'
1864 && alternate
1865 && expand)
1866 {
1867 int val;
1868 char buf[20];
1869 /* Turns the next expression into a string */
1870 idx = exp_get_abs ("% operator needs absolute expression",
1871 idx + 1,
1872 in,
1873 &val);
1874 sprintf(buf, "%d", val);
1875 sb_add_string (out, buf);
1876 }
1877 else if (in->ptr[idx] == '"'
1878 || in->ptr[idx] == '<'
1879 || (alternate && in->ptr[idx] == '\''))
1880 {
1881 if (alternate && expand)
1882 {
1883 /* Keep the quotes */
1884 sb_add_char (out, '\"');
1885
1886 idx = getstring (idx, in, out);
1887 sb_add_char (out, '\"');
1888
1889 }
1890 else {
1891 idx = getstring (idx, in, out);
1892 }
1893 }
1894 else
1895 {
1896 while (idx < in->len
1897 && (in->ptr[idx] == '"'
1898 || in->ptr[idx] == '\''
1899 || pretend_quoted
1900 || !ISSEP (in->ptr[idx])))
1901 {
1902 if (in->ptr[idx] == '"'
1903 || in->ptr[idx] == '\'')
1904 {
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++]);
1910 if (idx == in->len)
1911 return idx;
1912 }
1913 sb_add_char (out, in->ptr[idx++]);
1914 }
1915 }
1916 }
1917
1918 return idx;
1919 }
1920
1921
1922 /* skip along sb in starting at idx, suck off whitespace a ( and more
1923 whitespace. return the idx of the next char */
1924
1925 static int
1926 skip_openp (idx, in)
1927 int idx;
1928 sb *in;
1929 {
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);
1934 return idx;
1935 }
1936
1937 /* skip along sb in starting at idx, suck off whitespace a ) and more
1938 whitespace. return the idx of the next char */
1939
1940 static int
1941 skip_closep (idx, in)
1942 int idx;
1943 sb *in;
1944 {
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);
1949 return idx;
1950 }
1951
1952 /* .len */
1953
1954 static int
1955 dolen (idx, in, out)
1956 int idx;
1957 sb *in;
1958 sb *out;
1959 {
1960
1961 sb stringout;
1962 char buffer[10];
1963
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);
1970
1971 sb_kill (&stringout);
1972 return idx;
1973 }
1974
1975
1976 /* .instr */
1977
1978 static
1979 int
1980 doinstr (idx, in, out)
1981 int idx;
1982 sb *in;
1983 sb *out;
1984 {
1985 sb string;
1986 sb search;
1987 int i;
1988 int start;
1989 int res;
1990 char buffer[10];
1991
1992 sb_new (&string);
1993 sb_new (&search);
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]))
2000 {
2001 idx = exp_get_abs (".instr needs absolute expresson.\n", idx, in, &start);
2002 }
2003 else
2004 {
2005 start = 0;
2006 }
2007 idx = skip_closep (idx, in);
2008 res = -1;
2009 for (i = start; i < string.len; i++)
2010 {
2011 if (strncmp (string.ptr + i, search.ptr, search.len) == 0)
2012 {
2013 res = i;
2014 break;
2015 }
2016 }
2017 sprintf (buffer, "%d", res);
2018 sb_add_string (out, buffer);
2019 sb_kill (&string);
2020 sb_kill (&search);
2021 return idx;
2022 }
2023
2024
2025 static int
2026 dosubstr (idx, in, out)
2027 int idx;
2028 sb *in;
2029 sb *out;
2030 {
2031 sb string;
2032 int pos;
2033 int len;
2034 sb_new (&string);
2035
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);
2043
2044
2045 if (len < 0 || pos < 0 ||
2046 pos > string.len
2047 || pos + len > string.len)
2048 {
2049 sb_add_string (out, " ");
2050 }
2051 else
2052 {
2053 sb_add_char (out, '"');
2054 while (len > 0)
2055 {
2056 sb_add_char (out, string.ptr[pos++]);
2057 len--;
2058 }
2059 sb_add_char (out, '"');
2060 }
2061 sb_kill(&string);
2062 return idx;
2063 }
2064
2065 /* scan line, change tokens in the hash table to their replacements */
2066 static void
2067 process_assigns (idx, in, buf)
2068 int idx;
2069 sb *in;
2070 sb *buf;
2071 {
2072 while (idx < in->len)
2073 {
2074 hash_entry *ptr;
2075 if (in->ptr[idx] == '\\'
2076 && in->ptr[idx + 1] == '&')
2077 {
2078 idx = condass_lookup_name (in, idx + 2, buf, 1);
2079 }
2080 else if (in->ptr[idx] == '\\'
2081 && in->ptr[idx + 1] == '$')
2082 {
2083 idx = condass_lookup_name (in, idx + 2, buf, 0);
2084 }
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]))
2109 {
2110 /* may be a simple name subsitution, see if we have a word */
2111 sb acc;
2112 int cur = idx + 1;
2113 while (cur < in->len
2114 && (ISNEXTCHAR (in->ptr[cur])))
2115 cur++;
2116
2117 sb_new (&acc);
2118 sb_add_buffer (&acc, in->ptr + idx, cur - idx);
2119 ptr = hash_lookup (&assign_hash_table, &acc);
2120 if (ptr)
2121 {
2122 /* Found a definition for it */
2123 sb_add_sb (buf, &ptr->value.s);
2124 }
2125 else
2126 {
2127 /* No definition, just copy the word */
2128 sb_add_sb (buf, &acc);
2129 }
2130 sb_kill (&acc);
2131 idx = cur;
2132 }
2133 else
2134 {
2135 sb_add_char (buf, in->ptr[idx++]);
2136 }
2137 }
2138 }
2139
2140 static int
2141 get_and_process (idx, in, out)
2142 int idx;
2143 sb *in;
2144 sb *out;
2145 {
2146 sb t;
2147 sb_new (&t);
2148 idx = get_any_string (idx, in, &t, 1, 0);
2149 process_assigns (0, &t, out);
2150 sb_kill (&t);
2151 return idx;
2152 }
2153
2154 static
2155 void
2156 process_file ()
2157 {
2158 sb line;
2159 sb t1, t2;
2160 sb acc;
2161 sb label_in;
2162 int more;
2163
2164 sb_new (&line);
2165 sb_new (&t1);
2166 sb_new (&t2);
2167 sb_new(&acc);
2168 sb_new (&label_in);
2169 sb_reset (&line);
2170 more = get_line (&line);
2171 while (more)
2172 {
2173 /* Find any label and pseudo op that we're intested in */
2174 int l;
2175 if (line.len == 0)
2176 {
2177 if (condass_on ())
2178 fprintf (outfile, "\n");
2179 }
2180 else if (mri
2181 && (line.ptr[0] == '*'
2182 || line.ptr[0] == '!'))
2183 {
2184 /* MRI line comment. */
2185 fprintf (outfile, sb_name (&line));
2186 }
2187 else
2188 {
2189 l = grab_label (&line, &label_in);
2190 sb_reset (&label);
2191 if (label_in.len)
2192 {
2193 /* Munge any label */
2194
2195
2196 process_assigns (0, &label_in, &label);
2197 }
2198
2199 if (line.ptr[l] == ':')
2200 l++;
2201 while (ISWHITE (line.ptr[l]) && l < line.len)
2202 l++;
2203
2204 if (l < line.len)
2205 {
2206 if (process_pseudo_op (l, &line, &acc))
2207 {
2208
2209
2210
2211 }
2212 else if (condass_on ())
2213 {
2214 if (macro_op (l, &line))
2215 {
2216
2217
2218 }
2219 else
2220 {
2221 {
2222 if (label.len)
2223 {
2224 fprintf (outfile, "%s:\t", sb_name (&label));
2225 }
2226 else
2227 fprintf (outfile, "\t");
2228 sb_reset(&t1);
2229 process_assigns (l, &line, &t1);
2230 sb_reset (&t2);
2231 change_base (0, &t1, &t2);
2232 fprintf (outfile, "%s\n", sb_name (&t2));
2233 }
2234 }
2235 }
2236 }
2237 else {
2238 /* Only a label on this line */
2239 if (label.len && condass_on())
2240 {
2241 fprintf (outfile, "%s:\n", sb_name (&label));
2242 }
2243 }
2244 }
2245
2246 if (had_end)
2247 break;
2248 sb_reset (&line);
2249 more = get_line (&line);
2250 }
2251
2252 if (!had_end && !mri)
2253 WARNING ((stderr, "END missing from end of file.\n"));
2254 }
2255
2256
2257
2258
2259
2260 static void
2261 free_old_entry (ptr)
2262 hash_entry *ptr;
2263 {
2264 if (ptr)
2265 {
2266 if (ptr->type == hash_string)
2267 sb_kill(&ptr->value.s);
2268 }
2269 }
2270
2271 /* name: .ASSIGNA <value> */
2272
2273 static void
2274 do_assigna (idx, in)
2275 int idx;
2276 sb *in;
2277 {
2278 sb tmp;
2279 int val;
2280 sb_new (&tmp);
2281
2282 process_assigns (idx, in, &tmp);
2283 idx = exp_get_abs (".ASSIGNA needs constant expression argument.\n", 0, &tmp, &val);
2284
2285 if (!label.len)
2286 {
2287 ERROR ((stderr, ".ASSIGNA without label.\n"));
2288 }
2289 else
2290 {
2291 hash_entry *ptr = hash_create (&vars, &label);
2292 free_old_entry (ptr);
2293 ptr->type = hash_integer;
2294 ptr->value.i = val;
2295 }
2296 sb_kill (&tmp);
2297 }
2298
2299 /* name: .ASSIGNC <string> */
2300
2301 static void
2302 do_assignc (idx, in)
2303 int idx;
2304 sb *in;
2305 {
2306 sb acc;
2307 sb_new (&acc);
2308 idx = getstring (idx, in, &acc);
2309
2310 if (!label.len)
2311 {
2312 ERROR ((stderr, ".ASSIGNS without label.\n"));
2313 }
2314 else
2315 {
2316 hash_entry *ptr = hash_create (&vars, &label);
2317 free_old_entry (ptr);
2318 ptr->type = hash_string;
2319 sb_new (&ptr->value.s);
2320 sb_add_sb (&ptr->value.s, &acc);
2321 }
2322 sb_kill (&acc);
2323 }
2324
2325
2326 /* name: .REG (reg) */
2327
2328 static void
2329 do_reg (idx, in)
2330 int idx;
2331 sb *in;
2332 {
2333 /* remove reg stuff from inside parens */
2334 sb what;
2335 if (!mri)
2336 idx = skip_openp (idx, in);
2337 else
2338 idx = sb_skip_white (idx, in);
2339 sb_new (&what);
2340 while (idx < in->len
2341 && (mri
2342 ? ! eol (idx, in)
2343 : in->ptr[idx] != ')'))
2344 {
2345 sb_add_char (&what, in->ptr[idx]);
2346 idx++;
2347 }
2348 hash_add_to_string_table (&assign_hash_table, &label, &what, 1);
2349 sb_kill (&what);
2350 }
2351
2352
2353 static int
2354 condass_lookup_name (inbuf, idx, out, warn)
2355 sb *inbuf;
2356 int idx;
2357 sb *out;
2358 int warn;
2359 {
2360 hash_entry *ptr;
2361 sb condass_acc;
2362 sb_new (&condass_acc);
2363
2364 while (idx < inbuf->len
2365 && ISNEXTCHAR (inbuf->ptr[idx]))
2366 {
2367 sb_add_char (&condass_acc, inbuf->ptr[idx++]);
2368 }
2369
2370 if (inbuf->ptr[idx] == '\'')
2371 idx++;
2372 ptr = hash_lookup (&vars, &condass_acc);
2373
2374
2375 if (!ptr)
2376 {
2377 if (warn)
2378 {
2379 WARNING ((stderr, "Can't find preprocessor variable %s.\n", sb_name (&condass_acc)));
2380 }
2381 else
2382 {
2383 sb_add_string (out, "0");
2384 }
2385 }
2386 else
2387 {
2388 if (ptr->type == hash_integer)
2389 {
2390 char buffer[30];
2391 sprintf (buffer, "%d", ptr->value.i);
2392 sb_add_string (out, buffer);
2393 }
2394 else
2395 {
2396 sb_add_sb (out, &ptr->value.s);
2397 }
2398 }
2399 sb_kill (&condass_acc);
2400 return idx;
2401 }
2402
2403 #define EQ 1
2404 #define NE 2
2405 #define GE 3
2406 #define LT 4
2407 #define LE 5
2408 #define GT 6
2409 #define NEVER 7
2410
2411 static int
2412 whatcond (idx, in, val)
2413 int idx;
2414 sb *in;
2415 int *val;
2416 {
2417 int cond;
2418
2419 idx = sb_skip_white (idx, in);
2420 cond = NEVER;
2421 if (idx + 1 < in->len)
2422 {
2423 char *p;
2424 char a, b;
2425
2426 p = in->ptr + idx;
2427 a = toupper ((unsigned char) p[0]);
2428 b = toupper ((unsigned char) p[1]);
2429 if (a == 'E' && b == 'Q')
2430 cond = EQ;
2431 else if (a == 'N' && b == 'E')
2432 cond = NE;
2433 else if (a == 'L' && b == 'T')
2434 cond = LT;
2435 else if (a == 'L' && b == 'E')
2436 cond = LE;
2437 else if (a == 'G' && b == 'T')
2438 cond = GT;
2439 else if (a == 'G' && b == 'E')
2440 cond = GE;
2441 }
2442 if (cond == NEVER)
2443 {
2444 ERROR ((stderr, "Comparison operator must be one of EQ, NE, LT, LE, GT or GE.\n"));
2445 cond = NEVER;
2446 }
2447 idx = sb_skip_white (idx + 2, in);
2448 *val = cond;
2449 return idx;
2450 }
2451
2452 static int
2453 istrue (idx, in)
2454 int idx;
2455 sb *in;
2456 {
2457 int res;
2458 sb acc_a;
2459 sb cond;
2460 sb acc_b;
2461 sb_new (&acc_a);
2462 sb_new (&cond);
2463 sb_new (&acc_b);
2464 idx = sb_skip_white (idx, in);
2465
2466 if (in->ptr[idx] == '"')
2467 {
2468 int cond;
2469 int same;
2470 /* This is a string comparision */
2471 idx = getstring (idx, in, &acc_a);
2472 idx = whatcond (idx, in, &cond);
2473 idx = getstring (idx, in, &acc_b);
2474 same = acc_a.len == acc_b.len && (strncmp (acc_a.ptr, acc_b.ptr, acc_a.len) == 0);
2475
2476 if (cond != EQ && cond != NE)
2477 {
2478 ERROR ((stderr, "Comparison operator for strings must be EQ or NE\n"));
2479 res = 0;
2480 }
2481 else
2482 res = (cond != EQ) ^ same;
2483 }
2484 else
2485 /* This is a numeric expression */
2486 {
2487 int vala;
2488 int valb;
2489 int cond;
2490 idx = exp_get_abs ("Conditional operator must have absolute operands.\n", idx, in, &vala);
2491 idx = whatcond (idx, in, &cond);
2492 idx = sb_skip_white (idx, in);
2493 if (in->ptr[idx] == '"')
2494 {
2495 WARNING ((stderr, "String compared against expression.\n"));
2496 res = 0;
2497 }
2498 else
2499 {
2500 idx = exp_get_abs ("Conditional operator must have absolute operands.\n", idx, in, &valb);
2501 switch (cond)
2502 {
2503 default:
2504 res = 42;
2505 break;
2506 case EQ:
2507 res = vala == valb;
2508 break;
2509 case NE:
2510 res = vala != valb;
2511 break;
2512 case LT:
2513 res = vala < valb;
2514 break;
2515 case LE:
2516 res = vala <= valb;
2517 break;
2518 case GT:
2519 res = vala > valb;
2520 break;
2521 case GE:
2522 res = vala >= valb;
2523 break;
2524 case NEVER:
2525 res = 0;
2526 break;
2527 }
2528 }
2529 }
2530
2531 sb_kill (&acc_a);
2532 sb_kill (&cond);
2533 sb_kill (&acc_b);
2534 return res;
2535 }
2536
2537 /* .AIF */
2538 static void
2539 do_aif (idx, in)
2540 int idx;
2541 sb *in;
2542 {
2543 if (ifi >= IFNESTING)
2544 {
2545 FATAL ((stderr, "AIF nesting unreasonable.\n"));
2546 }
2547 ifi++;
2548 ifstack[ifi].on = ifstack[ifi-1].on ? istrue (idx, in) : 0;
2549 ifstack[ifi].hadelse = 0;
2550 }
2551
2552
2553 /* .AELSE */
2554 static void
2555 do_aelse ()
2556 {
2557 ifstack[ifi].on = ifstack[ifi-1].on ? !ifstack[ifi].on : 0;
2558 if (ifstack[ifi].hadelse)
2559 {
2560 ERROR ((stderr, "Multiple AELSEs in AIF.\n"));
2561 }
2562 ifstack[ifi].hadelse = 1;
2563 }
2564
2565
2566 /* .AENDI */
2567 static void
2568 do_aendi ()
2569 {
2570 if (ifi != 0)
2571 {
2572 ifi--;
2573 }
2574 else
2575 {
2576 ERROR ((stderr, "AENDI without AIF.\n"));
2577 }
2578 }
2579
2580 static int
2581 condass_on ()
2582 {
2583 return ifstack[ifi].on;
2584 }
2585
2586 /* MRI IFEQ, IFNE, IFLT, IFLE, IFGE, IFGT. */
2587
2588 static void
2589 do_if (idx, in, cond)
2590 int idx;
2591 sb *in;
2592 int cond;
2593 {
2594 int val;
2595 int res;
2596
2597 if (ifi >= IFNESTING)
2598 {
2599 FATAL ((stderr, "IF nesting unreasonable.\n"));
2600 }
2601
2602 idx = exp_get_abs ("Conditional operator must have absolute operands.\n",
2603 idx, in, &val);
2604 switch (cond)
2605 {
2606 default:
2607 case EQ: res = val == 0; break;
2608 case NE: res = val != 0; break;
2609 case LT: res = val < 0; break;
2610 case LE: res = val <= 0; break;
2611 case GE: res = val >= 0; break;
2612 case GT: res = val > 0; break;
2613 }
2614
2615 ifi++;
2616 ifstack[ifi].on = ifstack[ifi-1].on ? res: 0;
2617 ifstack[ifi].hadelse = 0;
2618 }
2619
2620 /* Get a string for the MRI IFC or IFNC pseudo-ops. */
2621
2622 static int
2623 get_mri_string (idx, in, val, terminator)
2624 int idx;
2625 sb *in;
2626 sb *val;
2627 int terminator;
2628 {
2629 idx = sb_skip_white (idx, in);
2630
2631 if (idx < in->len
2632 && in->ptr[idx] == '\'')
2633 {
2634 sb_add_char (val, '\'');
2635 for (++idx; idx < in->len; ++idx)
2636 {
2637 sb_add_char (val, in->ptr[idx]);
2638 if (in->ptr[idx] == '\'')
2639 {
2640 ++idx;
2641 if (idx >= in->len
2642 || in->ptr[idx] != '\'')
2643 break;
2644 }
2645 }
2646 idx = sb_skip_white (idx, in);
2647 }
2648 else
2649 {
2650 int i;
2651
2652 while (idx < in->len
2653 && in->ptr[idx] != terminator)
2654 {
2655 sb_add_char (val, in->ptr[idx]);
2656 ++idx;
2657 }
2658 i = val->len - 1;
2659 while (i >= 0 && ISWHITE (val->ptr[i]))
2660 --i;
2661 val->len = i + 1;
2662 }
2663
2664 return idx;
2665 }
2666
2667 /* MRI IFC, IFNC. */
2668
2669 static void
2670 do_ifc (idx, in, ifnc)
2671 int idx;
2672 sb *in;
2673 int ifnc;
2674 {
2675 sb first;
2676 sb second;
2677 int res;
2678
2679 if (ifi >= IFNESTING)
2680 {
2681 FATAL ((stderr, "IF nesting unreasonable.\n"));
2682 }
2683
2684 sb_new (&first);
2685 sb_new (&second);
2686
2687 idx = get_mri_string (idx, in, &first, ',');
2688
2689 if (idx >= in->len || in->ptr[idx] != ',')
2690 {
2691 ERROR ((stderr, "Bad format for IF or IFNC.\n"));
2692 return;
2693 }
2694
2695 idx = get_mri_string (idx + 1, in, &second, ';');
2696
2697 res = (first.len == second.len
2698 && strncmp (first.ptr, second.ptr, first.len) == 0);
2699 res ^= ifnc;
2700
2701 ifi++;
2702 ifstack[ifi].on = ifstack[ifi-1].on ? res : 0;
2703 ifstack[ifi].hadelse = 0;
2704 }
2705
2706 /* Read input lines till we get to a TO string.
2707 Increase nesting depth if we geta FROM string.
2708 Put the results into sb at PTR. */
2709
2710 static void
2711 buffer_and_nest (from, to, ptr)
2712 const char *from;
2713 const char *to;
2714 sb *ptr;
2715 {
2716 int from_len = strlen (from);
2717 int to_len = strlen (to);
2718 int depth = 1;
2719 int line_start = ptr->len;
2720 int line = linecount ();
2721
2722 int more = get_line (ptr);
2723
2724 while (more)
2725 {
2726 /* Try and find the first pseudo op on the line */
2727 int i = line_start;
2728
2729 if (!alternate && !mri)
2730 {
2731 /* With normal syntax we can suck what we want till we get
2732 to the dot. With the alternate, labels have to start in
2733 the first column, since we cant tell what's a label and
2734 whats a pseudoop */
2735
2736 /* Skip leading whitespace */
2737 while (i < ptr->len
2738 && ISWHITE (ptr->ptr[i]))
2739 i++;
2740
2741 /* Skip over a label */
2742 while (i < ptr->len
2743 && ISNEXTCHAR (ptr->ptr[i]))
2744 i++;
2745
2746 /* And a colon */
2747 if (i < ptr->len
2748 && ptr->ptr[i] == ':')
2749 i++;
2750
2751 }
2752 /* Skip trailing whitespace */
2753 while (i < ptr->len
2754 && ISWHITE (ptr->ptr[i]))
2755 i++;
2756
2757 if (i < ptr->len && (ptr->ptr[i] == '.'
2758 || alternate
2759 || mri))
2760 {
2761 if (ptr->ptr[i] == '.')
2762 i++;
2763 if (strncasecmp (ptr->ptr + i, from, from_len) == 0)
2764 depth++;
2765 if (strncasecmp (ptr->ptr + i, to, to_len) == 0)
2766 {
2767 depth--;
2768 if (depth == 0)
2769 {
2770 /* Reset the string to not include the ending rune */
2771 ptr->len = line_start;
2772 break;
2773 }
2774 }
2775 }
2776
2777 /* Add a CR to the end and keep running */
2778 sb_add_char (ptr, '\n');
2779 line_start = ptr->len;
2780 more = get_line (ptr);
2781 }
2782
2783
2784 if (depth)
2785 FATAL ((stderr, "End of file whilst inside %s, started on line %d.\n", from, line));
2786 }
2787
2788
2789 /* .ENDR */
2790 static void
2791 do_aendr ()
2792 {
2793 if (!mri)
2794 ERROR ((stderr, "AENDR without a AREPEAT.\n"));
2795 else
2796 ERROR ((stderr, "ENDR without a REPT.\n"));
2797 }
2798
2799 /* .AWHILE */
2800
2801 static
2802 void
2803 do_awhile (idx, in)
2804 int idx;
2805 sb *in;
2806 {
2807 sb exp;
2808
2809 sb sub;
2810
2811 int doit;
2812 sb_new (&sub);
2813 sb_new (&exp);
2814
2815 process_assigns (idx, in, &exp);
2816 doit = istrue (0, &exp);
2817
2818 buffer_and_nest ("AWHILE", "AENDW", &sub);
2819
2820 /* Turn
2821 .AWHILE exp
2822 foo
2823 .AENDW
2824 into
2825 foo
2826 .AWHILE exp
2827 foo
2828 .ENDW
2829 */
2830
2831 if (doit)
2832 {
2833 int index = include_next_index ();
2834
2835 sb copy;
2836 sb_new (&copy);
2837 sb_add_sb (&copy, &sub);
2838 sb_add_sb (&copy, in);
2839 sb_add_string (&copy, "\n");
2840 sb_add_sb (&copy, &sub);
2841 sb_add_string (&copy, "\t.AENDW\n");
2842 /* Push another WHILE */
2843 include_buf (&exp, &copy, include_while, index);
2844 sb_kill (&copy);
2845 }
2846 sb_kill (&exp);
2847 sb_kill (&sub);
2848 }
2849
2850
2851 /* .AENDW */
2852
2853 static void
2854 do_aendw ()
2855 {
2856 ERROR ((stderr, "AENDW without a AENDW.\n"));
2857 }
2858
2859
2860 /* .EXITM
2861
2862 Pop things off the include stack until the type and index changes */
2863
2864 static void
2865 do_exitm ()
2866 {
2867 include_type type = sp->type;
2868 if (type == include_repeat
2869 || type == include_while
2870 || type == include_macro)
2871 {
2872 int index = sp->index;
2873 include_pop ();
2874 while (sp->index == index
2875 && sp->type == type)
2876 {
2877 include_pop ();
2878 }
2879 }
2880 }
2881
2882 /* .AREPEAT */
2883
2884 static void
2885 do_arepeat (idx, in)
2886 int idx;
2887 sb *in;
2888 {
2889 sb exp; /* buffer with expression in it */
2890 sb copy; /* expanded repeat block */
2891 sb sub; /* contents of AREPEAT */
2892 int rc;
2893 char buffer[30];
2894 sb_new (&exp);
2895 sb_new (&copy);
2896 sb_new (&sub);
2897 process_assigns (idx, in, &exp);
2898 idx = exp_get_abs ("AREPEAT must have absolute operand.\n", 0, &exp, &rc);
2899 if (!mri)
2900 buffer_and_nest ("AREPEAT", "AENDR", &sub);
2901 else
2902 buffer_and_nest ("REPT", "ENDR", &sub);
2903 if (rc > 0)
2904 {
2905 /* Push back the text following the repeat, and another repeat block
2906 so
2907 .AREPEAT 20
2908 foo
2909 .AENDR
2910 gets turned into
2911 foo
2912 .AREPEAT 19
2913 foo
2914 .AENDR
2915 */
2916 int index = include_next_index ();
2917 sb_add_sb (&copy, &sub);
2918 if (rc > 1)
2919 {
2920 if (!mri)
2921 sprintf (buffer, "\t.AREPEAT %d\n", rc - 1);
2922 else
2923 sprintf (buffer, "\tREPT %d\n", rc - 1);
2924 sb_add_string (&copy, buffer);
2925 sb_add_sb (&copy, &sub);
2926 if (!mri)
2927 sb_add_string (&copy, " .AENDR\n");
2928 else
2929 sb_add_string (&copy, " ENDR\n");
2930 }
2931
2932 include_buf (&exp, &copy, include_repeat, index);
2933 }
2934 sb_kill (&exp);
2935 sb_kill (&sub);
2936 sb_kill (&copy);
2937 }
2938
2939 /* .ENDM */
2940
2941 static void
2942 do_endm ()
2943 {
2944 ERROR ((stderr, ".ENDM without a matching .MACRO.\n"));
2945 }
2946
2947 /* MRI IRP pseudo-op. */
2948
2949 static void
2950 do_irp (idx, in, irpc)
2951 int idx;
2952 sb *in;
2953 int irpc;
2954 {
2955 const char *mn;
2956 sb sub;
2957 formal_entry f;
2958 hash_table h;
2959 hash_entry *p;
2960 sb name;
2961 sb out;
2962
2963 if (irpc)
2964 mn = "IRPC";
2965 else
2966 mn = "IRP";
2967
2968 idx = sb_skip_white (idx, in);
2969
2970 sb_new (&sub);
2971 buffer_and_nest (mn, "ENDR", &sub);
2972
2973 sb_new (&f.name);
2974 sb_new (&f.def);
2975 sb_new (&f.actual);
2976
2977 idx = get_token (idx, in, &f.name);
2978 if (f.name.len == 0)
2979 {
2980 ERROR ((stderr, "Missing model parameter in %s", mn));
2981 return;
2982 }
2983
2984 hash_new_table (1, &h);
2985 p = hash_create (&h, &f.name);
2986 p->type = hash_formal;
2987 p->value.f = &f;
2988
2989 f.index = 1;
2990 f.next = NULL;
2991
2992 sb_new (&name);
2993 sb_add_string (&name, mn);
2994
2995 sb_new (&out);
2996
2997 idx = sb_skip_comma (idx, in);
2998 if (eol (idx, in))
2999 {
3000 /* Expand once with a null string. */
3001 macro_expand_body (&name, &sub, &out, &f, &h);
3002 fprintf (outfile, "%s", sb_name (&out));
3003 }
3004 else
3005 {
3006 while (!eol (idx, in))
3007 {
3008 if (!irpc)
3009 idx = get_any_string (idx, in, &f.actual, 1, 0);
3010 else
3011 {
3012 sb_reset (&f.actual);
3013 sb_add_char (&f.actual, in->ptr[idx]);
3014 ++idx;
3015 }
3016 sb_reset (&out);
3017 macro_expand_body (&name, &sub, &out, &f, &h);
3018 fprintf (outfile, "%s", sb_name (&out));
3019 if (!irpc)
3020 idx = sb_skip_comma (idx, in);
3021 else
3022 idx = sb_skip_white (idx, in);
3023 }
3024 }
3025
3026 sb_kill (&sub);
3027 sb_kill (&name);
3028 sb_kill (&out);
3029 }
3030
3031 /* MACRO PROCESSING */
3032
3033 static int number;
3034 hash_table macro_table;
3035
3036 /* Understand
3037
3038 .MACRO <name>
3039 stuff
3040 .ENDM
3041 */
3042
3043 static int
3044 do_formals (macro, idx, in)
3045 macro_entry *macro;
3046 int idx;
3047 sb *in;
3048 {
3049 formal_entry **p = &macro->formals;
3050 macro->formal_count = 0;
3051 hash_new_table (5, &macro->formal_hash);
3052 while (idx < in->len)
3053 {
3054 formal_entry *formal;
3055
3056 formal = (formal_entry *) xmalloc (sizeof (formal_entry));
3057
3058 sb_new (&formal->name);
3059 sb_new (&formal->def);
3060 sb_new (&formal->actual);
3061
3062 idx = sb_skip_white (idx, in);
3063 idx = get_token (idx, in, &formal->name);
3064 if (formal->name.len == 0)
3065 break;
3066 idx = sb_skip_white (idx, in);
3067 if (formal->name.len)
3068 {
3069 /* This is a formal */
3070 if (idx < in->len && in->ptr[idx] == '=')
3071 {
3072 /* Got a default */
3073 idx = get_any_string (idx + 1, in, &formal->def, 1, 0);
3074 }
3075 }
3076
3077 {
3078 /* Add to macro's hash table */
3079
3080 hash_entry *p = hash_create (&macro->formal_hash, &formal->name);
3081 p->type = hash_formal;
3082 p->value.f = formal;
3083 }
3084
3085 formal->index = macro->formal_count;
3086 idx = sb_skip_comma (idx, in);
3087 macro->formal_count++;
3088 *p = formal;
3089 p = &formal->next;
3090 *p = NULL;
3091 }
3092
3093 if (mri)
3094 {
3095 formal_entry *formal;
3096
3097 /* Add a special NARG formal, which macro_expand will set to the
3098 number of arguments. */
3099 formal = (formal_entry *) xmalloc (sizeof (formal_entry));
3100
3101 sb_new (&formal->name);
3102 sb_new (&formal->def);
3103 sb_new (&formal->actual);
3104
3105 sb_add_string (&formal->name, "NARG");
3106
3107 {
3108 /* Add to macro's hash table */
3109
3110 hash_entry *p = hash_create (&macro->formal_hash, &formal->name);
3111 p->type = hash_formal;
3112 p->value.f = formal;
3113 }
3114
3115 formal->index = -2;
3116 *p = formal;
3117 formal->next = NULL;
3118 }
3119
3120 return idx;
3121 }
3122
3123 /* Parse off LOCAL n1, n2,... Invent a label name for it */
3124 static
3125 void
3126 do_local (idx, line)
3127 int idx;
3128 sb *line;
3129 {
3130 static int ln;
3131 sb acc;
3132 sb sub;
3133 char subs[10];
3134 sb_new (&acc);
3135 sb_new (&sub);
3136 idx = sb_skip_white (idx, line);
3137 while (!eol(idx, line))
3138 {
3139 sb_reset (&acc);
3140 sb_reset (&sub);
3141 ln++;
3142 sprintf(subs, "LL%04x", ln);
3143 idx = get_token(idx, line, &acc);
3144 sb_add_string (&sub, subs);
3145 hash_add_to_string_table (&assign_hash_table, &acc, &sub, 1);
3146 idx = sb_skip_comma (idx, line);
3147 }
3148 sb_kill (&sub);
3149 sb_kill (&acc);
3150 }
3151
3152 static
3153 void
3154 do_macro (idx, in)
3155 int idx;
3156 sb *in;
3157 {
3158 macro_entry *macro;
3159 sb name;
3160
3161 macro = (macro_entry *) xmalloc (sizeof (macro_entry));
3162 sb_new (&macro->sub);
3163 sb_new (&name);
3164
3165 macro->formal_count = 0;
3166 macro->formals = 0;
3167
3168 idx = sb_skip_white (idx, in);
3169 buffer_and_nest ("MACRO", "ENDM", &macro->sub);
3170 if (label.len)
3171 {
3172
3173 sb_add_sb (&name, &label);
3174 if (in->ptr[idx] == '(')
3175 {
3176 /* It's the label: MACRO (formals,...) sort */
3177 idx = do_formals (macro, idx + 1, in);
3178 if (in->ptr[idx] != ')')
3179 ERROR ((stderr, "Missing ) after formals.\n"));
3180 }
3181 else {
3182 /* It's the label: MACRO formals,... sort */
3183 idx = do_formals (macro, idx, in);
3184 }
3185 }
3186 else
3187 {
3188 idx = get_token (idx, in, &name);
3189 idx = sb_skip_white (idx, in);
3190 idx = do_formals (macro, idx, in);
3191 }
3192
3193 /* and stick it in the macro hash table */
3194 hash_create (&macro_table, &name)->value.m = macro;
3195 }
3196
3197 static
3198 int
3199 get_token (idx, in, name)
3200 int idx;
3201 sb *in;
3202 sb *name;
3203 {
3204 if (idx < in->len
3205 && ISFIRSTCHAR (in->ptr[idx]))
3206 {
3207 sb_add_char (name, in->ptr[idx++]);
3208 while (idx < in->len
3209 && ISNEXTCHAR (in->ptr[idx]))
3210 {
3211 sb_add_char (name, in->ptr[idx++]);
3212 }
3213 }
3214 /* Ignore trailing & */
3215 if (alternate && idx < in->len && in->ptr[idx] == '&')
3216 idx++;
3217 return idx;
3218 }
3219
3220 /* Scan a token, but stop if a ' is seen */
3221 static int
3222 get_apost_token (idx, in, name, kind)
3223 int idx;
3224 sb *in;
3225 sb *name;
3226 int kind;
3227 {
3228 idx = get_token (idx, in, name);
3229 if (idx < in->len && in->ptr[idx] == kind)
3230 idx++;
3231 return idx;
3232 }
3233
3234 static int
3235 sub_actual (src, in, t, formal_hash, kind, out, copyifnotthere)
3236 int src;
3237 sb *in;
3238 sb *t;
3239 hash_table *formal_hash;
3240 int kind;
3241 sb *out;
3242 int copyifnotthere;
3243 {
3244 /* This is something to take care of */
3245 hash_entry *ptr;
3246 src = get_apost_token (src, in, t, kind);
3247 /* See if it's in the macro's hash table */
3248 ptr = hash_lookup (formal_hash, t);
3249 if (ptr)
3250 {
3251 if (ptr->value.f->actual.len)
3252 {
3253 sb_add_sb (out, &ptr->value.f->actual);
3254 }
3255 else
3256 {
3257 sb_add_sb (out, &ptr->value.f->def);
3258 }
3259 }
3260 else if (copyifnotthere)
3261 {
3262 sb_add_sb (out, t);
3263 }
3264 else
3265 {
3266 sb_add_char (out, '\\');
3267 sb_add_sb (out, t);
3268 }
3269 return src;
3270 }
3271
3272 /* Copy the body from the macro buffer into a safe place and
3273 substitute any args. */
3274
3275 static void
3276 macro_expand_body (name, in, out, formals, formal_hash)
3277 sb *name;
3278 sb *in;
3279 sb *out;
3280 formal_entry *formals;
3281 hash_table *formal_hash;
3282 {
3283 sb t;
3284 int src = 0;
3285 int inquote = 0;
3286
3287 sb_new (&t);
3288
3289 while (src < in->len)
3290 {
3291 if (in->ptr[src] == '&')
3292 {
3293 sb_reset (&t);
3294 if (mri && src + 1 < in->len && in->ptr[src + 1] == '&')
3295 {
3296 src = sub_actual (src + 2, in, &t, formal_hash, '\'', out, 1);
3297 }
3298 else
3299 {
3300 src = sub_actual (src + 1, in, &t, formal_hash, '&', out, 0);
3301 }
3302 }
3303 else if (in->ptr[src] == '\\')
3304 {
3305 src++;
3306 if (in->ptr[src] == comment_char)
3307 {
3308 /* This is a comment, just drop the rest of the line */
3309 while (src < in->len
3310 && in->ptr[src] != '\n')
3311 src++;
3312
3313 }
3314 else if (in->ptr[src] == '(')
3315 {
3316 /* Sub in till the next ')' literally */
3317 src++;
3318 while (src < in->len && in->ptr[src] != ')')
3319 {
3320 sb_add_char (out, in->ptr[src++]);
3321 }
3322 if (in->ptr[src] == ')')
3323 src++;
3324 else
3325 ERROR ((stderr, "Missplaced ).\n"));
3326 }
3327 else if (in->ptr[src] == '@')
3328 {
3329 /* Sub in the macro invocation number */
3330
3331 char buffer[6];
3332 src++;
3333 sprintf (buffer, "%05d", number);
3334 sb_add_string (out, buffer);
3335 }
3336 else if (in->ptr[src] == '&')
3337 {
3338 /* This is a preprocessor variable name, we don't do them
3339 here */
3340 sb_add_char (out, '\\');
3341 sb_add_char (out, '&');
3342 src++;
3343 }
3344 else if (mri
3345 && isalnum ((unsigned char) in->ptr[src]))
3346 {
3347 int ind;
3348 formal_entry *f;
3349
3350 if (isdigit ((unsigned char) in->ptr[src]))
3351 ind = in->ptr[src] - '0';
3352 else if (isupper ((unsigned char) in->ptr[src]))
3353 ind = in->ptr[src] - 'A' + 10;
3354 else
3355 ind = in->ptr[src] - 'a' + 10;
3356 ++src;
3357 for (f = formals; f != NULL; f = f->next)
3358 {
3359 if (f->index == ind - 1)
3360 {
3361 if (f->actual.len != 0)
3362 sb_add_sb (out, &f->actual);
3363 else
3364 sb_add_sb (out, &f->def);
3365 break;
3366 }
3367 }
3368 }
3369 else
3370 {
3371 sb_reset (&t);
3372 src = sub_actual (src, in, &t, formal_hash, '\'', out, 0);
3373 }
3374 }
3375 else if (ISFIRSTCHAR (in->ptr[src]) && (alternate || mri))
3376 {
3377 sb_reset (&t);
3378 src = sub_actual (src, in, &t, formal_hash, '\'', out, 1);
3379 }
3380 else if (ISCOMMENTCHAR (in->ptr[src])
3381 && src + 1 < in->len
3382 && ISCOMMENTCHAR (in->ptr[src+1])
3383 && !inquote)
3384 {
3385 /* Two comment chars in a row cause the rest of the line to
3386 be dropped. */
3387 while (src < in->len && in->ptr[src] != '\n')
3388 src++;
3389 }
3390 else if (in->ptr[src] == '"'
3391 || (mri && in->ptr[src] == '\''))
3392 {
3393 inquote = !inquote;
3394 sb_add_char (out, in->ptr[src++]);
3395 }
3396 else if (mri
3397 && in->ptr[src] == '='
3398 && src + 1 < in->len
3399 && in->ptr[src + 1] == '=')
3400 {
3401 hash_entry *ptr;
3402
3403 sb_reset (&t);
3404 src = get_token (src + 2, in, &t);
3405 ptr = hash_lookup (formal_hash, &t);
3406 if (ptr == NULL)
3407 {
3408 ERROR ((stderr, "MACRO formal argument %s does not exist.\n",
3409 sb_name (&t)));
3410 }
3411 else
3412 {
3413 if (ptr->value.f->actual.len)
3414 {
3415 sb_add_string (out, "-1");
3416 }
3417 else
3418 {
3419 sb_add_char (out, '0');
3420 }
3421 }
3422 }
3423 else
3424 {
3425 sb_add_char (out, in->ptr[src++]);
3426 }
3427 }
3428
3429 sb_kill (&t);
3430 }
3431
3432 static void
3433 macro_expand (name, idx, in, m)
3434 sb *name;
3435 int idx;
3436 sb *in;
3437 macro_entry *m;
3438 {
3439 sb t;
3440 sb out;
3441 hash_entry *ptr;
3442 formal_entry *f;
3443 int is_positional = 0;
3444 int is_keyword = 0;
3445 int narg = 0;
3446
3447 sb_new (&t);
3448 sb_new (&out);
3449
3450 /* Reset any old value the actuals may have */
3451 for (f = m->formals; f; f = f->next)
3452 sb_reset (&f->actual);
3453 f = m->formals;
3454
3455 if (mri)
3456 {
3457 /* The macro may be called with an optional qualifier, which may
3458 be referred to in the macro body as \0. */
3459 if (idx < in->len && in->ptr[idx] == '.')
3460 {
3461 formal_entry *n;
3462
3463 n = (formal_entry *) xmalloc (sizeof (formal_entry));
3464 sb_new (&n->name);
3465 sb_new (&n->def);
3466 sb_new (&n->actual);
3467 n->index = -1;
3468
3469 n->next = m->formals;
3470 m->formals = n;
3471
3472 idx = get_any_string (idx + 1, in, &n->actual, 1, 0);
3473 }
3474 }
3475
3476 /* Peel off the actuals and store them away in the hash tables' actuals */
3477 while (!eol(idx, in))
3478 {
3479 int scan;
3480 idx = sb_skip_white (idx, in);
3481 /* Look and see if it's a positional or keyword arg */
3482 scan = idx;
3483 while (scan < in->len
3484 && !ISSEP (in->ptr[scan])
3485 && (!alternate && in->ptr[scan] != '='))
3486 scan++;
3487 if (scan < in->len && (!alternate) && in->ptr[scan] == '=')
3488 {
3489 is_keyword = 1;
3490 if (is_positional)
3491 {
3492 ERROR ((stderr, "Can't mix positional and keyword arguments.\n"));
3493 return;
3494 }
3495 /* This is a keyword arg, fetch the formal name and
3496 then the actual stuff */
3497 sb_reset (&t);
3498 idx = get_token (idx, in, &t);
3499 if (in->ptr[idx] != '=')
3500 ERROR ((stderr, "confused about formal params.\n"));
3501
3502 /* Lookup the formal in the macro's list */
3503 ptr = hash_lookup (&m->formal_hash, &t);
3504 if (!ptr)
3505 {
3506 ERROR ((stderr, "MACRO formal argument %s does not exist.\n", sb_name (&t)));
3507 return;
3508 }
3509 else
3510 {
3511 /* Insert this value into the right place */
3512 sb_reset (&ptr->value.f->actual);
3513 idx = get_any_string (idx + 1, in, &ptr->value.f->actual, 0, 0);
3514 if (ptr->value.f->actual.len > 0)
3515 ++narg;
3516 }
3517 }
3518 else
3519 {
3520 /* This is a positional arg */
3521 is_positional = 1;
3522 if (is_keyword)
3523 {
3524 ERROR ((stderr, "Can't mix positional and keyword arguments.\n"));
3525 return;
3526 }
3527 if (!f)
3528 {
3529 formal_entry **pf;
3530 int c;
3531
3532 if (!mri)
3533 {
3534 ERROR ((stderr, "Too many positional arguments.\n"));
3535 return;
3536 }
3537 f = (formal_entry *) xmalloc (sizeof (formal_entry));
3538 sb_new (&f->name);
3539 sb_new (&f->def);
3540 sb_new (&f->actual);
3541 f->next = NULL;
3542
3543 c = -1;
3544 for (pf = &m->formals; *pf != NULL; pf = &(*pf)->next)
3545 if ((*pf)->index >= c)
3546 c = (*pf)->index + 1;
3547 *pf = f;
3548 f->index = c;
3549 }
3550
3551 sb_reset (&f->actual);
3552 idx = get_any_string (idx, in, &f->actual, 1, 0);
3553 if (f->actual.len > 0)
3554 ++narg;
3555 do
3556 {
3557 f = f->next;
3558 }
3559 while (f != NULL && f->index < 0);
3560 }
3561
3562 idx = sb_skip_comma (idx, in);
3563 }
3564
3565 if (mri)
3566 {
3567 char buffer[20];
3568
3569 sb_reset (&t);
3570 sb_add_string (&t, "NARG");
3571 ptr = hash_lookup (&m->formal_hash, &t);
3572 sb_reset (&ptr->value.f->actual);
3573 sprintf (buffer, "%d", narg);
3574 sb_add_string (&ptr->value.f->actual, buffer);
3575 }
3576
3577 macro_expand_body (name, &m->sub, &out, m->formals, &m->formal_hash);
3578
3579 include_buf (name, &out, include_macro, include_next_index ());
3580
3581 if (mri)
3582 {
3583 formal_entry **pf;
3584
3585 /* Discard any unnamed formal arguments. */
3586 pf = &m->formals;
3587 while (*pf != NULL)
3588 {
3589 if ((*pf)->name.len != 0)
3590 pf = &(*pf)->next;
3591 else
3592 {
3593 sb_kill (&(*pf)->name);
3594 sb_kill (&(*pf)->def);
3595 sb_kill (&(*pf)->actual);
3596 f = (*pf)->next;
3597 free (*pf);
3598 *pf = f;
3599 }
3600 }
3601 }
3602
3603 sb_kill (&t);
3604 sb_kill (&out);
3605 number++;
3606 }
3607
3608 static int
3609 macro_op (idx, in)
3610 int idx;
3611 sb *in;
3612 {
3613 int res = 0;
3614 /* The macro name must be the first thing on the line */
3615 if (idx < in->len)
3616 {
3617 sb name;
3618 hash_entry *ptr;
3619 sb_new (&name);
3620 idx = get_token (idx, in, &name);
3621
3622 if (name.len)
3623 {
3624 /* Got a name, look it up */
3625
3626 ptr = hash_lookup (&macro_table, &name);
3627
3628 if (ptr)
3629 {
3630 /* It's in the table, copy out the stuff and convert any macro args */
3631 macro_expand (&name, idx, in, ptr->value.m);
3632 res = 1;
3633 }
3634 }
3635 sb_kill (&name);
3636 }
3637
3638
3639 return res;
3640 }
3641
3642
3643 /* STRING HANDLING */
3644
3645 static int
3646 getstring (idx, in, acc)
3647 int idx;
3648 sb *in;
3649 sb *acc;
3650 {
3651 idx = sb_skip_white (idx, in);
3652
3653 while (idx < in->len
3654 && (in->ptr[idx] == '"'
3655 || in->ptr[idx] == '<'
3656 || (in->ptr[idx] == '\'' && alternate)))
3657 {
3658 if (in->ptr[idx] == '<')
3659 {
3660 if (alternate || mri)
3661 {
3662 int nest = 0;
3663 idx++;
3664 while ((in->ptr[idx] != '>' || nest)
3665 && idx < in->len)
3666 {
3667 if (in->ptr[idx] == '!')
3668 {
3669 idx++ ;
3670 sb_add_char (acc, in->ptr[idx++]);
3671 }
3672 else {
3673 if (in->ptr[idx] == '>')
3674 nest--;
3675 if (in->ptr[idx] == '<')
3676 nest++;
3677 sb_add_char (acc, in->ptr[idx++]);
3678 }
3679 }
3680 idx++;
3681 }
3682 else {
3683 int code;
3684 idx++;
3685 idx = exp_get_abs ("Character code in string must be absolute expression.\n",
3686 idx, in, &code);
3687 sb_add_char (acc, code);
3688
3689 if (in->ptr[idx] != '>')
3690 ERROR ((stderr, "Missing > for character code.\n"));
3691 idx++;
3692 }
3693 }
3694 else if (in->ptr[idx] == '"' || in->ptr[idx] == '\'')
3695 {
3696 char tchar = in->ptr[idx];
3697 idx++;
3698 while (idx < in->len)
3699 {
3700 if (alternate && in->ptr[idx] == '!')
3701 {
3702 idx++ ;
3703 sb_add_char (acc, in->ptr[idx++]);
3704 }
3705 else {
3706 if (in->ptr[idx] == tchar)
3707 {
3708 idx++;
3709 if (idx >= in->len || in->ptr[idx] != tchar)
3710 break;
3711 }
3712 sb_add_char (acc, in->ptr[idx]);
3713 idx++;
3714 }
3715 }
3716 }
3717 }
3718
3719 return idx;
3720 }
3721
3722 /* .SDATA[C|Z] <string> */
3723
3724 static
3725 void
3726 do_sdata (idx, in, type)
3727 int idx;
3728 sb *in;
3729 int type;
3730 {
3731 int nc = 0;
3732 int pidx = -1;
3733 sb acc;
3734 sb_new (&acc);
3735 fprintf (outfile, ".byte\t");
3736
3737 while (!eol (idx, in))
3738 {
3739 int i;
3740 sb_reset (&acc);
3741 idx = sb_skip_white (idx, in);
3742 while (!eol (idx, in))
3743 {
3744 pidx = idx = get_any_string (idx, in, &acc, 0, 1);
3745 if (type == 'c')
3746 {
3747 if (acc.len > 255)
3748 {
3749 ERROR ((stderr, "string for SDATAC longer than 255 characters (%d).\n", acc.len));
3750 }
3751 fprintf (outfile, "%d", acc.len);
3752 nc = 1;
3753 }
3754
3755 for (i = 0; i < acc.len; i++)
3756 {
3757 if (nc)
3758 {
3759 fprintf (outfile, ",");
3760 }
3761 fprintf (outfile, "%d", acc.ptr[i]);
3762 nc = 1;
3763 }
3764
3765 if (type == 'z')
3766 {
3767 if (nc)
3768 fprintf (outfile, ",");
3769 fprintf (outfile, "0");
3770 }
3771 idx = sb_skip_comma (idx, in);
3772 if (idx == pidx) break;
3773 }
3774 if (!alternate && in->ptr[idx] != ',' && idx != in->len)
3775 {
3776 fprintf (outfile, "\n");
3777 ERROR ((stderr, "illegal character in SDATA line (0x%x).\n", in->ptr[idx]));
3778 break;
3779 }
3780 idx++;
3781 }
3782 sb_kill (&acc);
3783 fprintf (outfile, "\n");
3784 }
3785
3786 /* .SDATAB <count> <string> */
3787
3788 static void
3789 do_sdatab (idx, in)
3790 int idx;
3791 sb *in;
3792 {
3793 int repeat;
3794 int i;
3795 sb acc;
3796 sb_new (&acc);
3797
3798 idx = exp_get_abs ("Must have absolute SDATAB repeat count.\n", idx, in, &repeat);
3799 if (repeat <= 0)
3800 {
3801 ERROR ((stderr, "Must have positive SDATAB repeat count (%d).\n", repeat));
3802 repeat = 1;
3803 }
3804
3805 idx = sb_skip_comma (idx, in);
3806 idx = getstring (idx, in, &acc);
3807
3808 for (i = 0; i < repeat; i++)
3809 {
3810 if (i)
3811 fprintf (outfile, "\t");
3812 fprintf (outfile, ".byte\t");
3813 sb_print (&acc);
3814 fprintf (outfile, "\n");
3815 }
3816 sb_kill (&acc);
3817
3818 }
3819
3820 static int
3821 new_file (name)
3822 const char *name;
3823 {
3824 FILE *newone = fopen (name, "r");
3825 if (!newone)
3826 return 0;
3827
3828 if (isp == MAX_INCLUDES)
3829 FATAL ((stderr, "Unreasonable include depth (%ld).\n", (long) isp));
3830
3831 sp++;
3832 sp->handle = newone;
3833
3834 sb_new (&sp->name);
3835 sb_add_string (&sp->name, name);
3836
3837 sp->linecount = 1;
3838 sp->pushback_index = 0;
3839 sp->type = include_file;
3840 sp->index = 0;
3841 sb_new (&sp->pushback);
3842 return 1;
3843 }
3844
3845 static void
3846 do_include (idx, in)
3847 int idx;
3848 sb *in;
3849 {
3850 sb t;
3851 sb cat;
3852 include_path *includes;
3853
3854 sb_new (&t);
3855 sb_new (&cat);
3856
3857 if (! mri)
3858 idx = getstring (idx, in, &t);
3859 else
3860 {
3861 idx = sb_skip_white (idx, in);
3862 while (idx < in->len && ! ISWHITE (in->ptr[idx]))
3863 {
3864 sb_add_char (&t, in->ptr[idx]);
3865 ++idx;
3866 }
3867 }
3868
3869 for (includes = paths_head; includes; includes = includes->next)
3870 {
3871 sb_reset (&cat);
3872 sb_add_sb (&cat, &includes->path);
3873 sb_add_char (&cat, '/');
3874 sb_add_sb (&cat, &t);
3875 if (new_file (sb_name (&cat)))
3876 {
3877 break;
3878 }
3879 }
3880 if (!includes)
3881 {
3882 if (! new_file (sb_name (&t)))
3883 FATAL ((stderr, "Can't open include file `%s'.\n", sb_name (&t)));
3884 }
3885 sb_kill (&cat);
3886 sb_kill (&t);
3887 }
3888
3889 static void
3890 include_pop ()
3891 {
3892 if (sp != include_stack)
3893 {
3894 if (sp->handle)
3895 fclose (sp->handle);
3896 sp--;
3897 }
3898 }
3899
3900 /* Get the next character from the include stack. If there's anything
3901 in the pushback buffer, take that first. If we're at eof, pop from
3902 the stack and try again. Keep the linecount up to date. */
3903
3904 static int
3905 get ()
3906 {
3907 int r;
3908
3909 if (sp->pushback.len != sp->pushback_index)
3910 {
3911 r = (char) (sp->pushback.ptr[sp->pushback_index++]);
3912 /* When they've all gone, reset the pointer */
3913 if (sp->pushback_index == sp->pushback.len)
3914 {
3915 sp->pushback.len = 0;
3916 sp->pushback_index = 0;
3917 }
3918 }
3919 else if (sp->handle)
3920 {
3921 r = getc (sp->handle);
3922 }
3923 else
3924 r = EOF;
3925
3926 if (r == EOF && isp)
3927 {
3928 include_pop ();
3929 r = get ();
3930 while (r == EOF && isp)
3931 {
3932 include_pop ();
3933 r = get ();
3934 }
3935 return r;
3936 }
3937 if (r == '\n')
3938 {
3939 sp->linecount++;
3940 }
3941
3942 return r;
3943 }
3944
3945 static int
3946 linecount ()
3947 {
3948 return sp->linecount;
3949 }
3950
3951 static int
3952 include_next_index ()
3953 {
3954 static int index;
3955 if (!unreasonable
3956 && index > MAX_REASONABLE)
3957 FATAL ((stderr, "Unreasonable expansion (-u turns off check).\n"));
3958 return ++index;
3959 }
3960
3961
3962 /* Initialize the chartype vector. */
3963
3964 static void
3965 chartype_init ()
3966 {
3967 int x;
3968 for (x = 0; x < 256; x++)
3969 {
3970 if (isalpha (x) || x == '_' || x == '$')
3971 chartype[x] |= FIRSTBIT;
3972
3973 if (mri && x == '.')
3974 chartype[x] |= FIRSTBIT;
3975
3976 if (isdigit (x) || isalpha (x) || x == '_' || x == '$')
3977 chartype[x] |= NEXTBIT;
3978
3979 if (x == ' ' || x == '\t' || x == ',' || x == '"' || x == ';'
3980 || x == '"' || x == '<' || x == '>' || x == ')' || x == '(')
3981 chartype[x] |= SEPBIT;
3982
3983 if (x == 'b' || x == 'B'
3984 || x == 'q' || x == 'Q'
3985 || x == 'h' || x == 'H'
3986 || x == 'd' || x == 'D')
3987 chartype [x] |= BASEBIT;
3988
3989 if (x == ' ' || x == '\t')
3990 chartype[x] |= WHITEBIT;
3991
3992 if (x == comment_char)
3993 chartype[x] |= COMMENTBIT;
3994 }
3995 }
3996
3997
3998
3999 /* What to do with all the keywords */
4000 #define PROCESS 0x1000 /* Run substitution over the line */
4001 #define LAB 0x2000 /* Spit out the label */
4002
4003 #define K_EQU (PROCESS|1)
4004 #define K_ASSIGN (PROCESS|2)
4005 #define K_REG (PROCESS|3)
4006 #define K_ORG (PROCESS|4)
4007 #define K_RADIX (PROCESS|5)
4008 #define K_DATA (LAB|PROCESS|6)
4009 #define K_DATAB (LAB|PROCESS|7)
4010 #define K_SDATA (LAB|PROCESS|8)
4011 #define K_SDATAB (LAB|PROCESS|9)
4012 #define K_SDATAC (LAB|PROCESS|10)
4013 #define K_SDATAZ (LAB|PROCESS|11)
4014 #define K_RES (LAB|PROCESS|12)
4015 #define K_SRES (LAB|PROCESS|13)
4016 #define K_SRESC (LAB|PROCESS|14)
4017 #define K_SRESZ (LAB|PROCESS|15)
4018 #define K_EXPORT (LAB|PROCESS|16)
4019 #define K_GLOBAL (LAB|PROCESS|17)
4020 #define K_PRINT (LAB|PROCESS|19)
4021 #define K_FORM (LAB|PROCESS|20)
4022 #define K_HEADING (LAB|PROCESS|21)
4023 #define K_PAGE (LAB|PROCESS|22)
4024 #define K_IMPORT (LAB|PROCESS|23)
4025 #define K_PROGRAM (LAB|PROCESS|24)
4026 #define K_END (PROCESS|25)
4027 #define K_INCLUDE (PROCESS|26)
4028 #define K_IGNORED (PROCESS|27)
4029 #define K_ASSIGNA (PROCESS|28)
4030 #define K_ASSIGNC (29)
4031 #define K_AIF (PROCESS|30)
4032 #define K_AELSE (PROCESS|31)
4033 #define K_AENDI (PROCESS|32)
4034 #define K_AREPEAT (PROCESS|33)
4035 #define K_AENDR (PROCESS|34)
4036 #define K_AWHILE (35)
4037 #define K_AENDW (PROCESS|36)
4038 #define K_EXITM (37)
4039 #define K_MACRO (PROCESS|38)
4040 #define K_ENDM (39)
4041 #define K_ALIGN (PROCESS|LAB|40)
4042 #define K_ALTERNATE (41)
4043 #define K_DB (LAB|PROCESS|42)
4044 #define K_DW (LAB|PROCESS|43)
4045 #define K_DL (LAB|PROCESS|44)
4046 #define K_LOCAL (45)
4047 #define K_IFEQ (PROCESS|46)
4048 #define K_IFNE (PROCESS|47)
4049 #define K_IFLT (PROCESS|48)
4050 #define K_IFLE (PROCESS|49)
4051 #define K_IFGE (PROCESS|50)
4052 #define K_IFGT (PROCESS|51)
4053 #define K_IFC (PROCESS|52)
4054 #define K_IFNC (PROCESS|53)
4055 #define K_IRP (PROCESS|54)
4056 #define K_IRPC (PROCESS|55)
4057
4058
4059 struct keyword
4060 {
4061 char *name;
4062 int code;
4063 int extra;
4064 };
4065
4066 static struct keyword kinfo[] =
4067 {
4068 { "EQU", K_EQU, 0 },
4069 { "ALTERNATE", K_ALTERNATE, 0 },
4070 { "ASSIGN", K_ASSIGN, 0 },
4071 { "REG", K_REG, 0 },
4072 { "ORG", K_ORG, 0 },
4073 { "RADIX", K_RADIX, 0 },
4074 { "DATA", K_DATA, 0 },
4075 { "DB", K_DB, 0 },
4076 { "DW", K_DW, 0 },
4077 { "DL", K_DL, 0 },
4078 { "DATAB", K_DATAB, 0 },
4079 { "SDATA", K_SDATA, 0 },
4080 { "SDATAB", K_SDATAB, 0 },
4081 { "SDATAZ", K_SDATAZ, 0 },
4082 { "SDATAC", K_SDATAC, 0 },
4083 { "RES", K_RES, 0 },
4084 { "SRES", K_SRES, 0 },
4085 { "SRESC", K_SRESC, 0 },
4086 { "SRESZ", K_SRESZ, 0 },
4087 { "EXPORT", K_EXPORT, 0 },
4088 { "GLOBAL", K_GLOBAL, 0 },
4089 { "PRINT", K_PRINT, 0 },
4090 { "FORM", K_FORM, 0 },
4091 { "HEADING", K_HEADING, 0 },
4092 { "PAGE", K_PAGE, 0 },
4093 { "PROGRAM", K_IGNORED, 0 },
4094 { "END", K_END, 0 },
4095 { "INCLUDE", K_INCLUDE, 0 },
4096 { "ASSIGNA", K_ASSIGNA, 0 },
4097 { "ASSIGNC", K_ASSIGNC, 0 },
4098 { "AIF", K_AIF, 0 },
4099 { "AELSE", K_AELSE, 0 },
4100 { "AENDI", K_AENDI, 0 },
4101 { "AREPEAT", K_AREPEAT, 0 },
4102 { "AENDR", K_AENDR, 0 },
4103 { "EXITM", K_EXITM, 0 },
4104 { "MACRO", K_MACRO, 0 },
4105 { "ENDM", K_ENDM, 0 },
4106 { "AWHILE", K_AWHILE, 0 },
4107 { "ALIGN", K_ALIGN, 0 },
4108 { "AENDW", K_AENDW, 0 },
4109 { "ALTERNATE", K_ALTERNATE, 0 },
4110 { "LOCAL", K_LOCAL, 0 },
4111 { NULL, 0, 0 }
4112 };
4113
4114 /* Although the conditional operators are handled by gas, we need to
4115 handle them here as well, in case they are used in a recursive
4116 macro to end the recursion. */
4117
4118 static struct keyword mrikinfo[] =
4119 {
4120 { "IFEQ", K_IFEQ, 0 },
4121 { "IFNE", K_IFNE, 0 },
4122 { "IFLT", K_IFLT, 0 },
4123 { "IFLE", K_IFLE, 0 },
4124 { "IFGE", K_IFGE, 0 },
4125 { "IFGT", K_IFGT, 0 },
4126 { "IFC", K_IFC, 0 },
4127 { "IFNC", K_IFNC, 0 },
4128 { "ELSEC", K_AELSE, 0 },
4129 { "ENDC", K_AENDI, 0 },
4130 { "MEXIT", K_EXITM, 0 },
4131 { "REPT", K_AREPEAT, 0 },
4132 { "IRP", K_IRP, 0 },
4133 { "IRPC", K_IRPC, 0 },
4134 { "ENDR", K_AENDR, 0 },
4135 { NULL, 0, 0 }
4136 };
4137
4138 /* Look for a pseudo op on the line. If one's there then call
4139 its handler. */
4140
4141 static int
4142 process_pseudo_op (idx, line, acc)
4143 int idx;
4144 sb *line;
4145 sb *acc;
4146 {
4147 int oidx = idx;
4148
4149 if (line->ptr[idx] == '.' || alternate || mri)
4150 {
4151 /* Scan forward and find pseudo name */
4152 char *in;
4153 hash_entry *ptr;
4154
4155 char *s;
4156 char *e;
4157 if (line->ptr[idx] == '.')
4158 idx++;
4159 in = line->ptr + idx;
4160 s = in;
4161 e = s;
4162 sb_reset (acc);
4163
4164 while (idx < line->len && *e && ISFIRSTCHAR (*e))
4165 {
4166 sb_add_char (acc, *e);
4167 e++;
4168 idx++;
4169 }
4170
4171 ptr = hash_lookup (&keyword_hash_table, acc);
4172
4173 if (!ptr)
4174 {
4175 #if 0
4176 /* This one causes lots of pain when trying to preprocess
4177 ordinary code */
4178 WARNING ((stderr, "Unrecognised pseudo op `%s'.\n", sb_name (acc)));
4179 #endif
4180 return 0;
4181 }
4182 if (ptr->value.i & LAB)
4183 { /* output the label */
4184 if (label.len)
4185 {
4186 fprintf (outfile, "%s:\t", sb_name (&label));
4187 }
4188 else
4189 fprintf (outfile, "\t");
4190 }
4191
4192 if (mri && ptr->value.i == K_END)
4193 {
4194 sb t;
4195
4196 sb_new (&t);
4197 sb_add_buffer (&t, line->ptr + oidx, idx - oidx);
4198 fprintf (outfile, "\t%s", sb_name (&t));
4199 sb_kill (&t);
4200 }
4201
4202 if (ptr->value.i & PROCESS)
4203 {
4204 /* Polish the rest of the line before handling the pseudo op */
4205 #if 0
4206 strip_comments(line);
4207 #endif
4208 sb_reset (acc);
4209 process_assigns (idx, line, acc);
4210 sb_reset(line);
4211 change_base (0, acc, line);
4212 idx = 0;
4213 }
4214 if (!condass_on ())
4215 {
4216 switch (ptr->value.i)
4217 {
4218 case K_AIF:
4219 do_aif (idx, line);
4220 break;
4221 case K_AELSE:
4222 do_aelse ();
4223 break;
4224 case K_AENDI:
4225 do_aendi ();
4226 break;
4227 }
4228 return 1;
4229 }
4230 else
4231 {
4232 switch (ptr->value.i)
4233 {
4234 case K_ALTERNATE:
4235 alternate = 1;
4236 return 1;
4237 case K_AELSE:
4238 do_aelse ();
4239 return 1;
4240 case K_AENDI:
4241 do_aendi ();
4242 return 1;
4243 case K_ORG:
4244 ERROR ((stderr, "ORG command not allowed.\n"));
4245 break;
4246 case K_RADIX:
4247 do_radix (line);
4248 return 1;
4249 case K_DB:
4250 do_data (idx, line, 1);
4251 return 1;
4252 case K_DW:
4253 do_data (idx, line, 2);
4254 return 1;
4255 case K_DL:
4256 do_data (idx, line, 4);
4257 return 1;
4258 case K_DATA:
4259 do_data (idx, line, 0);
4260 return 1;
4261 case K_DATAB:
4262 do_datab (idx, line);
4263 return 1;
4264 case K_SDATA:
4265 do_sdata (idx, line, 0);
4266 return 1;
4267 case K_SDATAB:
4268 do_sdatab (idx, line);
4269 return 1;
4270 case K_SDATAC:
4271 do_sdata (idx, line, 'c');
4272 return 1;
4273 case K_SDATAZ:
4274 do_sdata (idx, line, 'z');
4275 return 1;
4276 case K_ASSIGN:
4277 do_assign (1, 0, line);
4278 return 1;
4279 case K_AIF:
4280 do_aif (idx, line);
4281 return 1;
4282 case K_AREPEAT:
4283 do_arepeat (idx, line);
4284 return 1;
4285 case K_AENDW:
4286 do_aendw ();
4287 return 1;
4288 case K_AWHILE:
4289 do_awhile (idx, line);
4290 return 1;
4291 case K_AENDR:
4292 do_aendr ();
4293 return 1;
4294 case K_EQU:
4295 do_assign (0, idx, line);
4296 return 1;
4297 case K_ALIGN:
4298 do_align (idx, line);
4299 return 1;
4300 case K_RES:
4301 do_res (idx, line, 0);
4302 return 1;
4303 case K_SRES:
4304 do_res (idx, line, 's');
4305 return 1;
4306 case K_INCLUDE:
4307 do_include (idx, line);
4308 return 1;
4309 case K_LOCAL:
4310 do_local (idx, line);
4311 return 1;
4312 case K_MACRO:
4313 do_macro (idx, line);
4314 return 1;
4315 case K_ENDM:
4316 do_endm ();
4317 return 1;
4318 case K_SRESC:
4319 do_res (idx, line, 'c');
4320 return 1;
4321 case K_PRINT:
4322 do_print (idx, line);
4323 return 1;
4324 case K_FORM:
4325 do_form (idx, line);
4326 return 1;
4327 case K_HEADING:
4328 do_heading (idx, line);
4329 return 1;
4330 case K_PAGE:
4331 do_page ();
4332 return 1;
4333 case K_GLOBAL:
4334 case K_EXPORT:
4335 do_export (line);
4336 return 1;
4337 case K_IMPORT:
4338 return 1;
4339 case K_SRESZ:
4340 do_res (idx, line, 'z');
4341 return 1;
4342 case K_IGNORED:
4343 return 1;
4344 case K_END:
4345 do_end (line);
4346 return 1;
4347 case K_ASSIGNA:
4348 do_assigna (idx, line);
4349 return 1;
4350 case K_ASSIGNC:
4351 do_assignc (idx, line);
4352 return 1;
4353 case K_EXITM:
4354 do_exitm ();
4355 return 1;
4356 case K_REG:
4357 do_reg (idx, line);
4358 return 1;
4359 case K_IFEQ:
4360 do_if (idx, line, EQ);
4361 return 1;
4362 case K_IFNE:
4363 do_if (idx, line, NE);
4364 return 1;
4365 case K_IFLT:
4366 do_if (idx, line, LT);
4367 return 1;
4368 case K_IFLE:
4369 do_if (idx, line, LE);
4370 return 1;
4371 case K_IFGE:
4372 do_if (idx, line, GE);
4373 return 1;
4374 case K_IFGT:
4375 do_if (idx, line, GT);
4376 return 1;
4377 case K_IFC:
4378 do_ifc (idx, line, 0);
4379 return 1;
4380 case K_IFNC:
4381 do_ifc (idx, line, 1);
4382 return 1;
4383 case K_IRP:
4384 do_irp (idx, line, 0);
4385 return 1;
4386 case K_IRPC:
4387 do_irp (idx, line, 1);
4388 return 1;
4389 }
4390 }
4391 }
4392 return 0;
4393 }
4394
4395
4396
4397 /* Add a keyword to the hash table. */
4398
4399 static void
4400 add_keyword (name, code)
4401 const char *name;
4402 int code;
4403 {
4404 sb label;
4405 int j;
4406
4407 sb_new (&label);
4408 sb_add_string (&label, name);
4409
4410 hash_add_to_int_table (&keyword_hash_table, &label, code);
4411
4412 sb_reset (&label);
4413 for (j = 0; name[j]; j++)
4414 sb_add_char (&label, name[j] - 'A' + 'a');
4415 hash_add_to_int_table (&keyword_hash_table, &label, code);
4416
4417 sb_kill (&label);
4418 }
4419
4420 /* Build the keyword hash table - put each keyword in the table twice,
4421 once upper and once lower case.*/
4422
4423 static void
4424 process_init ()
4425 {
4426 int i;
4427
4428 for (i = 0; kinfo[i].name; i++)
4429 add_keyword (kinfo[i].name, kinfo[i].code);
4430
4431 if (mri)
4432 {
4433 for (i = 0; mrikinfo[i].name; i++)
4434 add_keyword (mrikinfo[i].name, mrikinfo[i].code);
4435 }
4436 }
4437
4438
4439 static void
4440 do_define (string)
4441 const char *string;
4442 {
4443 sb label;
4444 int res = 1;
4445 hash_entry *ptr;
4446 sb_new (&label);
4447
4448
4449 while (*string)
4450 {
4451 if (*string == '=')
4452 {
4453 sb value;
4454 sb_new (&value);
4455 string++;
4456 while (*string)
4457 {
4458 sb_add_char (&value, *string);
4459 string++;
4460 }
4461 exp_get_abs ("Invalid expression on command line.\n", 0, &value, &res);
4462 sb_kill (&value);
4463 break;
4464 }
4465 sb_add_char (&label, *string);
4466
4467 string ++;
4468 }
4469
4470 ptr = hash_create (&vars, &label);
4471 free_old_entry (ptr);
4472 ptr->type = hash_integer;
4473 ptr->value.i = res;
4474 sb_kill (&label);
4475 }
4476 char *program_name;
4477
4478 /* The list of long options. */
4479 static struct option long_options[] =
4480 {
4481 { "alternate", no_argument, 0, 'a' },
4482 { "include", required_argument, 0, 'I' },
4483 { "commentchar", required_argument, 0, 'c' },
4484 { "copysource", no_argument, 0, 's' },
4485 { "debug", no_argument, 0, 'd' },
4486 { "help", no_argument, 0, 'h' },
4487 { "mri", no_argument, 0, 'M' },
4488 { "output", required_argument, 0, 'o' },
4489 { "print", no_argument, 0, 'p' },
4490 { "unreasonable", no_argument, 0, 'u' },
4491 { "version", no_argument, 0, 'v' },
4492 { "define", required_argument, 0, 'd' },
4493 { NULL, no_argument, 0, 0 }
4494 };
4495
4496 /* Show a usage message and exit. */
4497 static void
4498 show_usage (file, status)
4499 FILE *file;
4500 int status;
4501 {
4502 fprintf (file, "\
4503 Usage: %s \n\
4504 [-a] [--alternate] enter alternate macro mode\n\
4505 [-c char] [--commentchar char] change the comment character from !\n\
4506 [-d] [--debug] print some debugging info\n\
4507 [-h] [--help] print this message\n\
4508 [-M] [--mri] enter MRI compatibility mode\n\
4509 [-o out] [--output out] set the output file\n\
4510 [-p] [--print] print line numbers\n\
4511 [-s] [--copysource] copy source through as comments \n\
4512 [-u] [--unreasonable] allow unreasonable nesting\n\
4513 [-v] [--version] print the program version\n\
4514 [-Dname=value] create preprocessor variable called name, with value\n\
4515 [-Ipath] add to include path list\n\
4516 [in-file]\n", program_name);
4517 exit (status);
4518 }
4519
4520 /* Display a help message and exit. */
4521 static void
4522 show_help ()
4523 {
4524 printf ("%s: Gnu Assembler Macro Preprocessor\n",
4525 program_name);
4526 show_usage (stdout, 0);
4527 }
4528
4529 int
4530 main (argc, argv)
4531 int argc;
4532 char **argv;
4533 {
4534 int opt;
4535 char *out_name = 0;
4536 sp = include_stack;
4537
4538 ifstack[0].on = 1;
4539 ifi = 0;
4540
4541
4542
4543 program_name = argv[0];
4544 xmalloc_set_program_name (program_name);
4545
4546 hash_new_table (101, &macro_table);
4547 hash_new_table (101, &keyword_hash_table);
4548 hash_new_table (101, &assign_hash_table);
4549 hash_new_table (101, &vars);
4550
4551 sb_new (&label);
4552
4553 while ((opt = getopt_long (argc, argv, "I:sdhavc:upo:D:M", long_options,
4554 (int *) NULL))
4555 != EOF)
4556 {
4557 switch (opt)
4558 {
4559 case 'o':
4560 out_name = optarg;
4561 break;
4562 case 'u':
4563 unreasonable = 1;
4564 break;
4565 case 'I':
4566 {
4567 include_path *p = (include_path *) xmalloc (sizeof (include_path));
4568 sb_new (&p->path);
4569 sb_add_string (&p->path, optarg);
4570 if (paths_tail)
4571 paths_tail->next = p;
4572 else
4573 paths_head = p;
4574 paths_tail = p;
4575 }
4576 break;
4577 case 'p':
4578 print_line_number = 1;
4579 break;
4580 case 'c':
4581 comment_char = optarg[0];
4582 break;
4583 case 'a':
4584 alternate = 1;
4585 break;
4586 case 's':
4587 copysource = 1;
4588 break;
4589 case 'd':
4590 stats = 1;
4591 break;
4592 case 'D':
4593 do_define (optarg);
4594 break;
4595 case 'M':
4596 mri = 1;
4597 comment_char = ';';
4598 break;
4599 case 'h':
4600 show_help ();
4601 /*NOTREACHED*/
4602 case 'v':
4603 printf ("GNU %s version %s\n", program_name, program_version);
4604 exit (0);
4605 /*NOTREACHED*/
4606 case 0:
4607 break;
4608 default:
4609 show_usage (stderr, 1);
4610 /*NOTREACHED*/
4611 }
4612 }
4613
4614 process_init ();
4615
4616 if (out_name) {
4617 outfile = fopen (out_name, "w");
4618 if (!outfile)
4619 {
4620 fprintf (stderr, "%s: Can't open output file `%s'.\n",
4621 program_name, out_name);
4622 exit (1);
4623 }
4624 }
4625 else {
4626 outfile = stdout;
4627 }
4628
4629 chartype_init ();
4630 if (!outfile)
4631 outfile = stdout;
4632
4633 /* Process all the input files */
4634
4635 while (optind < argc)
4636 {
4637 if (new_file (argv[optind]))
4638 {
4639 process_file ();
4640 }
4641 else
4642 {
4643 fprintf (stderr, "%s: Can't open input file `%s'.\n",
4644 program_name, argv[optind]);
4645 exit (1);
4646 }
4647 optind++;
4648 }
4649
4650 quit ();
4651 return 0;
4652 }