* cpu-i386.c (i8086_arch): Architecture info for the i8086.
[deliverable/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 #include "sb.h"
69 #include "macro.h"
70
71 char *program_version = "1.2";
72
73 #define MAX_INCLUDES 30 /* Maximum include depth */
74 #define MAX_REASONABLE 1000 /* Maximum number of expansions */
75
76 int unreasonable; /* -u on command line */
77 int stats; /* -d on command line */
78 int print_line_number; /* -p flag on command line */
79 int copysource; /* -c flag on command line */
80 int warnings; /* Number of WARNINGs generated so far. */
81 int errors; /* Number of ERRORs generated so far. */
82 int fatals; /* Number of fatal ERRORs generated so far (either 0 or 1). */
83 int alternate = 0; /* -a on command line */
84 int mri = 0; /* -M on command line */
85 char comment_char = '!';
86 int radix = 10; /* Default radix */
87
88 int had_end; /* Seen .END */
89
90 /* The output stream */
91 FILE *outfile;
92
93 /* the attributes of each character are stored as a bit pattern
94 chartype, which gives us quick tests. */
95
96
97 #define FIRSTBIT 1
98 #define NEXTBIT 2
99 #define SEPBIT 4
100 #define WHITEBIT 8
101 #define COMMENTBIT 16
102 #define BASEBIT 32
103 #define ISCOMMENTCHAR(x) (chartype[(unsigned)(x)] & COMMENTBIT)
104 #define ISFIRSTCHAR(x) (chartype[(unsigned)(x)] & FIRSTBIT)
105 #define ISNEXTCHAR(x) (chartype[(unsigned)(x)] & NEXTBIT)
106 #define ISSEP(x) (chartype[(unsigned)(x)] & SEPBIT)
107 #define ISWHITE(x) (chartype[(unsigned)(x)] & WHITEBIT)
108 #define ISBASE(x) (chartype[(unsigned)(x)] & BASEBIT)
109 static char chartype[256];
110
111
112 /* Conditional assembly uses the `ifstack'. Each aif pushes another
113 entry onto the stack, and sets the on flag if it should. The aelse
114 sets hadelse, and toggles on. An aend pops a level. We limit to
115 100 levels of nesting, not because we're facists pigs with read
116 only minds, but because more than 100 levels of nesting is probably
117 a bug in the user's macro structure. */
118
119 #define IFNESTING 100
120 struct
121 {
122 int on; /* is the level being output */
123 int hadelse; /* has an aelse been seen */
124 }
125 ifstack[IFNESTING];
126 int ifi;
127
128 /* The final and intermediate results of expression evaluation are kept in
129 exp_t's. Note that a symbol is not an sb, but a pointer into the input
130 line. It must be coped somewhere safe before the next line is read in. */
131
132 typedef struct
133 {
134 char *name;
135 int len;
136 }
137 symbol;
138
139 typedef struct
140 {
141 int value; /* constant part */
142 symbol add_symbol; /* name part */
143 symbol sub_symbol; /* name part */
144 }
145 exp_t;
146
147
148 /* Hashing is done in a pretty standard way. A hash_table has a
149 pointer to a vector of pointers to hash_entrys, and the size of the
150 vector. A hash_entry contains a union of all the info we like to
151 store in hash table. If there is a hash collision, hash_entries
152 with the same hash are kept in a chain. */
153
154 /* What the data in a hash_entry means */
155 typedef enum
156 {
157 hash_integer, /* name->integer mapping */
158 hash_string, /* name->string mapping */
159 hash_macro, /* name is a macro */
160 hash_formal /* name is a formal argument */
161 } hash_type;
162
163 typedef struct hs
164 {
165 sb key; /* symbol name */
166 hash_type type; /* symbol meaning */
167 union
168 {
169 sb s;
170 int i;
171 struct macro_struct *m;
172 struct formal_struct *f;
173 } value;
174 struct hs *next; /* next hash_entry with same hash key */
175 } hash_entry;
176
177 typedef struct
178 {
179 hash_entry **table;
180 int size;
181 } hash_table;
182
183
184 /* Structures used to store macros.
185
186 Each macro knows its name and included text. It gets built with a
187 list of formal arguments, and also keeps a hash table which points
188 into the list to speed up formal search. Each formal knows its
189 name and its default value. Each time the macro is expanded, the
190 formals get the actual values attatched to them. */
191
192 /* describe the formal arguments to a macro */
193
194 typedef struct formal_struct
195 {
196 struct formal_struct *next; /* next formal in list */
197 sb name; /* name of the formal */
198 sb def; /* the default value */
199 sb actual; /* the actual argument (changed on each expansion) */
200 int index; /* the index of the formal 0..formal_count-1 */
201 }
202 formal_entry;
203
204 /* describe the macro. */
205
206 typedef struct macro_struct
207 {
208 sb sub; /* substitution text. */
209 int formal_count; /* number of formal args. */
210 formal_entry *formals; /* pointer to list of formal_structs */
211 hash_table formal_hash; /* hash table of formals. */
212 }
213 macro_entry;
214
215 /* how we nest files and expand macros etc.
216
217 we keep a stack of of include_stack structs. each include file
218 pushes a new level onto the stack. we keep an sb with a pushback
219 too. unget chars are pushed onto the pushback sb, getchars first
220 checks the pushback sb before reading from the input stream.
221
222 small things are expanded by adding the text of the item onto the
223 pushback sb. larger items are grown by pushing a new level and
224 allocating the entire pushback buf for the item. each time
225 something like a macro is expanded, the stack index is changed. we
226 can then perform an exitm by popping all entries off the stack with
227 the same stack index. if we're being reasonable, we can detect
228 recusive expansion by checking the index is reasonably small.
229 */
230
231 typedef enum
232 {
233 include_file, include_repeat, include_while, include_macro
234 } include_type;
235
236 struct include_stack
237 {
238 sb pushback; /* current pushback stream */
239 int pushback_index; /* next char to read from stream */
240 FILE *handle; /* open file */
241 sb name; /* name of file */
242 int linecount; /* number of lines read so far */
243 include_type type;
244 int index; /* index of this layer */
245 }
246 include_stack[MAX_INCLUDES];
247
248 struct include_stack *sp;
249 #define isp (sp - include_stack)
250
251 /* Include file list */
252
253 typedef struct include_path
254 {
255 struct include_path *next;
256 sb path;
257 } include_path;
258
259 include_path *paths_head;
260 include_path *paths_tail;
261
262
263 static void quit PARAMS ((void));
264 static void hash_new_table PARAMS ((int, hash_table *));
265 static int hash PARAMS ((sb *));
266 static hash_entry *hash_create PARAMS ((hash_table *, sb *));
267 static void hash_add_to_string_table PARAMS ((hash_table *, sb *, sb *, int));
268 static void hash_add_to_int_table PARAMS ((hash_table *, sb *, int));
269 static hash_entry *hash_lookup PARAMS ((hash_table *, sb *));
270 static void checkconst PARAMS ((int, exp_t *));
271 static int sb_strtol PARAMS ((int, sb *, int, int *));
272 static int level_0 PARAMS ((int, sb *, exp_t *));
273 static int level_1 PARAMS ((int, sb *, exp_t *));
274 static int level_2 PARAMS ((int, sb *, exp_t *));
275 static int level_3 PARAMS ((int, sb *, exp_t *));
276 static int level_4 PARAMS ((int, sb *, exp_t *));
277 static int level_5 PARAMS ((int, sb *, exp_t *));
278 static int exp_parse PARAMS ((int, sb *, exp_t *));
279 static void exp_string PARAMS ((exp_t *, sb *));
280 static int exp_get_abs PARAMS ((const char *, int, sb *, int *));
281 #if 0
282 static void strip_comments PARAMS ((sb *));
283 #endif
284 static void unget PARAMS ((int));
285 static void include_buf PARAMS ((sb *, sb *, include_type, int));
286 static void include_print_where_line PARAMS ((FILE *));
287 static void include_print_line PARAMS ((FILE *));
288 static int get_line PARAMS ((sb *));
289 static int grab_label PARAMS ((sb *, sb *));
290 static void change_base PARAMS ((int, sb *, sb *));
291 static void do_end PARAMS ((sb *));
292 static void do_assign PARAMS ((int, int, sb *));
293 static void do_radix PARAMS ((sb *));
294 static int get_opsize PARAMS ((int, sb *, int *));
295 static int eol PARAMS ((int, sb *));
296 static void do_data PARAMS ((int, sb *, int));
297 static void do_datab PARAMS ((int, sb *));
298 static void do_align PARAMS ((int, sb *));
299 static void do_res PARAMS ((int, sb *, int));
300 static void do_export PARAMS ((sb *));
301 static void do_print PARAMS ((int, sb *));
302 static void do_heading PARAMS ((int, sb *));
303 static void do_page PARAMS ((void));
304 static void do_form PARAMS ((int, sb *));
305 static int get_any_string PARAMS ((int, sb *, sb *, int, int));
306 static int skip_openp PARAMS ((int, sb *));
307 static int skip_closep PARAMS ((int, sb *));
308 static int dolen PARAMS ((int, sb *, sb *));
309 static int doinstr PARAMS ((int, sb *, sb *));
310 static int dosubstr PARAMS ((int, sb *, sb *));
311 static void process_assigns PARAMS ((int, sb *, sb *));
312 static int get_and_process PARAMS ((int, sb *, sb *));
313 static void process_file PARAMS ((void));
314 static void free_old_entry PARAMS ((hash_entry *));
315 static void do_assigna PARAMS ((int, sb *));
316 static void do_assignc PARAMS ((int, sb *));
317 static void do_reg PARAMS ((int, sb *));
318 static int condass_lookup_name PARAMS ((sb *, int, sb *, int));
319 static int whatcond PARAMS ((int, sb *, int *));
320 static int istrue PARAMS ((int, sb *));
321 static void do_aif PARAMS ((int, sb *));
322 static void do_aelse PARAMS ((void));
323 static void do_aendi PARAMS ((void));
324 static int condass_on PARAMS ((void));
325 static void do_if PARAMS ((int, sb *, int));
326 static int get_mri_string PARAMS ((int, sb *, sb *, int));
327 static void do_ifc PARAMS ((int, sb *, int));
328 static void do_aendr PARAMS ((void));
329 static void do_awhile PARAMS ((int, sb *));
330 static void do_aendw PARAMS ((void));
331 static void do_exitm PARAMS ((void));
332 static void do_arepeat PARAMS ((int, sb *));
333 static void do_endm PARAMS ((void));
334 static void do_irp PARAMS ((int, sb *, int));
335 static void do_local PARAMS ((int, sb *));
336 static void do_macro PARAMS ((int, sb *));
337 static int macro_op PARAMS ((int, sb *));
338 static int getstring PARAMS ((int, sb *, sb *));
339 static void do_sdata PARAMS ((int, sb *, int));
340 static void do_sdatab PARAMS ((int, sb *));
341 static int new_file PARAMS ((const char *));
342 static void do_include PARAMS ((int, sb *));
343 static void include_pop PARAMS ((void));
344 static int get PARAMS ((void));
345 static int linecount PARAMS ((void));
346 static int include_next_index PARAMS ((void));
347 static void chartype_init PARAMS ((void));
348 static int process_pseudo_op PARAMS ((int, sb *, sb *));
349 static void add_keyword PARAMS ((const char *, int));
350 static void process_init PARAMS ((void));
351 static void do_define PARAMS ((const char *));
352 static void show_usage PARAMS ((FILE *, int));
353 static void show_help PARAMS ((void));
354
355 #define FATAL(x) \
356 do { include_print_where_line (stderr); fprintf x ; fatals++; quit(); } while(0)
357 #define ERROR(x) \
358 do { include_print_where_line (stderr); fprintf x; errors++; } while(0)
359 #define WARNING(x) \
360 do { include_print_where_line (stderr); fprintf x; warnings++;} while(0)
361
362
363
364 /* exit the program and return the right ERROR code. */
365 static void
366 quit ()
367 {
368 int exitcode;
369 if (fatals + errors)
370 exitcode = 1;
371 else
372 exitcode = 0;
373
374 if (stats)
375 {
376 int i;
377 for (i = 0; i < sb_max_power_two; i++)
378 {
379 fprintf (stderr, "strings size %8d : %d\n", 1<<i, string_count[i]);
380 }
381 }
382 exit (exitcode);
383 }
384
385 /* hash table maintenance. */
386
387 /* build a new hash table with size buckets, and fill in the info at ptr. */
388
389 static void
390 hash_new_table (size, ptr)
391 int size;
392 hash_table *ptr;
393 {
394 int i;
395 ptr->size = size;
396 ptr->table = (hash_entry **) xmalloc (size * (sizeof (hash_entry *)));
397 /* Fill with null-pointer, not zero-bit-pattern. */
398 for (i = 0; i < size; i++)
399 ptr->table[i] = 0;
400 }
401
402 /* calculate and return the hash value of the sb at key. */
403
404 static int
405 hash (key)
406 sb *key;
407 {
408 int k = 0x1234;
409 int i;
410 char *p = key->ptr;
411 for (i = 0; i < key->len; i++)
412 {
413 k ^= (k << 2) ^ *p;
414 p++;
415 }
416 return k & 0xf0fff;
417 }
418
419 /* lookup key in hash_table tab, if present, then return it, otherwise
420 build a new one and fill it with hash_integer. */
421
422 static
423 hash_entry *
424 hash_create (tab, key)
425 hash_table *tab;
426 sb *key;
427 {
428 int k = hash (key) % tab->size;
429 hash_entry *p;
430 hash_entry **table = tab->table;
431
432 p = table[k];
433
434 while (1)
435 {
436 if (!p)
437 {
438 hash_entry *n = (hash_entry *) xmalloc (sizeof (hash_entry));
439 n->next = table[k];
440 sb_new (&n->key);
441 sb_add_sb (&n->key, key);
442 table[k] = n;
443 n->type = hash_integer;
444 return n;
445 }
446 if (strncmp (table[k]->key.ptr, key->ptr, key->len) == 0)
447 {
448 return p;
449 }
450 p = p->next;
451 }
452 }
453
454 /* add sb name with key into hash_table tab. if replacing old value
455 and again, then ERROR. */
456
457 static
458 void
459 hash_add_to_string_table (tab, key, name, again)
460 hash_table *tab;
461 sb *key;
462 sb *name;
463 int again;
464 {
465 hash_entry *ptr = hash_create (tab, key);
466 if (ptr->type == hash_integer)
467 {
468 sb_new (&ptr->value.s);
469 }
470 if (ptr->value.s.len)
471 {
472 if (!again)
473 ERROR ((stderr, "redefintion not allowed"));
474 }
475
476 ptr->type = hash_string;
477 sb_reset (&ptr->value.s);
478
479 sb_add_sb (&ptr->value.s, name);
480 }
481
482 /* add integer name to hash_table tab with sb key. */
483
484 static
485 void
486 hash_add_to_int_table (tab, key, name)
487 hash_table *tab;
488 sb *key;
489 int name;
490 {
491 hash_entry *ptr = hash_create (tab, key);
492 ptr->value.i = name;
493 }
494
495 /* lookup sb key in hash_table tab. if found return hash_entry result,
496 else 0. */
497
498 static
499 hash_entry *
500 hash_lookup (tab, key)
501 hash_table *tab;
502 sb *key;
503 {
504 int k = hash (key) % tab->size;
505 hash_entry **table = tab->table;
506 hash_entry *p = table[k];
507 while (p)
508 {
509 if (p->key.len == key->len
510 && strncmp (p->key.ptr, key->ptr, key->len) == 0)
511 return p;
512 p = p->next;
513 }
514 return 0;
515 }
516
517
518 /* expressions
519
520 are handled in a really simple recursive decent way. each bit of
521 the machine takes an index into an sb and a pointer to an exp_t,
522 modifies the *exp_t and returns the index of the first character
523 past the part of the expression parsed.
524
525 expression precedence:
526 ( )
527 unary + - ~
528 * /
529 + -
530 &
531 | ~
532
533 */
534
535
536 /* make sure that the exp_t at term is constant, if not the give the op ERROR. */
537
538 static
539 void
540 checkconst (op, term)
541 int op;
542 exp_t *term;
543 {
544 if (term->add_symbol.len
545 || term->sub_symbol.len)
546 {
547 ERROR ((stderr, "the %c operator cannot take non-absolute arguments.\n", op));
548 }
549 }
550
551 /* turn the number in string at idx into a number of base,
552 fill in ptr and return the index of the first character not in the
553 number. */
554
555 static
556 int
557 sb_strtol (idx, string, base, ptr)
558 int idx;
559 sb *string;
560 int base;
561 int *ptr;
562 {
563 int value = 0;
564 idx = sb_skip_white (idx, string);
565
566 while (idx < string->len)
567 {
568 int ch = string->ptr[idx];
569 int dig = 0;
570 if (isdigit (ch))
571 dig = ch - '0';
572 else if (ch >= 'a' && ch <= 'f')
573 dig = ch - 'a' + 10;
574 else if (ch >= 'A' && ch <= 'F')
575 dig = ch - 'A' + 10;
576 else
577 break;
578
579 if (dig >= base)
580 break;
581
582 value = value * base + dig;
583 idx++;
584 }
585 *ptr = value;
586 return idx;
587 }
588
589 static int
590 level_0 (idx, string, lhs)
591 int idx;
592 sb *string;
593 exp_t *lhs;
594 {
595 lhs->add_symbol.len = 0;
596 lhs->add_symbol.name = 0;
597
598 lhs->sub_symbol.len = 0;
599 lhs->sub_symbol.name = 0;
600
601 idx = sb_skip_white (idx, string);
602
603 lhs->value = 0;
604
605 if (isdigit (string->ptr[idx]))
606 {
607 idx = sb_strtol (idx, string, 10, &lhs->value);
608 }
609 else if (ISFIRSTCHAR (string->ptr[idx]))
610 {
611 int len = 0;
612 lhs->add_symbol.name = string->ptr + idx;
613 while (idx < string->len && ISNEXTCHAR (string->ptr[idx]))
614 {
615 idx++;
616 len++;
617 }
618 lhs->add_symbol.len = len;
619 }
620 else if (string->ptr[idx] == '"')
621 {
622 sb acc;
623 sb_new (&acc);
624 ERROR ((stderr, "string where expression expected.\n"));
625 idx = getstring (idx, string, &acc);
626 sb_kill (&acc);
627 }
628 else
629 {
630 ERROR ((stderr, "can't find primary in expression.\n"));
631 idx++;
632 }
633 return sb_skip_white (idx, string);
634 }
635
636
637
638 static int
639 level_1 (idx, string, lhs)
640 int idx;
641 sb *string;
642 exp_t *lhs;
643 {
644 idx = sb_skip_white (idx, string);
645
646 switch (string->ptr[idx])
647 {
648 case '+':
649 idx = level_1 (idx + 1, string, lhs);
650 break;
651 case '~':
652 idx = level_1 (idx + 1, string, lhs);
653 checkconst ('~', lhs);
654 lhs->value = ~lhs->value;
655 break;
656 case '-':
657 {
658 symbol t;
659 idx = level_1 (idx + 1, string, lhs);
660 lhs->value = -lhs->value;
661 t = lhs->add_symbol;
662 lhs->add_symbol = lhs->sub_symbol;
663 lhs->sub_symbol = t;
664 break;
665 }
666 case '(':
667 idx++;
668 idx = level_5 (sb_skip_white (idx, string), string, lhs);
669 if (string->ptr[idx] != ')')
670 ERROR ((stderr, "misplaced closing parens.\n"));
671 else
672 idx++;
673 break;
674 default:
675 idx = level_0 (idx, string, lhs);
676 break;
677 }
678 return sb_skip_white (idx, string);
679 }
680
681 static int
682 level_2 (idx, string, lhs)
683 int idx;
684 sb *string;
685 exp_t *lhs;
686 {
687 exp_t rhs;
688
689 idx = level_1 (idx, string, lhs);
690
691 while (idx < string->len && (string->ptr[idx] == '*'
692 || string->ptr[idx] == '/'))
693 {
694 char op = string->ptr[idx++];
695 idx = level_1 (idx, string, &rhs);
696 switch (op)
697 {
698 case '*':
699 checkconst ('*', lhs);
700 checkconst ('*', &rhs);
701 lhs->value *= rhs.value;
702 break;
703 case '/':
704 checkconst ('/', lhs);
705 checkconst ('/', &rhs);
706 if (rhs.value == 0)
707 ERROR ((stderr, "attempt to divide by zero.\n"));
708 else
709 lhs->value /= rhs.value;
710 break;
711 }
712 }
713 return sb_skip_white (idx, string);
714 }
715
716
717 static int
718 level_3 (idx, string, lhs)
719 int idx;
720 sb *string;
721 exp_t *lhs;
722 {
723 exp_t rhs;
724
725 idx = level_2 (idx, string, lhs);
726
727 while (idx < string->len
728 && (string->ptr[idx] == '+'
729 || string->ptr[idx] == '-'))
730 {
731 char op = string->ptr[idx++];
732 idx = level_2 (idx, string, &rhs);
733 switch (op)
734 {
735 case '+':
736 lhs->value += rhs.value;
737 if (lhs->add_symbol.name && rhs.add_symbol.name)
738 {
739 ERROR ((stderr, "can't add two relocatable expressions\n"));
740 }
741 /* change nn+symbol to symbol + nn */
742 if (rhs.add_symbol.name)
743 {
744 lhs->add_symbol = rhs.add_symbol;
745 }
746 break;
747 case '-':
748 lhs->value -= rhs.value;
749 lhs->sub_symbol = rhs.add_symbol;
750 break;
751 }
752 }
753 return sb_skip_white (idx, string);
754 }
755
756 static int
757 level_4 (idx, string, lhs)
758 int idx;
759 sb *string;
760 exp_t *lhs;
761 {
762 exp_t rhs;
763
764 idx = level_3 (idx, string, lhs);
765
766 while (idx < string->len &&
767 string->ptr[idx] == '&')
768 {
769 char op = string->ptr[idx++];
770 idx = level_3 (idx, string, &rhs);
771 switch (op)
772 {
773 case '&':
774 checkconst ('&', lhs);
775 checkconst ('&', &rhs);
776 lhs->value &= rhs.value;
777 break;
778 }
779 }
780 return sb_skip_white (idx, string);
781 }
782
783 static int
784 level_5 (idx, string, lhs)
785 int idx;
786 sb *string;
787 exp_t *lhs;
788 {
789 exp_t rhs;
790
791 idx = level_4 (idx, string, lhs);
792
793 while (idx < string->len
794 && (string->ptr[idx] == '|' || string->ptr[idx] == '~'))
795 {
796 char op = string->ptr[idx++];
797 idx = level_4 (idx, string, &rhs);
798 switch (op)
799 {
800 case '|':
801 checkconst ('|', lhs);
802 checkconst ('|', &rhs);
803 lhs->value |= rhs.value;
804 break;
805 case '~':
806 checkconst ('~', lhs);
807 checkconst ('~', &rhs);
808 lhs->value ^= rhs.value;
809 break;
810 }
811 }
812 return sb_skip_white (idx, string);
813 }
814
815
816 /* parse the expression at offset idx into string, fill up res with
817 the result. return the index of the first char past the expression.
818 */
819
820 static int
821 exp_parse (idx, string, res)
822 int idx;
823 sb *string;
824 exp_t *res;
825 {
826 return level_5 (sb_skip_white (idx, string), string, res);
827 }
828
829
830 /* turn the expression at exp into text and glue it onto the end of
831 string. */
832
833 static void
834 exp_string (exp, string)
835 exp_t *exp;
836 sb *string;
837 {
838 int np = 0;
839 int ad = 0;
840 sb_reset (string);
841
842 if (exp->add_symbol.len)
843 {
844 sb_add_buffer (string, exp->add_symbol.name, exp->add_symbol.len);
845 np = 1;
846 ad = 1;
847 }
848 if (exp->value)
849 {
850 char buf[20];
851 if (np)
852 sb_add_char (string, '+');
853 sprintf (buf, "%d", exp->value);
854 sb_add_string (string, buf);
855 np = 1;
856 ad = 1;
857 }
858 if (exp->sub_symbol.len)
859 {
860 sb_add_char (string, '-');
861 sb_add_buffer (string, exp->add_symbol.name, exp->add_symbol.len);
862 np = 0;
863 ad = 1;
864 }
865
866 if (!ad)
867 sb_add_char (string, '0');
868 }
869
870
871 /* parse the expression at offset idx into sb in, return the value in val.
872 if the expression is not constant, give ERROR emsg. returns the index
873 of the first character past the end of the expression. */
874
875 static int
876 exp_get_abs (emsg, idx, in, val)
877 const char *emsg;
878 int idx;
879 sb *in;
880 int *val;
881 {
882 exp_t res;
883 idx = exp_parse (idx, in, &res);
884 if (res.add_symbol.len || res.sub_symbol.len)
885 ERROR ((stderr, emsg));
886 *val = res.value;
887 return idx;
888 }
889
890
891 sb label; /* current label parsed from line */
892 hash_table assign_hash_table; /* hash table for all assigned variables */
893 hash_table keyword_hash_table; /* hash table for keyword */
894 hash_table vars; /* hash table for eq variables */
895
896 #define in_comment ';'
897
898 #if 0
899 static void
900 strip_comments (out)
901 sb *out;
902 {
903 char *s = out->ptr;
904 int i = 0;
905 for (i = 0; i < out->len; i++)
906 {
907 if (ISCOMMENTCHAR(s[i]))
908 {
909 out->len = i;
910 return;
911 }
912 }
913 }
914 #endif
915
916 /* push back character ch so that it can be read again. */
917
918 static void
919 unget (ch)
920 int ch;
921 {
922 if (ch == '\n')
923 {
924 sp->linecount--;
925 }
926 if (sp->pushback_index)
927 sp->pushback_index--;
928 else
929 sb_add_char (&sp->pushback, ch);
930 }
931
932 /* push the sb ptr onto the include stack, with the given name, type and index. */
933
934 static
935 void
936 include_buf (name, ptr, type, index)
937 sb *name;
938 sb *ptr;
939 include_type type;
940 int index;
941 {
942 sp++;
943 if (sp - include_stack >= MAX_INCLUDES)
944 FATAL ((stderr, "unreasonable nesting.\n"));
945 sb_new (&sp->name);
946 sb_add_sb (&sp->name, name);
947 sp->handle = 0;
948 sp->linecount = 1;
949 sp->pushback_index = 0;
950 sp->type = type;
951 sp->index = index;
952 sb_new (&sp->pushback);
953 sb_add_sb (&sp->pushback, ptr);
954 }
955
956
957 /* used in ERROR messages, print info on where the include stack is onto file. */
958 static
959 void
960 include_print_where_line (file)
961 FILE *file;
962 {
963 struct include_stack *p = include_stack + 1;
964
965 while (p <= sp)
966 {
967 fprintf (file, "%s:%d ", sb_name (&p->name), p->linecount - 1);
968 p++;
969 }
970 }
971
972 /* used in listings, print the line number onto file. */
973 static void
974 include_print_line (file)
975 FILE *file;
976 {
977 int n;
978 struct include_stack *p = include_stack + 1;
979
980 n = fprintf (file, "%4d", p->linecount);
981 p++;
982 while (p <= sp)
983 {
984 n += fprintf (file, ".%d", p->linecount);
985 p++;
986 }
987 while (n < 8 * 3)
988 {
989 fprintf (file, " ");
990 n++;
991 }
992 }
993
994
995 /* read a line from the top of the include stack into sb in. */
996
997 static int
998 get_line (in)
999 sb *in;
1000 {
1001 int online = 0;
1002 int more = 1;
1003
1004 if (copysource)
1005 {
1006 putc (comment_char, outfile);
1007 if (print_line_number)
1008 include_print_line (outfile);
1009 }
1010
1011 while (1)
1012 {
1013 int ch = get ();
1014
1015 while (ch == '\r')
1016 ch = get ();
1017
1018 if (ch == EOF)
1019 {
1020 if (online)
1021 {
1022 WARNING ((stderr, "End of file not at start of line.\n"));
1023 if (copysource)
1024 putc ('\n', outfile);
1025 ch = '\n';
1026 }
1027 else
1028 more = 0;
1029 break;
1030 }
1031
1032 if (copysource)
1033 {
1034 putc (ch, outfile);
1035 }
1036
1037 if (ch == '\n')
1038 {
1039 ch = get ();
1040 online = 0;
1041 if (ch == '+')
1042 {
1043 /* continued line */
1044 if (copysource)
1045 {
1046 putc (comment_char, outfile);
1047 putc ('+', outfile);
1048 }
1049 ch = get ();
1050 }
1051 else
1052 {
1053 if (ch != EOF)
1054 unget (ch);
1055 break;
1056 }
1057 }
1058 else
1059 {
1060 sb_add_char (in, ch);
1061 }
1062 online++;
1063 }
1064
1065 return more;
1066 }
1067
1068 /* find a label from sb in and put it in out. */
1069
1070 static int
1071 grab_label (in, out)
1072 sb *in;
1073 sb *out;
1074 {
1075 int i = 0;
1076 sb_reset (out);
1077 if (ISFIRSTCHAR (in->ptr[i]))
1078 {
1079 sb_add_char (out, in->ptr[i]);
1080 i++;
1081 while ((ISNEXTCHAR (in->ptr[i])
1082 || in->ptr[i] == '\\'
1083 || in->ptr[i] == '&')
1084 && i < in->len)
1085 {
1086 sb_add_char (out, in->ptr[i]);
1087 i++;
1088 }
1089 }
1090 return i;
1091 }
1092
1093 /* find all strange base stuff and turn into decimal. also
1094 find all the other numbers and convert them from the default radix */
1095
1096 static void
1097 change_base (idx, in, out)
1098 int idx;
1099 sb *in;
1100 sb *out;
1101 {
1102 char buffer[20];
1103
1104 while (idx < in->len)
1105 {
1106 if (in->ptr[idx] == '\\'
1107 && idx + 1 < in->len
1108 && in->ptr[idx + 1] == '(')
1109 {
1110 idx += 2;
1111 while (idx < in->len
1112 && in->ptr[idx] != ')')
1113 {
1114 sb_add_char (out, in->ptr[idx]);
1115 idx++;
1116 }
1117 if (idx < in->len)
1118 idx++;
1119 }
1120 else if (idx < in->len - 1 && in->ptr[idx + 1] == '\'' && ! mri)
1121 {
1122 int base;
1123 int value;
1124 switch (in->ptr[idx])
1125 {
1126 case 'b':
1127 case 'B':
1128 base = 2;
1129 break;
1130 case 'q':
1131 case 'Q':
1132 base = 8;
1133 break;
1134 case 'h':
1135 case 'H':
1136 base = 16;
1137 break;
1138 case 'd':
1139 case 'D':
1140 base = 10;
1141 break;
1142 default:
1143 ERROR ((stderr, "Illegal base character %c.\n", in->ptr[idx]));
1144 base = 10;
1145 break;
1146 }
1147
1148 idx = sb_strtol (idx + 2, in, base, &value);
1149 sprintf (buffer, "%d", value);
1150 sb_add_string (out, buffer);
1151 }
1152 else if (ISFIRSTCHAR (in->ptr[idx]))
1153 {
1154 /* copy entire names through quickly */
1155 sb_add_char (out, in->ptr[idx]);
1156 idx++;
1157 while (idx < in->len && ISNEXTCHAR (in->ptr[idx]))
1158 {
1159 sb_add_char (out, in->ptr[idx]);
1160 idx++;
1161 }
1162 }
1163 else if (isdigit (in->ptr[idx]))
1164 {
1165 int value;
1166 /* all numbers must start with a digit, let's chew it and
1167 spit out decimal */
1168 idx = sb_strtol (idx, in, radix, &value);
1169 sprintf (buffer, "%d", value);
1170 sb_add_string (out, buffer);
1171
1172 /* skip all undigsested letters */
1173 while (idx < in->len && ISNEXTCHAR (in->ptr[idx]))
1174 {
1175 sb_add_char (out, in->ptr[idx]);
1176 idx++;
1177 }
1178 }
1179 else if (in->ptr[idx] == '"' || in->ptr[idx] == '\'')
1180 {
1181 char tchar = in->ptr[idx];
1182 /* copy entire names through quickly */
1183 sb_add_char (out, in->ptr[idx]);
1184 idx++;
1185 while (idx < in->len && in->ptr[idx] != tchar)
1186 {
1187 sb_add_char (out, in->ptr[idx]);
1188 idx++;
1189 }
1190 }
1191 else
1192 {
1193 /* nothing special, just pass it through */
1194 sb_add_char (out, in->ptr[idx]);
1195 idx++;
1196 }
1197 }
1198
1199 }
1200
1201 /* .end */
1202 static void
1203 do_end (in)
1204 sb *in;
1205 {
1206 had_end = 1;
1207 if (mri)
1208 fprintf (outfile, "%s\n", sb_name (in));
1209 }
1210
1211 /* .assign */
1212
1213 static void
1214 do_assign (again, idx, in)
1215 int again;
1216 int idx;
1217 sb *in;
1218 {
1219 /* stick label in symbol table with following value */
1220 exp_t e;
1221 sb acc;
1222
1223 sb_new (&acc);
1224 idx = exp_parse (idx, in, &e);
1225 exp_string (&e, &acc);
1226 hash_add_to_string_table (&assign_hash_table, &label, &acc, again);
1227 sb_kill (&acc);
1228 }
1229
1230
1231 /* .radix [b|q|d|h] */
1232
1233 static
1234 void
1235 do_radix (ptr)
1236 sb *ptr;
1237 {
1238 int idx = sb_skip_white (0, ptr);
1239 switch (ptr->ptr[idx])
1240 {
1241 case 'B':
1242 case 'b':
1243 radix = 2;
1244 break;
1245 case 'q':
1246 case 'Q':
1247 radix = 8;
1248 break;
1249 case 'd':
1250 case 'D':
1251 radix = 10;
1252 break;
1253 case 'h':
1254 case 'H':
1255 radix = 16;
1256 break;
1257 default:
1258 ERROR ((stderr, "radix is %c must be one of b, q, d or h", radix));
1259 }
1260 }
1261
1262
1263 /* Parse off a .b, .w or .l */
1264
1265 static int
1266 get_opsize (idx, in, size)
1267 int idx;
1268 sb *in;
1269 int *size;
1270 {
1271 *size = 4;
1272 if (in->ptr[idx] == '.')
1273 {
1274 idx++;
1275 }
1276 switch (in->ptr[idx])
1277 {
1278 case 'b':
1279 case 'B':
1280 *size = 1;
1281 break;
1282 case 'w':
1283 case 'W':
1284 *size = 2;
1285 break;
1286 case 'l':
1287 case 'L':
1288 *size = 4;
1289 break;
1290 case ' ':
1291 case '\t':
1292 break;
1293 default:
1294 ERROR ((stderr, "size must be one of b, w or l, is %c.\n", in->ptr[idx]));
1295 break;
1296 }
1297 idx++;
1298
1299 return idx;
1300 }
1301
1302 static
1303 int eol(idx, line)
1304 int idx;
1305 sb *line;
1306 {
1307 idx = sb_skip_white (idx, line);
1308 if (idx < line->len
1309 && ISCOMMENTCHAR(line->ptr[idx]))
1310 return 1;
1311 if (idx >= line->len)
1312 return 1;
1313 return 0;
1314 }
1315
1316 /* .data [.b|.w|.l] <data>*
1317 or d[bwl] <data>* */
1318
1319 static void
1320 do_data (idx, in, size)
1321 int idx;
1322 sb *in;
1323 int size;
1324 {
1325 int opsize = 4;
1326 char *opname = ".yikes!";
1327 sb acc;
1328 sb_new (&acc);
1329
1330 if (!size)
1331 {
1332 idx = get_opsize (idx, in, &opsize);
1333 }
1334 else {
1335 opsize = size;
1336 }
1337 switch (opsize)
1338 {
1339 case 4:
1340 opname = ".long";
1341 break;
1342 case 2:
1343 opname = ".short";
1344 break;
1345 case 1:
1346 opname = ".byte";
1347 break;
1348 }
1349
1350
1351 fprintf (outfile, "%s\t", opname);
1352
1353 idx = sb_skip_white (idx, in);
1354
1355 if (alternate
1356 && idx < in->len
1357 && in->ptr[idx] == '"')
1358 {
1359 int i;
1360 idx = getstring (idx, in, &acc);
1361 for (i = 0; i < acc.len; i++)
1362 {
1363 if (i)
1364 fprintf(outfile,",");
1365 fprintf (outfile, "%d", acc.ptr[i]);
1366 }
1367 }
1368 else
1369 {
1370 while (!eol (idx, in))
1371 {
1372 exp_t e;
1373 idx = exp_parse (idx, in, &e);
1374 exp_string (&e, &acc);
1375 sb_add_char (&acc, 0);
1376 fprintf (outfile, acc.ptr);
1377 if (idx < in->len && in->ptr[idx] == ',')
1378 {
1379 fprintf (outfile, ",");
1380 idx++;
1381 }
1382 }
1383 }
1384 sb_kill (&acc);
1385 sb_print_at (outfile, idx, in);
1386 fprintf (outfile, "\n");
1387 }
1388
1389 /* .datab [.b|.w|.l] <repeat>,<fill> */
1390
1391 static void
1392 do_datab (idx, in)
1393 int idx;
1394 sb *in;
1395 {
1396 int opsize;
1397 int repeat;
1398 int fill;
1399
1400 idx = get_opsize (idx, in, &opsize);
1401
1402 idx = exp_get_abs ("datab repeat must be constant.\n", idx, in, &repeat);
1403 idx = sb_skip_comma (idx, in);
1404 idx = exp_get_abs ("datab data must be absolute.\n", idx, in, &fill);
1405
1406 fprintf (outfile, ".fill\t%d,%d,%d\n", repeat, opsize, fill);
1407 }
1408
1409 /* .align <size> */
1410
1411 static void
1412 do_align (idx, in)
1413 int idx;
1414 sb *in;
1415 {
1416 int al, have_fill, fill;
1417
1418 idx = exp_get_abs ("align needs absolute expression.\n", idx, in, &al);
1419 idx = sb_skip_white (idx, in);
1420 have_fill = 0;
1421 fill = 0;
1422 if (! eol (idx, in))
1423 {
1424 idx = sb_skip_comma (idx, in);
1425 idx = exp_get_abs (".align needs absolute fill value.\n", idx, in,
1426 &fill);
1427 have_fill = 1;
1428 }
1429
1430 if (al != 1
1431 && al != 2
1432 && al != 4)
1433 WARNING ((stderr, "alignment must be one of 1, 2 or 4.\n"));
1434
1435 fprintf (outfile, ".align %d", al);
1436 if (have_fill)
1437 fprintf (outfile, ",%d", fill);
1438 fprintf (outfile, "\n");
1439 }
1440
1441 /* .res[.b|.w|.l] <size> */
1442
1443 static void
1444 do_res (idx, in, type)
1445 int idx;
1446 sb *in;
1447 int type;
1448 {
1449 int size = 4;
1450 int count = 0;
1451
1452 idx = get_opsize (idx, in, &size);
1453 while (!eol(idx, in))
1454 {
1455 idx = sb_skip_white (idx, in);
1456 if (in->ptr[idx] == ',')
1457 idx++;
1458 idx = exp_get_abs ("res needs absolute expression for fill count.\n", idx, in, &count);
1459
1460 if (type == 'c' || type == 'z')
1461 count++;
1462
1463 fprintf (outfile, ".space %d\n", count * size);
1464 }
1465 }
1466
1467
1468 /* .export */
1469
1470 static void
1471 do_export (in)
1472 sb *in;
1473 {
1474 fprintf (outfile, ".global %s\n", sb_name (in));
1475 }
1476
1477 /* .print [list] [nolist] */
1478
1479 static void
1480 do_print (idx, in)
1481 int idx;
1482 sb *in;
1483 {
1484 idx = sb_skip_white (idx, in);
1485 while (idx < in->len)
1486 {
1487 if (strncasecmp (in->ptr + idx, "LIST", 4) == 0)
1488 {
1489 fprintf (outfile, ".list\n");
1490 idx += 4;
1491 }
1492 else if (strncasecmp (in->ptr + idx, "NOLIST", 6) == 0)
1493 {
1494 fprintf (outfile, ".nolist\n");
1495 idx += 6;
1496 }
1497 idx++;
1498 }
1499 }
1500
1501 /* .head */
1502 static void
1503 do_heading (idx, in)
1504 int idx;
1505 sb *in;
1506 {
1507 sb head;
1508 sb_new (&head);
1509 idx = getstring (idx, in, &head);
1510 fprintf (outfile, ".title \"%s\"\n", sb_name (&head));
1511 sb_kill (&head);
1512 }
1513
1514 /* .page */
1515
1516 static void
1517 do_page ()
1518 {
1519 fprintf (outfile, ".eject\n");
1520 }
1521
1522 /* .form [lin=<value>] [col=<value>] */
1523 static void
1524 do_form (idx, in)
1525 int idx;
1526 sb *in;
1527 {
1528 int lines = 60;
1529 int columns = 132;
1530 idx = sb_skip_white (idx, in);
1531
1532 while (idx < in->len)
1533 {
1534
1535 if (strncasecmp (in->ptr + idx, "LIN=", 4) == 0)
1536 {
1537 idx += 4;
1538 idx = exp_get_abs ("form LIN= needs absolute expresssion.\n", idx, in, &lines);
1539 }
1540
1541 if (strncasecmp (in->ptr + idx, "COL=", 4) == 0)
1542 {
1543 idx += 4;
1544 idx = exp_get_abs ("form COL= needs absolute expresssion.\n", idx, in, &columns);
1545 }
1546
1547 idx++;
1548 }
1549 fprintf (outfile, ".psize %d,%d\n", lines, columns);
1550
1551 }
1552
1553
1554 /* Fetch string from the input stream,
1555 rules:
1556 'Bxyx<whitespace> -> return 'Bxyza
1557 %<char> -> return string of decimal value of x
1558 "<string>" -> return string
1559 xyx<whitespace> -> return xyz
1560 */
1561 static int
1562 get_any_string (idx, in, out, expand, pretend_quoted)
1563 int idx;
1564 sb *in;
1565 sb *out;
1566 int expand;
1567 int pretend_quoted;
1568 {
1569 sb_reset (out);
1570 idx = sb_skip_white (idx, in);
1571
1572 if (idx < in->len)
1573 {
1574 if (in->len > 2 && in->ptr[idx+1] == '\'' && ISBASE (in->ptr[idx]))
1575 {
1576 while (!ISSEP (in->ptr[idx]))
1577 sb_add_char (out, in->ptr[idx++]);
1578 }
1579 else if (in->ptr[idx] == '%'
1580 && alternate
1581 && expand)
1582 {
1583 int val;
1584 char buf[20];
1585 /* Turns the next expression into a string */
1586 idx = exp_get_abs ("% operator needs absolute expression",
1587 idx + 1,
1588 in,
1589 &val);
1590 sprintf(buf, "%d", val);
1591 sb_add_string (out, buf);
1592 }
1593 else if (in->ptr[idx] == '"'
1594 || in->ptr[idx] == '<'
1595 || (alternate && in->ptr[idx] == '\''))
1596 {
1597 if (alternate && expand)
1598 {
1599 /* Keep the quotes */
1600 sb_add_char (out, '\"');
1601
1602 idx = getstring (idx, in, out);
1603 sb_add_char (out, '\"');
1604
1605 }
1606 else {
1607 idx = getstring (idx, in, out);
1608 }
1609 }
1610 else
1611 {
1612 while (idx < in->len
1613 && (in->ptr[idx] == '"'
1614 || in->ptr[idx] == '\''
1615 || pretend_quoted
1616 || !ISSEP (in->ptr[idx])))
1617 {
1618 if (in->ptr[idx] == '"'
1619 || in->ptr[idx] == '\'')
1620 {
1621 char tchar = in->ptr[idx];
1622 sb_add_char (out, in->ptr[idx++]);
1623 while (idx < in->len
1624 && in->ptr[idx] != tchar)
1625 sb_add_char (out, in->ptr[idx++]);
1626 if (idx == in->len)
1627 return idx;
1628 }
1629 sb_add_char (out, in->ptr[idx++]);
1630 }
1631 }
1632 }
1633
1634 return idx;
1635 }
1636
1637
1638 /* skip along sb in starting at idx, suck off whitespace a ( and more
1639 whitespace. return the idx of the next char */
1640
1641 static int
1642 skip_openp (idx, in)
1643 int idx;
1644 sb *in;
1645 {
1646 idx = sb_skip_white (idx, in);
1647 if (in->ptr[idx] != '(')
1648 ERROR ((stderr, "misplaced ( .\n"));
1649 idx = sb_skip_white (idx + 1, in);
1650 return idx;
1651 }
1652
1653 /* skip along sb in starting at idx, suck off whitespace a ) and more
1654 whitespace. return the idx of the next char */
1655
1656 static int
1657 skip_closep (idx, in)
1658 int idx;
1659 sb *in;
1660 {
1661 idx = sb_skip_white (idx, in);
1662 if (in->ptr[idx] != ')')
1663 ERROR ((stderr, "misplaced ).\n"));
1664 idx = sb_skip_white (idx + 1, in);
1665 return idx;
1666 }
1667
1668 /* .len */
1669
1670 static int
1671 dolen (idx, in, out)
1672 int idx;
1673 sb *in;
1674 sb *out;
1675 {
1676
1677 sb stringout;
1678 char buffer[10];
1679
1680 sb_new (&stringout);
1681 idx = skip_openp (idx, in);
1682 idx = get_and_process (idx, in, &stringout);
1683 idx = skip_closep (idx, in);
1684 sprintf (buffer, "%d", stringout.len);
1685 sb_add_string (out, buffer);
1686
1687 sb_kill (&stringout);
1688 return idx;
1689 }
1690
1691
1692 /* .instr */
1693
1694 static
1695 int
1696 doinstr (idx, in, out)
1697 int idx;
1698 sb *in;
1699 sb *out;
1700 {
1701 sb string;
1702 sb search;
1703 int i;
1704 int start;
1705 int res;
1706 char buffer[10];
1707
1708 sb_new (&string);
1709 sb_new (&search);
1710 idx = skip_openp (idx, in);
1711 idx = get_and_process (idx, in, &string);
1712 idx = sb_skip_comma (idx, in);
1713 idx = get_and_process (idx, in, &search);
1714 idx = sb_skip_comma (idx, in);
1715 if (isdigit (in->ptr[idx]))
1716 {
1717 idx = exp_get_abs (".instr needs absolute expresson.\n", idx, in, &start);
1718 }
1719 else
1720 {
1721 start = 0;
1722 }
1723 idx = skip_closep (idx, in);
1724 res = -1;
1725 for (i = start; i < string.len; i++)
1726 {
1727 if (strncmp (string.ptr + i, search.ptr, search.len) == 0)
1728 {
1729 res = i;
1730 break;
1731 }
1732 }
1733 sprintf (buffer, "%d", res);
1734 sb_add_string (out, buffer);
1735 sb_kill (&string);
1736 sb_kill (&search);
1737 return idx;
1738 }
1739
1740
1741 static int
1742 dosubstr (idx, in, out)
1743 int idx;
1744 sb *in;
1745 sb *out;
1746 {
1747 sb string;
1748 int pos;
1749 int len;
1750 sb_new (&string);
1751
1752 idx = skip_openp (idx, in);
1753 idx = get_and_process (idx, in, &string);
1754 idx = sb_skip_comma (idx, in);
1755 idx = exp_get_abs ("need absolute position.\n", idx, in, &pos);
1756 idx = sb_skip_comma (idx, in);
1757 idx = exp_get_abs ("need absolute length.\n", idx, in, &len);
1758 idx = skip_closep (idx, in);
1759
1760
1761 if (len < 0 || pos < 0 ||
1762 pos > string.len
1763 || pos + len > string.len)
1764 {
1765 sb_add_string (out, " ");
1766 }
1767 else
1768 {
1769 sb_add_char (out, '"');
1770 while (len > 0)
1771 {
1772 sb_add_char (out, string.ptr[pos++]);
1773 len--;
1774 }
1775 sb_add_char (out, '"');
1776 }
1777 sb_kill(&string);
1778 return idx;
1779 }
1780
1781 /* scan line, change tokens in the hash table to their replacements */
1782 static void
1783 process_assigns (idx, in, buf)
1784 int idx;
1785 sb *in;
1786 sb *buf;
1787 {
1788 while (idx < in->len)
1789 {
1790 hash_entry *ptr;
1791 if (in->ptr[idx] == '\\'
1792 && idx + 1 < in->len
1793 && in->ptr[idx + 1] == '(')
1794 {
1795 do
1796 {
1797 sb_add_char (buf, in->ptr[idx]);
1798 idx++;
1799 }
1800 while (idx < in->len && in->ptr[idx - 1] != ')');
1801 }
1802 else if (in->ptr[idx] == '\\'
1803 && idx + 1 < in->len
1804 && in->ptr[idx + 1] == '&')
1805 {
1806 idx = condass_lookup_name (in, idx + 2, buf, 1);
1807 }
1808 else if (in->ptr[idx] == '\\'
1809 && idx + 1 < in->len
1810 && in->ptr[idx + 1] == '$')
1811 {
1812 idx = condass_lookup_name (in, idx + 2, buf, 0);
1813 }
1814 else if (idx + 3 < in->len
1815 && in->ptr[idx] == '.'
1816 && toupper ((unsigned char) in->ptr[idx + 1]) == 'L'
1817 && toupper ((unsigned char) in->ptr[idx + 2]) == 'E'
1818 && toupper ((unsigned char) in->ptr[idx + 3]) == 'N')
1819 idx = dolen (idx + 4, in, buf);
1820 else if (idx + 6 < in->len
1821 && in->ptr[idx] == '.'
1822 && toupper ((unsigned char) in->ptr[idx + 1]) == 'I'
1823 && toupper ((unsigned char) in->ptr[idx + 2]) == 'N'
1824 && toupper ((unsigned char) in->ptr[idx + 3]) == 'S'
1825 && toupper ((unsigned char) in->ptr[idx + 4]) == 'T'
1826 && toupper ((unsigned char) in->ptr[idx + 5]) == 'R')
1827 idx = doinstr (idx + 6, in, buf);
1828 else if (idx + 7 < in->len
1829 && in->ptr[idx] == '.'
1830 && toupper ((unsigned char) in->ptr[idx + 1]) == 'S'
1831 && toupper ((unsigned char) in->ptr[idx + 2]) == 'U'
1832 && toupper ((unsigned char) in->ptr[idx + 3]) == 'B'
1833 && toupper ((unsigned char) in->ptr[idx + 4]) == 'S'
1834 && toupper ((unsigned char) in->ptr[idx + 5]) == 'T'
1835 && toupper ((unsigned char) in->ptr[idx + 6]) == 'R')
1836 idx = dosubstr (idx + 7, in, buf);
1837 else if (ISFIRSTCHAR (in->ptr[idx]))
1838 {
1839 /* may be a simple name subsitution, see if we have a word */
1840 sb acc;
1841 int cur = idx + 1;
1842 while (cur < in->len
1843 && (ISNEXTCHAR (in->ptr[cur])))
1844 cur++;
1845
1846 sb_new (&acc);
1847 sb_add_buffer (&acc, in->ptr + idx, cur - idx);
1848 ptr = hash_lookup (&assign_hash_table, &acc);
1849 if (ptr)
1850 {
1851 /* Found a definition for it */
1852 sb_add_sb (buf, &ptr->value.s);
1853 }
1854 else
1855 {
1856 /* No definition, just copy the word */
1857 sb_add_sb (buf, &acc);
1858 }
1859 sb_kill (&acc);
1860 idx = cur;
1861 }
1862 else
1863 {
1864 sb_add_char (buf, in->ptr[idx++]);
1865 }
1866 }
1867 }
1868
1869 static int
1870 get_and_process (idx, in, out)
1871 int idx;
1872 sb *in;
1873 sb *out;
1874 {
1875 sb t;
1876 sb_new (&t);
1877 idx = get_any_string (idx, in, &t, 1, 0);
1878 process_assigns (0, &t, out);
1879 sb_kill (&t);
1880 return idx;
1881 }
1882
1883 static
1884 void
1885 process_file ()
1886 {
1887 sb line;
1888 sb t1, t2;
1889 sb acc;
1890 sb label_in;
1891 int more;
1892
1893 sb_new (&line);
1894 sb_new (&t1);
1895 sb_new (&t2);
1896 sb_new(&acc);
1897 sb_new (&label_in);
1898 sb_reset (&line);
1899 more = get_line (&line);
1900 while (more)
1901 {
1902 /* Find any label and pseudo op that we're intested in */
1903 int l;
1904 if (line.len == 0)
1905 {
1906 if (condass_on ())
1907 fprintf (outfile, "\n");
1908 }
1909 else if (mri
1910 && (line.ptr[0] == '*'
1911 || line.ptr[0] == '!'))
1912 {
1913 /* MRI line comment. */
1914 fprintf (outfile, sb_name (&line));
1915 }
1916 else
1917 {
1918 l = grab_label (&line, &label_in);
1919 sb_reset (&label);
1920 if (label_in.len)
1921 {
1922 /* Munge any label */
1923
1924
1925 process_assigns (0, &label_in, &label);
1926 }
1927
1928 if (line.ptr[l] == ':')
1929 l++;
1930 while (ISWHITE (line.ptr[l]) && l < line.len)
1931 l++;
1932
1933 if (l < line.len)
1934 {
1935 if (process_pseudo_op (l, &line, &acc))
1936 {
1937
1938
1939
1940 }
1941 else if (condass_on ())
1942 {
1943 if (macro_op (l, &line))
1944 {
1945
1946
1947 }
1948 else
1949 {
1950 {
1951 if (label.len)
1952 {
1953 fprintf (outfile, "%s:\t", sb_name (&label));
1954 }
1955 else
1956 fprintf (outfile, "\t");
1957 sb_reset(&t1);
1958 process_assigns (l, &line, &t1);
1959 sb_reset (&t2);
1960 change_base (0, &t1, &t2);
1961 fprintf (outfile, "%s\n", sb_name (&t2));
1962 }
1963 }
1964 }
1965 }
1966 else {
1967 /* Only a label on this line */
1968 if (label.len && condass_on())
1969 {
1970 fprintf (outfile, "%s:\n", sb_name (&label));
1971 }
1972 }
1973 }
1974
1975 if (had_end)
1976 break;
1977 sb_reset (&line);
1978 more = get_line (&line);
1979 }
1980
1981 if (!had_end && !mri)
1982 WARNING ((stderr, "END missing from end of file.\n"));
1983 }
1984
1985
1986
1987
1988
1989 static void
1990 free_old_entry (ptr)
1991 hash_entry *ptr;
1992 {
1993 if (ptr)
1994 {
1995 if (ptr->type == hash_string)
1996 sb_kill(&ptr->value.s);
1997 }
1998 }
1999
2000 /* name: .ASSIGNA <value> */
2001
2002 static void
2003 do_assigna (idx, in)
2004 int idx;
2005 sb *in;
2006 {
2007 sb tmp;
2008 int val;
2009 sb_new (&tmp);
2010
2011 process_assigns (idx, in, &tmp);
2012 idx = exp_get_abs (".ASSIGNA needs constant expression argument.\n", 0, &tmp, &val);
2013
2014 if (!label.len)
2015 {
2016 ERROR ((stderr, ".ASSIGNA without label.\n"));
2017 }
2018 else
2019 {
2020 hash_entry *ptr = hash_create (&vars, &label);
2021 free_old_entry (ptr);
2022 ptr->type = hash_integer;
2023 ptr->value.i = val;
2024 }
2025 sb_kill (&tmp);
2026 }
2027
2028 /* name: .ASSIGNC <string> */
2029
2030 static void
2031 do_assignc (idx, in)
2032 int idx;
2033 sb *in;
2034 {
2035 sb acc;
2036 sb_new (&acc);
2037 idx = getstring (idx, in, &acc);
2038
2039 if (!label.len)
2040 {
2041 ERROR ((stderr, ".ASSIGNS without label.\n"));
2042 }
2043 else
2044 {
2045 hash_entry *ptr = hash_create (&vars, &label);
2046 free_old_entry (ptr);
2047 ptr->type = hash_string;
2048 sb_new (&ptr->value.s);
2049 sb_add_sb (&ptr->value.s, &acc);
2050 }
2051 sb_kill (&acc);
2052 }
2053
2054
2055 /* name: .REG (reg) */
2056
2057 static void
2058 do_reg (idx, in)
2059 int idx;
2060 sb *in;
2061 {
2062 /* remove reg stuff from inside parens */
2063 sb what;
2064 if (!mri)
2065 idx = skip_openp (idx, in);
2066 else
2067 idx = sb_skip_white (idx, in);
2068 sb_new (&what);
2069 while (idx < in->len
2070 && (mri
2071 ? ! eol (idx, in)
2072 : in->ptr[idx] != ')'))
2073 {
2074 sb_add_char (&what, in->ptr[idx]);
2075 idx++;
2076 }
2077 hash_add_to_string_table (&assign_hash_table, &label, &what, 1);
2078 sb_kill (&what);
2079 }
2080
2081
2082 static int
2083 condass_lookup_name (inbuf, idx, out, warn)
2084 sb *inbuf;
2085 int idx;
2086 sb *out;
2087 int warn;
2088 {
2089 hash_entry *ptr;
2090 sb condass_acc;
2091 sb_new (&condass_acc);
2092
2093 while (idx < inbuf->len
2094 && ISNEXTCHAR (inbuf->ptr[idx]))
2095 {
2096 sb_add_char (&condass_acc, inbuf->ptr[idx++]);
2097 }
2098
2099 if (inbuf->ptr[idx] == '\'')
2100 idx++;
2101 ptr = hash_lookup (&vars, &condass_acc);
2102
2103
2104 if (!ptr)
2105 {
2106 if (warn)
2107 {
2108 WARNING ((stderr, "Can't find preprocessor variable %s.\n", sb_name (&condass_acc)));
2109 }
2110 else
2111 {
2112 sb_add_string (out, "0");
2113 }
2114 }
2115 else
2116 {
2117 if (ptr->type == hash_integer)
2118 {
2119 char buffer[30];
2120 sprintf (buffer, "%d", ptr->value.i);
2121 sb_add_string (out, buffer);
2122 }
2123 else
2124 {
2125 sb_add_sb (out, &ptr->value.s);
2126 }
2127 }
2128 sb_kill (&condass_acc);
2129 return idx;
2130 }
2131
2132 #define EQ 1
2133 #define NE 2
2134 #define GE 3
2135 #define LT 4
2136 #define LE 5
2137 #define GT 6
2138 #define NEVER 7
2139
2140 static int
2141 whatcond (idx, in, val)
2142 int idx;
2143 sb *in;
2144 int *val;
2145 {
2146 int cond;
2147
2148 idx = sb_skip_white (idx, in);
2149 cond = NEVER;
2150 if (idx + 1 < in->len)
2151 {
2152 char *p;
2153 char a, b;
2154
2155 p = in->ptr + idx;
2156 a = toupper ((unsigned char) p[0]);
2157 b = toupper ((unsigned char) p[1]);
2158 if (a == 'E' && b == 'Q')
2159 cond = EQ;
2160 else if (a == 'N' && b == 'E')
2161 cond = NE;
2162 else if (a == 'L' && b == 'T')
2163 cond = LT;
2164 else if (a == 'L' && b == 'E')
2165 cond = LE;
2166 else if (a == 'G' && b == 'T')
2167 cond = GT;
2168 else if (a == 'G' && b == 'E')
2169 cond = GE;
2170 }
2171 if (cond == NEVER)
2172 {
2173 ERROR ((stderr, "Comparison operator must be one of EQ, NE, LT, LE, GT or GE.\n"));
2174 cond = NEVER;
2175 }
2176 idx = sb_skip_white (idx + 2, in);
2177 *val = cond;
2178 return idx;
2179 }
2180
2181 static int
2182 istrue (idx, in)
2183 int idx;
2184 sb *in;
2185 {
2186 int res;
2187 sb acc_a;
2188 sb cond;
2189 sb acc_b;
2190 sb_new (&acc_a);
2191 sb_new (&cond);
2192 sb_new (&acc_b);
2193 idx = sb_skip_white (idx, in);
2194
2195 if (in->ptr[idx] == '"')
2196 {
2197 int cond;
2198 int same;
2199 /* This is a string comparision */
2200 idx = getstring (idx, in, &acc_a);
2201 idx = whatcond (idx, in, &cond);
2202 idx = getstring (idx, in, &acc_b);
2203 same = acc_a.len == acc_b.len && (strncmp (acc_a.ptr, acc_b.ptr, acc_a.len) == 0);
2204
2205 if (cond != EQ && cond != NE)
2206 {
2207 ERROR ((stderr, "Comparison operator for strings must be EQ or NE\n"));
2208 res = 0;
2209 }
2210 else
2211 res = (cond != EQ) ^ same;
2212 }
2213 else
2214 /* This is a numeric expression */
2215 {
2216 int vala;
2217 int valb;
2218 int cond;
2219 idx = exp_get_abs ("Conditional operator must have absolute operands.\n", idx, in, &vala);
2220 idx = whatcond (idx, in, &cond);
2221 idx = sb_skip_white (idx, in);
2222 if (in->ptr[idx] == '"')
2223 {
2224 WARNING ((stderr, "String compared against expression.\n"));
2225 res = 0;
2226 }
2227 else
2228 {
2229 idx = exp_get_abs ("Conditional operator must have absolute operands.\n", idx, in, &valb);
2230 switch (cond)
2231 {
2232 default:
2233 res = 42;
2234 break;
2235 case EQ:
2236 res = vala == valb;
2237 break;
2238 case NE:
2239 res = vala != valb;
2240 break;
2241 case LT:
2242 res = vala < valb;
2243 break;
2244 case LE:
2245 res = vala <= valb;
2246 break;
2247 case GT:
2248 res = vala > valb;
2249 break;
2250 case GE:
2251 res = vala >= valb;
2252 break;
2253 case NEVER:
2254 res = 0;
2255 break;
2256 }
2257 }
2258 }
2259
2260 sb_kill (&acc_a);
2261 sb_kill (&cond);
2262 sb_kill (&acc_b);
2263 return res;
2264 }
2265
2266 /* .AIF */
2267 static void
2268 do_aif (idx, in)
2269 int idx;
2270 sb *in;
2271 {
2272 if (ifi >= IFNESTING)
2273 {
2274 FATAL ((stderr, "AIF nesting unreasonable.\n"));
2275 }
2276 ifi++;
2277 ifstack[ifi].on = ifstack[ifi-1].on ? istrue (idx, in) : 0;
2278 ifstack[ifi].hadelse = 0;
2279 }
2280
2281
2282 /* .AELSE */
2283 static void
2284 do_aelse ()
2285 {
2286 ifstack[ifi].on = ifstack[ifi-1].on ? !ifstack[ifi].on : 0;
2287 if (ifstack[ifi].hadelse)
2288 {
2289 ERROR ((stderr, "Multiple AELSEs in AIF.\n"));
2290 }
2291 ifstack[ifi].hadelse = 1;
2292 }
2293
2294
2295 /* .AENDI */
2296 static void
2297 do_aendi ()
2298 {
2299 if (ifi != 0)
2300 {
2301 ifi--;
2302 }
2303 else
2304 {
2305 ERROR ((stderr, "AENDI without AIF.\n"));
2306 }
2307 }
2308
2309 static int
2310 condass_on ()
2311 {
2312 return ifstack[ifi].on;
2313 }
2314
2315 /* MRI IFEQ, IFNE, IFLT, IFLE, IFGE, IFGT. */
2316
2317 static void
2318 do_if (idx, in, cond)
2319 int idx;
2320 sb *in;
2321 int cond;
2322 {
2323 int val;
2324 int res;
2325
2326 if (ifi >= IFNESTING)
2327 {
2328 FATAL ((stderr, "IF nesting unreasonable.\n"));
2329 }
2330
2331 idx = exp_get_abs ("Conditional operator must have absolute operands.\n",
2332 idx, in, &val);
2333 switch (cond)
2334 {
2335 default:
2336 case EQ: res = val == 0; break;
2337 case NE: res = val != 0; break;
2338 case LT: res = val < 0; break;
2339 case LE: res = val <= 0; break;
2340 case GE: res = val >= 0; break;
2341 case GT: res = val > 0; break;
2342 }
2343
2344 ifi++;
2345 ifstack[ifi].on = ifstack[ifi-1].on ? res: 0;
2346 ifstack[ifi].hadelse = 0;
2347 }
2348
2349 /* Get a string for the MRI IFC or IFNC pseudo-ops. */
2350
2351 static int
2352 get_mri_string (idx, in, val, terminator)
2353 int idx;
2354 sb *in;
2355 sb *val;
2356 int terminator;
2357 {
2358 idx = sb_skip_white (idx, in);
2359
2360 if (idx < in->len
2361 && in->ptr[idx] == '\'')
2362 {
2363 sb_add_char (val, '\'');
2364 for (++idx; idx < in->len; ++idx)
2365 {
2366 sb_add_char (val, in->ptr[idx]);
2367 if (in->ptr[idx] == '\'')
2368 {
2369 ++idx;
2370 if (idx >= in->len
2371 || in->ptr[idx] != '\'')
2372 break;
2373 }
2374 }
2375 idx = sb_skip_white (idx, in);
2376 }
2377 else
2378 {
2379 int i;
2380
2381 while (idx < in->len
2382 && in->ptr[idx] != terminator)
2383 {
2384 sb_add_char (val, in->ptr[idx]);
2385 ++idx;
2386 }
2387 i = val->len - 1;
2388 while (i >= 0 && ISWHITE (val->ptr[i]))
2389 --i;
2390 val->len = i + 1;
2391 }
2392
2393 return idx;
2394 }
2395
2396 /* MRI IFC, IFNC. */
2397
2398 static void
2399 do_ifc (idx, in, ifnc)
2400 int idx;
2401 sb *in;
2402 int ifnc;
2403 {
2404 sb first;
2405 sb second;
2406 int res;
2407
2408 if (ifi >= IFNESTING)
2409 {
2410 FATAL ((stderr, "IF nesting unreasonable.\n"));
2411 }
2412
2413 sb_new (&first);
2414 sb_new (&second);
2415
2416 idx = get_mri_string (idx, in, &first, ',');
2417
2418 if (idx >= in->len || in->ptr[idx] != ',')
2419 {
2420 ERROR ((stderr, "Bad format for IF or IFNC.\n"));
2421 return;
2422 }
2423
2424 idx = get_mri_string (idx + 1, in, &second, ';');
2425
2426 res = (first.len == second.len
2427 && strncmp (first.ptr, second.ptr, first.len) == 0);
2428 res ^= ifnc;
2429
2430 ifi++;
2431 ifstack[ifi].on = ifstack[ifi-1].on ? res : 0;
2432 ifstack[ifi].hadelse = 0;
2433 }
2434
2435 /* .ENDR */
2436 static void
2437 do_aendr ()
2438 {
2439 if (!mri)
2440 ERROR ((stderr, "AENDR without a AREPEAT.\n"));
2441 else
2442 ERROR ((stderr, "ENDR without a REPT.\n"));
2443 }
2444
2445 /* .AWHILE */
2446
2447 static
2448 void
2449 do_awhile (idx, in)
2450 int idx;
2451 sb *in;
2452 {
2453 int line = linecount ();
2454 sb exp;
2455 sb sub;
2456 int doit;
2457
2458 sb_new (&sub);
2459 sb_new (&exp);
2460
2461 process_assigns (idx, in, &exp);
2462 doit = istrue (0, &exp);
2463
2464 if (! buffer_and_nest ("AWHILE", "AENDW", &sub, get_line))
2465 FATAL ((stderr, "AWHILE without a AENDW at %d.\n", line - 1));
2466
2467 /* Turn
2468 .AWHILE exp
2469 foo
2470 .AENDW
2471 into
2472 foo
2473 .AWHILE exp
2474 foo
2475 .ENDW
2476 */
2477
2478 if (doit)
2479 {
2480 int index = include_next_index ();
2481
2482 sb copy;
2483 sb_new (&copy);
2484 sb_add_sb (&copy, &sub);
2485 sb_add_sb (&copy, in);
2486 sb_add_string (&copy, "\n");
2487 sb_add_sb (&copy, &sub);
2488 sb_add_string (&copy, "\t.AENDW\n");
2489 /* Push another WHILE */
2490 include_buf (&exp, &copy, include_while, index);
2491 sb_kill (&copy);
2492 }
2493 sb_kill (&exp);
2494 sb_kill (&sub);
2495 }
2496
2497
2498 /* .AENDW */
2499
2500 static void
2501 do_aendw ()
2502 {
2503 ERROR ((stderr, "AENDW without a AENDW.\n"));
2504 }
2505
2506
2507 /* .EXITM
2508
2509 Pop things off the include stack until the type and index changes */
2510
2511 static void
2512 do_exitm ()
2513 {
2514 include_type type = sp->type;
2515 if (type == include_repeat
2516 || type == include_while
2517 || type == include_macro)
2518 {
2519 int index = sp->index;
2520 include_pop ();
2521 while (sp->index == index
2522 && sp->type == type)
2523 {
2524 include_pop ();
2525 }
2526 }
2527 }
2528
2529 /* .AREPEAT */
2530
2531 static void
2532 do_arepeat (idx, in)
2533 int idx;
2534 sb *in;
2535 {
2536 int line = linecount ();
2537 sb exp; /* buffer with expression in it */
2538 sb copy; /* expanded repeat block */
2539 sb sub; /* contents of AREPEAT */
2540 int rc;
2541 int ret;
2542 char buffer[30];
2543
2544 sb_new (&exp);
2545 sb_new (&copy);
2546 sb_new (&sub);
2547 process_assigns (idx, in, &exp);
2548 idx = exp_get_abs ("AREPEAT must have absolute operand.\n", 0, &exp, &rc);
2549 if (!mri)
2550 ret = buffer_and_nest ("AREPEAT", "AENDR", &sub, get_line);
2551 else
2552 ret = buffer_and_nest ("REPT", "ENDR", &sub, get_line);
2553 if (! ret)
2554 FATAL ((stderr, "AREPEAT without a AENDR at %d.\n", line - 1));
2555 if (rc > 0)
2556 {
2557 /* Push back the text following the repeat, and another repeat block
2558 so
2559 .AREPEAT 20
2560 foo
2561 .AENDR
2562 gets turned into
2563 foo
2564 .AREPEAT 19
2565 foo
2566 .AENDR
2567 */
2568 int index = include_next_index ();
2569 sb_add_sb (&copy, &sub);
2570 if (rc > 1)
2571 {
2572 if (!mri)
2573 sprintf (buffer, "\t.AREPEAT %d\n", rc - 1);
2574 else
2575 sprintf (buffer, "\tREPT %d\n", rc - 1);
2576 sb_add_string (&copy, buffer);
2577 sb_add_sb (&copy, &sub);
2578 if (!mri)
2579 sb_add_string (&copy, " .AENDR\n");
2580 else
2581 sb_add_string (&copy, " ENDR\n");
2582 }
2583
2584 include_buf (&exp, &copy, include_repeat, index);
2585 }
2586 sb_kill (&exp);
2587 sb_kill (&sub);
2588 sb_kill (&copy);
2589 }
2590
2591 /* .ENDM */
2592
2593 static void
2594 do_endm ()
2595 {
2596 ERROR ((stderr, ".ENDM without a matching .MACRO.\n"));
2597 }
2598
2599 /* MRI IRP pseudo-op. */
2600
2601 static void
2602 do_irp (idx, in, irpc)
2603 int idx;
2604 sb *in;
2605 int irpc;
2606 {
2607 const char *err;
2608 sb out;
2609
2610 sb_new (&out);
2611
2612 err = expand_irp (irpc, idx, in, &out, get_line, comment_char);
2613 if (err != NULL)
2614 ERROR ((stderr, "%s\n", err));
2615
2616 fprintf (outfile, "%s", sb_terminate (&out));
2617
2618 sb_kill (&out);
2619 }
2620
2621 /* MACRO PROCESSING */
2622
2623 /* Parse off LOCAL n1, n2,... Invent a label name for it */
2624 static
2625 void
2626 do_local (idx, line)
2627 int idx;
2628 sb *line;
2629 {
2630 ERROR ((stderr, "LOCAL outside of MACRO"));
2631 }
2632
2633 static void
2634 do_macro (idx, in)
2635 int idx;
2636 sb *in;
2637 {
2638 const char *err;
2639 int line = linecount ();
2640
2641 err = define_macro (idx, in, &label, get_line);
2642 if (err != NULL)
2643 ERROR ((stderr, "macro at line %d: %s\n", line - 1, err));
2644 }
2645
2646 static int
2647 macro_op (idx, in)
2648 int idx;
2649 sb *in;
2650 {
2651 const char *err;
2652 sb out;
2653 sb name;
2654
2655 if (! macro_defined)
2656 return 0;
2657
2658 sb_terminate (in);
2659 if (! check_macro (in->ptr + idx, &out, comment_char, &err))
2660 return 0;
2661
2662 if (err != NULL)
2663 ERROR ((stderr, "%s\n", err));
2664
2665 sb_new (&name);
2666 sb_add_string (&name, "macro expansion");
2667
2668 include_buf (&name, &out, include_macro, include_next_index ());
2669
2670 sb_kill (&name);
2671 sb_kill (&out);
2672
2673 return 1;
2674 }
2675
2676 /* STRING HANDLING */
2677
2678 static int
2679 getstring (idx, in, acc)
2680 int idx;
2681 sb *in;
2682 sb *acc;
2683 {
2684 idx = sb_skip_white (idx, in);
2685
2686 while (idx < in->len
2687 && (in->ptr[idx] == '"'
2688 || in->ptr[idx] == '<'
2689 || (in->ptr[idx] == '\'' && alternate)))
2690 {
2691 if (in->ptr[idx] == '<')
2692 {
2693 if (alternate || mri)
2694 {
2695 int nest = 0;
2696 idx++;
2697 while ((in->ptr[idx] != '>' || nest)
2698 && idx < in->len)
2699 {
2700 if (in->ptr[idx] == '!')
2701 {
2702 idx++ ;
2703 sb_add_char (acc, in->ptr[idx++]);
2704 }
2705 else {
2706 if (in->ptr[idx] == '>')
2707 nest--;
2708 if (in->ptr[idx] == '<')
2709 nest++;
2710 sb_add_char (acc, in->ptr[idx++]);
2711 }
2712 }
2713 idx++;
2714 }
2715 else {
2716 int code;
2717 idx++;
2718 idx = exp_get_abs ("Character code in string must be absolute expression.\n",
2719 idx, in, &code);
2720 sb_add_char (acc, code);
2721
2722 if (in->ptr[idx] != '>')
2723 ERROR ((stderr, "Missing > for character code.\n"));
2724 idx++;
2725 }
2726 }
2727 else if (in->ptr[idx] == '"' || in->ptr[idx] == '\'')
2728 {
2729 char tchar = in->ptr[idx];
2730 idx++;
2731 while (idx < in->len)
2732 {
2733 if (alternate && in->ptr[idx] == '!')
2734 {
2735 idx++ ;
2736 sb_add_char (acc, in->ptr[idx++]);
2737 }
2738 else {
2739 if (in->ptr[idx] == tchar)
2740 {
2741 idx++;
2742 if (idx >= in->len || in->ptr[idx] != tchar)
2743 break;
2744 }
2745 sb_add_char (acc, in->ptr[idx]);
2746 idx++;
2747 }
2748 }
2749 }
2750 }
2751
2752 return idx;
2753 }
2754
2755 /* .SDATA[C|Z] <string> */
2756
2757 static
2758 void
2759 do_sdata (idx, in, type)
2760 int idx;
2761 sb *in;
2762 int type;
2763 {
2764 int nc = 0;
2765 int pidx = -1;
2766 sb acc;
2767 sb_new (&acc);
2768 fprintf (outfile, ".byte\t");
2769
2770 while (!eol (idx, in))
2771 {
2772 int i;
2773 sb_reset (&acc);
2774 idx = sb_skip_white (idx, in);
2775 while (!eol (idx, in))
2776 {
2777 pidx = idx = get_any_string (idx, in, &acc, 0, 1);
2778 if (type == 'c')
2779 {
2780 if (acc.len > 255)
2781 {
2782 ERROR ((stderr, "string for SDATAC longer than 255 characters (%d).\n", acc.len));
2783 }
2784 fprintf (outfile, "%d", acc.len);
2785 nc = 1;
2786 }
2787
2788 for (i = 0; i < acc.len; i++)
2789 {
2790 if (nc)
2791 {
2792 fprintf (outfile, ",");
2793 }
2794 fprintf (outfile, "%d", acc.ptr[i]);
2795 nc = 1;
2796 }
2797
2798 if (type == 'z')
2799 {
2800 if (nc)
2801 fprintf (outfile, ",");
2802 fprintf (outfile, "0");
2803 }
2804 idx = sb_skip_comma (idx, in);
2805 if (idx == pidx) break;
2806 }
2807 if (!alternate && in->ptr[idx] != ',' && idx != in->len)
2808 {
2809 fprintf (outfile, "\n");
2810 ERROR ((stderr, "illegal character in SDATA line (0x%x).\n", in->ptr[idx]));
2811 break;
2812 }
2813 idx++;
2814 }
2815 sb_kill (&acc);
2816 fprintf (outfile, "\n");
2817 }
2818
2819 /* .SDATAB <count> <string> */
2820
2821 static void
2822 do_sdatab (idx, in)
2823 int idx;
2824 sb *in;
2825 {
2826 int repeat;
2827 int i;
2828 sb acc;
2829 sb_new (&acc);
2830
2831 idx = exp_get_abs ("Must have absolute SDATAB repeat count.\n", idx, in, &repeat);
2832 if (repeat <= 0)
2833 {
2834 ERROR ((stderr, "Must have positive SDATAB repeat count (%d).\n", repeat));
2835 repeat = 1;
2836 }
2837
2838 idx = sb_skip_comma (idx, in);
2839 idx = getstring (idx, in, &acc);
2840
2841 for (i = 0; i < repeat; i++)
2842 {
2843 if (i)
2844 fprintf (outfile, "\t");
2845 fprintf (outfile, ".byte\t");
2846 sb_print (outfile, &acc);
2847 fprintf (outfile, "\n");
2848 }
2849 sb_kill (&acc);
2850
2851 }
2852
2853 static int
2854 new_file (name)
2855 const char *name;
2856 {
2857 FILE *newone = fopen (name, "r");
2858 if (!newone)
2859 return 0;
2860
2861 if (isp == MAX_INCLUDES)
2862 FATAL ((stderr, "Unreasonable include depth (%ld).\n", (long) isp));
2863
2864 sp++;
2865 sp->handle = newone;
2866
2867 sb_new (&sp->name);
2868 sb_add_string (&sp->name, name);
2869
2870 sp->linecount = 1;
2871 sp->pushback_index = 0;
2872 sp->type = include_file;
2873 sp->index = 0;
2874 sb_new (&sp->pushback);
2875 return 1;
2876 }
2877
2878 static void
2879 do_include (idx, in)
2880 int idx;
2881 sb *in;
2882 {
2883 sb t;
2884 sb cat;
2885 include_path *includes;
2886
2887 sb_new (&t);
2888 sb_new (&cat);
2889
2890 if (! mri)
2891 idx = getstring (idx, in, &t);
2892 else
2893 {
2894 idx = sb_skip_white (idx, in);
2895 while (idx < in->len && ! ISWHITE (in->ptr[idx]))
2896 {
2897 sb_add_char (&t, in->ptr[idx]);
2898 ++idx;
2899 }
2900 }
2901
2902 for (includes = paths_head; includes; includes = includes->next)
2903 {
2904 sb_reset (&cat);
2905 sb_add_sb (&cat, &includes->path);
2906 sb_add_char (&cat, '/');
2907 sb_add_sb (&cat, &t);
2908 if (new_file (sb_name (&cat)))
2909 {
2910 break;
2911 }
2912 }
2913 if (!includes)
2914 {
2915 if (! new_file (sb_name (&t)))
2916 FATAL ((stderr, "Can't open include file `%s'.\n", sb_name (&t)));
2917 }
2918 sb_kill (&cat);
2919 sb_kill (&t);
2920 }
2921
2922 static void
2923 include_pop ()
2924 {
2925 if (sp != include_stack)
2926 {
2927 if (sp->handle)
2928 fclose (sp->handle);
2929 sp--;
2930 }
2931 }
2932
2933 /* Get the next character from the include stack. If there's anything
2934 in the pushback buffer, take that first. If we're at eof, pop from
2935 the stack and try again. Keep the linecount up to date. */
2936
2937 static int
2938 get ()
2939 {
2940 int r;
2941
2942 if (sp->pushback.len != sp->pushback_index)
2943 {
2944 r = (char) (sp->pushback.ptr[sp->pushback_index++]);
2945 /* When they've all gone, reset the pointer */
2946 if (sp->pushback_index == sp->pushback.len)
2947 {
2948 sp->pushback.len = 0;
2949 sp->pushback_index = 0;
2950 }
2951 }
2952 else if (sp->handle)
2953 {
2954 r = getc (sp->handle);
2955 }
2956 else
2957 r = EOF;
2958
2959 if (r == EOF && isp)
2960 {
2961 include_pop ();
2962 r = get ();
2963 while (r == EOF && isp)
2964 {
2965 include_pop ();
2966 r = get ();
2967 }
2968 return r;
2969 }
2970 if (r == '\n')
2971 {
2972 sp->linecount++;
2973 }
2974
2975 return r;
2976 }
2977
2978 static int
2979 linecount ()
2980 {
2981 return sp->linecount;
2982 }
2983
2984 static int
2985 include_next_index ()
2986 {
2987 static int index;
2988 if (!unreasonable
2989 && index > MAX_REASONABLE)
2990 FATAL ((stderr, "Unreasonable expansion (-u turns off check).\n"));
2991 return ++index;
2992 }
2993
2994
2995 /* Initialize the chartype vector. */
2996
2997 static void
2998 chartype_init ()
2999 {
3000 int x;
3001 for (x = 0; x < 256; x++)
3002 {
3003 if (isalpha (x) || x == '_' || x == '$')
3004 chartype[x] |= FIRSTBIT;
3005
3006 if (mri && x == '.')
3007 chartype[x] |= FIRSTBIT;
3008
3009 if (isdigit (x) || isalpha (x) || x == '_' || x == '$')
3010 chartype[x] |= NEXTBIT;
3011
3012 if (x == ' ' || x == '\t' || x == ',' || x == '"' || x == ';'
3013 || x == '"' || x == '<' || x == '>' || x == ')' || x == '(')
3014 chartype[x] |= SEPBIT;
3015
3016 if (x == 'b' || x == 'B'
3017 || x == 'q' || x == 'Q'
3018 || x == 'h' || x == 'H'
3019 || x == 'd' || x == 'D')
3020 chartype [x] |= BASEBIT;
3021
3022 if (x == ' ' || x == '\t')
3023 chartype[x] |= WHITEBIT;
3024
3025 if (x == comment_char)
3026 chartype[x] |= COMMENTBIT;
3027 }
3028 }
3029
3030
3031
3032 /* What to do with all the keywords */
3033 #define PROCESS 0x1000 /* Run substitution over the line */
3034 #define LAB 0x2000 /* Spit out the label */
3035
3036 #define K_EQU (PROCESS|1)
3037 #define K_ASSIGN (PROCESS|2)
3038 #define K_REG (PROCESS|3)
3039 #define K_ORG (PROCESS|4)
3040 #define K_RADIX (PROCESS|5)
3041 #define K_DATA (LAB|PROCESS|6)
3042 #define K_DATAB (LAB|PROCESS|7)
3043 #define K_SDATA (LAB|PROCESS|8)
3044 #define K_SDATAB (LAB|PROCESS|9)
3045 #define K_SDATAC (LAB|PROCESS|10)
3046 #define K_SDATAZ (LAB|PROCESS|11)
3047 #define K_RES (LAB|PROCESS|12)
3048 #define K_SRES (LAB|PROCESS|13)
3049 #define K_SRESC (LAB|PROCESS|14)
3050 #define K_SRESZ (LAB|PROCESS|15)
3051 #define K_EXPORT (LAB|PROCESS|16)
3052 #define K_GLOBAL (LAB|PROCESS|17)
3053 #define K_PRINT (LAB|PROCESS|19)
3054 #define K_FORM (LAB|PROCESS|20)
3055 #define K_HEADING (LAB|PROCESS|21)
3056 #define K_PAGE (LAB|PROCESS|22)
3057 #define K_IMPORT (LAB|PROCESS|23)
3058 #define K_PROGRAM (LAB|PROCESS|24)
3059 #define K_END (PROCESS|25)
3060 #define K_INCLUDE (PROCESS|26)
3061 #define K_IGNORED (PROCESS|27)
3062 #define K_ASSIGNA (PROCESS|28)
3063 #define K_ASSIGNC (29)
3064 #define K_AIF (PROCESS|30)
3065 #define K_AELSE (PROCESS|31)
3066 #define K_AENDI (PROCESS|32)
3067 #define K_AREPEAT (PROCESS|33)
3068 #define K_AENDR (PROCESS|34)
3069 #define K_AWHILE (35)
3070 #define K_AENDW (PROCESS|36)
3071 #define K_EXITM (37)
3072 #define K_MACRO (PROCESS|38)
3073 #define K_ENDM (39)
3074 #define K_ALIGN (PROCESS|LAB|40)
3075 #define K_ALTERNATE (41)
3076 #define K_DB (LAB|PROCESS|42)
3077 #define K_DW (LAB|PROCESS|43)
3078 #define K_DL (LAB|PROCESS|44)
3079 #define K_LOCAL (45)
3080 #define K_IFEQ (PROCESS|46)
3081 #define K_IFNE (PROCESS|47)
3082 #define K_IFLT (PROCESS|48)
3083 #define K_IFLE (PROCESS|49)
3084 #define K_IFGE (PROCESS|50)
3085 #define K_IFGT (PROCESS|51)
3086 #define K_IFC (PROCESS|52)
3087 #define K_IFNC (PROCESS|53)
3088 #define K_IRP (PROCESS|54)
3089 #define K_IRPC (PROCESS|55)
3090
3091
3092 struct keyword
3093 {
3094 char *name;
3095 int code;
3096 int extra;
3097 };
3098
3099 static struct keyword kinfo[] =
3100 {
3101 { "EQU", K_EQU, 0 },
3102 { "ALTERNATE", K_ALTERNATE, 0 },
3103 { "ASSIGN", K_ASSIGN, 0 },
3104 { "REG", K_REG, 0 },
3105 { "ORG", K_ORG, 0 },
3106 { "RADIX", K_RADIX, 0 },
3107 { "DATA", K_DATA, 0 },
3108 { "DB", K_DB, 0 },
3109 { "DW", K_DW, 0 },
3110 { "DL", K_DL, 0 },
3111 { "DATAB", K_DATAB, 0 },
3112 { "SDATA", K_SDATA, 0 },
3113 { "SDATAB", K_SDATAB, 0 },
3114 { "SDATAZ", K_SDATAZ, 0 },
3115 { "SDATAC", K_SDATAC, 0 },
3116 { "RES", K_RES, 0 },
3117 { "SRES", K_SRES, 0 },
3118 { "SRESC", K_SRESC, 0 },
3119 { "SRESZ", K_SRESZ, 0 },
3120 { "EXPORT", K_EXPORT, 0 },
3121 { "GLOBAL", K_GLOBAL, 0 },
3122 { "PRINT", K_PRINT, 0 },
3123 { "FORM", K_FORM, 0 },
3124 { "HEADING", K_HEADING, 0 },
3125 { "PAGE", K_PAGE, 0 },
3126 { "PROGRAM", K_IGNORED, 0 },
3127 { "END", K_END, 0 },
3128 { "INCLUDE", K_INCLUDE, 0 },
3129 { "ASSIGNA", K_ASSIGNA, 0 },
3130 { "ASSIGNC", K_ASSIGNC, 0 },
3131 { "AIF", K_AIF, 0 },
3132 { "AELSE", K_AELSE, 0 },
3133 { "AENDI", K_AENDI, 0 },
3134 { "AREPEAT", K_AREPEAT, 0 },
3135 { "AENDR", K_AENDR, 0 },
3136 { "EXITM", K_EXITM, 0 },
3137 { "MACRO", K_MACRO, 0 },
3138 { "ENDM", K_ENDM, 0 },
3139 { "AWHILE", K_AWHILE, 0 },
3140 { "ALIGN", K_ALIGN, 0 },
3141 { "AENDW", K_AENDW, 0 },
3142 { "ALTERNATE", K_ALTERNATE, 0 },
3143 { "LOCAL", K_LOCAL, 0 },
3144 { NULL, 0, 0 }
3145 };
3146
3147 /* Although the conditional operators are handled by gas, we need to
3148 handle them here as well, in case they are used in a recursive
3149 macro to end the recursion. */
3150
3151 static struct keyword mrikinfo[] =
3152 {
3153 { "IFEQ", K_IFEQ, 0 },
3154 { "IFNE", K_IFNE, 0 },
3155 { "IFLT", K_IFLT, 0 },
3156 { "IFLE", K_IFLE, 0 },
3157 { "IFGE", K_IFGE, 0 },
3158 { "IFGT", K_IFGT, 0 },
3159 { "IFC", K_IFC, 0 },
3160 { "IFNC", K_IFNC, 0 },
3161 { "ELSEC", K_AELSE, 0 },
3162 { "ENDC", K_AENDI, 0 },
3163 { "MEXIT", K_EXITM, 0 },
3164 { "REPT", K_AREPEAT, 0 },
3165 { "IRP", K_IRP, 0 },
3166 { "IRPC", K_IRPC, 0 },
3167 { "ENDR", K_AENDR, 0 },
3168 { NULL, 0, 0 }
3169 };
3170
3171 /* Look for a pseudo op on the line. If one's there then call
3172 its handler. */
3173
3174 static int
3175 process_pseudo_op (idx, line, acc)
3176 int idx;
3177 sb *line;
3178 sb *acc;
3179 {
3180 int oidx = idx;
3181
3182 if (line->ptr[idx] == '.' || alternate || mri)
3183 {
3184 /* Scan forward and find pseudo name */
3185 char *in;
3186 hash_entry *ptr;
3187
3188 char *s;
3189 char *e;
3190 if (line->ptr[idx] == '.')
3191 idx++;
3192 in = line->ptr + idx;
3193 s = in;
3194 e = s;
3195 sb_reset (acc);
3196
3197 while (idx < line->len && *e && ISFIRSTCHAR (*e))
3198 {
3199 sb_add_char (acc, *e);
3200 e++;
3201 idx++;
3202 }
3203
3204 ptr = hash_lookup (&keyword_hash_table, acc);
3205
3206 if (!ptr)
3207 {
3208 #if 0
3209 /* This one causes lots of pain when trying to preprocess
3210 ordinary code */
3211 WARNING ((stderr, "Unrecognised pseudo op `%s'.\n", sb_name (acc)));
3212 #endif
3213 return 0;
3214 }
3215 if (ptr->value.i & LAB)
3216 { /* output the label */
3217 if (label.len)
3218 {
3219 fprintf (outfile, "%s:\t", sb_name (&label));
3220 }
3221 else
3222 fprintf (outfile, "\t");
3223 }
3224
3225 if (mri && ptr->value.i == K_END)
3226 {
3227 sb t;
3228
3229 sb_new (&t);
3230 sb_add_buffer (&t, line->ptr + oidx, idx - oidx);
3231 fprintf (outfile, "\t%s", sb_name (&t));
3232 sb_kill (&t);
3233 }
3234
3235 if (ptr->value.i & PROCESS)
3236 {
3237 /* Polish the rest of the line before handling the pseudo op */
3238 #if 0
3239 strip_comments(line);
3240 #endif
3241 sb_reset (acc);
3242 process_assigns (idx, line, acc);
3243 sb_reset(line);
3244 change_base (0, acc, line);
3245 idx = 0;
3246 }
3247 if (!condass_on ())
3248 {
3249 switch (ptr->value.i)
3250 {
3251 case K_AIF:
3252 do_aif (idx, line);
3253 break;
3254 case K_AELSE:
3255 do_aelse ();
3256 break;
3257 case K_AENDI:
3258 do_aendi ();
3259 break;
3260 }
3261 return 1;
3262 }
3263 else
3264 {
3265 switch (ptr->value.i)
3266 {
3267 case K_ALTERNATE:
3268 alternate = 1;
3269 macro_init (1, mri, 0, exp_get_abs);
3270 return 1;
3271 case K_AELSE:
3272 do_aelse ();
3273 return 1;
3274 case K_AENDI:
3275 do_aendi ();
3276 return 1;
3277 case K_ORG:
3278 ERROR ((stderr, "ORG command not allowed.\n"));
3279 break;
3280 case K_RADIX:
3281 do_radix (line);
3282 return 1;
3283 case K_DB:
3284 do_data (idx, line, 1);
3285 return 1;
3286 case K_DW:
3287 do_data (idx, line, 2);
3288 return 1;
3289 case K_DL:
3290 do_data (idx, line, 4);
3291 return 1;
3292 case K_DATA:
3293 do_data (idx, line, 0);
3294 return 1;
3295 case K_DATAB:
3296 do_datab (idx, line);
3297 return 1;
3298 case K_SDATA:
3299 do_sdata (idx, line, 0);
3300 return 1;
3301 case K_SDATAB:
3302 do_sdatab (idx, line);
3303 return 1;
3304 case K_SDATAC:
3305 do_sdata (idx, line, 'c');
3306 return 1;
3307 case K_SDATAZ:
3308 do_sdata (idx, line, 'z');
3309 return 1;
3310 case K_ASSIGN:
3311 do_assign (1, 0, line);
3312 return 1;
3313 case K_AIF:
3314 do_aif (idx, line);
3315 return 1;
3316 case K_AREPEAT:
3317 do_arepeat (idx, line);
3318 return 1;
3319 case K_AENDW:
3320 do_aendw ();
3321 return 1;
3322 case K_AWHILE:
3323 do_awhile (idx, line);
3324 return 1;
3325 case K_AENDR:
3326 do_aendr ();
3327 return 1;
3328 case K_EQU:
3329 do_assign (0, idx, line);
3330 return 1;
3331 case K_ALIGN:
3332 do_align (idx, line);
3333 return 1;
3334 case K_RES:
3335 do_res (idx, line, 0);
3336 return 1;
3337 case K_SRES:
3338 do_res (idx, line, 's');
3339 return 1;
3340 case K_INCLUDE:
3341 do_include (idx, line);
3342 return 1;
3343 case K_LOCAL:
3344 do_local (idx, line);
3345 return 1;
3346 case K_MACRO:
3347 do_macro (idx, line);
3348 return 1;
3349 case K_ENDM:
3350 do_endm ();
3351 return 1;
3352 case K_SRESC:
3353 do_res (idx, line, 'c');
3354 return 1;
3355 case K_PRINT:
3356 do_print (idx, line);
3357 return 1;
3358 case K_FORM:
3359 do_form (idx, line);
3360 return 1;
3361 case K_HEADING:
3362 do_heading (idx, line);
3363 return 1;
3364 case K_PAGE:
3365 do_page ();
3366 return 1;
3367 case K_GLOBAL:
3368 case K_EXPORT:
3369 do_export (line);
3370 return 1;
3371 case K_IMPORT:
3372 return 1;
3373 case K_SRESZ:
3374 do_res (idx, line, 'z');
3375 return 1;
3376 case K_IGNORED:
3377 return 1;
3378 case K_END:
3379 do_end (line);
3380 return 1;
3381 case K_ASSIGNA:
3382 do_assigna (idx, line);
3383 return 1;
3384 case K_ASSIGNC:
3385 do_assignc (idx, line);
3386 return 1;
3387 case K_EXITM:
3388 do_exitm ();
3389 return 1;
3390 case K_REG:
3391 do_reg (idx, line);
3392 return 1;
3393 case K_IFEQ:
3394 do_if (idx, line, EQ);
3395 return 1;
3396 case K_IFNE:
3397 do_if (idx, line, NE);
3398 return 1;
3399 case K_IFLT:
3400 do_if (idx, line, LT);
3401 return 1;
3402 case K_IFLE:
3403 do_if (idx, line, LE);
3404 return 1;
3405 case K_IFGE:
3406 do_if (idx, line, GE);
3407 return 1;
3408 case K_IFGT:
3409 do_if (idx, line, GT);
3410 return 1;
3411 case K_IFC:
3412 do_ifc (idx, line, 0);
3413 return 1;
3414 case K_IFNC:
3415 do_ifc (idx, line, 1);
3416 return 1;
3417 case K_IRP:
3418 do_irp (idx, line, 0);
3419 return 1;
3420 case K_IRPC:
3421 do_irp (idx, line, 1);
3422 return 1;
3423 }
3424 }
3425 }
3426 return 0;
3427 }
3428
3429
3430
3431 /* Add a keyword to the hash table. */
3432
3433 static void
3434 add_keyword (name, code)
3435 const char *name;
3436 int code;
3437 {
3438 sb label;
3439 int j;
3440
3441 sb_new (&label);
3442 sb_add_string (&label, name);
3443
3444 hash_add_to_int_table (&keyword_hash_table, &label, code);
3445
3446 sb_reset (&label);
3447 for (j = 0; name[j]; j++)
3448 sb_add_char (&label, name[j] - 'A' + 'a');
3449 hash_add_to_int_table (&keyword_hash_table, &label, code);
3450
3451 sb_kill (&label);
3452 }
3453
3454 /* Build the keyword hash table - put each keyword in the table twice,
3455 once upper and once lower case.*/
3456
3457 static void
3458 process_init ()
3459 {
3460 int i;
3461
3462 for (i = 0; kinfo[i].name; i++)
3463 add_keyword (kinfo[i].name, kinfo[i].code);
3464
3465 if (mri)
3466 {
3467 for (i = 0; mrikinfo[i].name; i++)
3468 add_keyword (mrikinfo[i].name, mrikinfo[i].code);
3469 }
3470 }
3471
3472
3473 static void
3474 do_define (string)
3475 const char *string;
3476 {
3477 sb label;
3478 int res = 1;
3479 hash_entry *ptr;
3480 sb_new (&label);
3481
3482
3483 while (*string)
3484 {
3485 if (*string == '=')
3486 {
3487 sb value;
3488 sb_new (&value);
3489 string++;
3490 while (*string)
3491 {
3492 sb_add_char (&value, *string);
3493 string++;
3494 }
3495 exp_get_abs ("Invalid expression on command line.\n", 0, &value, &res);
3496 sb_kill (&value);
3497 break;
3498 }
3499 sb_add_char (&label, *string);
3500
3501 string ++;
3502 }
3503
3504 ptr = hash_create (&vars, &label);
3505 free_old_entry (ptr);
3506 ptr->type = hash_integer;
3507 ptr->value.i = res;
3508 sb_kill (&label);
3509 }
3510 char *program_name;
3511
3512 /* The list of long options. */
3513 static struct option long_options[] =
3514 {
3515 { "alternate", no_argument, 0, 'a' },
3516 { "include", required_argument, 0, 'I' },
3517 { "commentchar", required_argument, 0, 'c' },
3518 { "copysource", no_argument, 0, 's' },
3519 { "debug", no_argument, 0, 'd' },
3520 { "help", no_argument, 0, 'h' },
3521 { "mri", no_argument, 0, 'M' },
3522 { "output", required_argument, 0, 'o' },
3523 { "print", no_argument, 0, 'p' },
3524 { "unreasonable", no_argument, 0, 'u' },
3525 { "version", no_argument, 0, 'v' },
3526 { "define", required_argument, 0, 'd' },
3527 { NULL, no_argument, 0, 0 }
3528 };
3529
3530 /* Show a usage message and exit. */
3531 static void
3532 show_usage (file, status)
3533 FILE *file;
3534 int status;
3535 {
3536 fprintf (file, "\
3537 Usage: %s \n\
3538 [-a] [--alternate] enter alternate macro mode\n\
3539 [-c char] [--commentchar char] change the comment character from !\n\
3540 [-d] [--debug] print some debugging info\n\
3541 [-h] [--help] print this message\n\
3542 [-M] [--mri] enter MRI compatibility mode\n\
3543 [-o out] [--output out] set the output file\n\
3544 [-p] [--print] print line numbers\n", program_name);
3545 fprintf (file, "\
3546 [-s] [--copysource] copy source through as comments \n\
3547 [-u] [--unreasonable] allow unreasonable nesting\n\
3548 [-v] [--version] print the program version\n\
3549 [-Dname=value] create preprocessor variable called name, with value\n\
3550 [-Ipath] add to include path list\n\
3551 [in-file]\n");
3552 exit (status);
3553 }
3554
3555 /* Display a help message and exit. */
3556 static void
3557 show_help ()
3558 {
3559 printf ("%s: Gnu Assembler Macro Preprocessor\n",
3560 program_name);
3561 show_usage (stdout, 0);
3562 }
3563
3564 int
3565 main (argc, argv)
3566 int argc;
3567 char **argv;
3568 {
3569 int opt;
3570 char *out_name = 0;
3571 sp = include_stack;
3572
3573 ifstack[0].on = 1;
3574 ifi = 0;
3575
3576
3577
3578 program_name = argv[0];
3579 xmalloc_set_program_name (program_name);
3580
3581 hash_new_table (101, &keyword_hash_table);
3582 hash_new_table (101, &assign_hash_table);
3583 hash_new_table (101, &vars);
3584
3585 sb_new (&label);
3586
3587 while ((opt = getopt_long (argc, argv, "I:sdhavc:upo:D:M", long_options,
3588 (int *) NULL))
3589 != EOF)
3590 {
3591 switch (opt)
3592 {
3593 case 'o':
3594 out_name = optarg;
3595 break;
3596 case 'u':
3597 unreasonable = 1;
3598 break;
3599 case 'I':
3600 {
3601 include_path *p = (include_path *) xmalloc (sizeof (include_path));
3602 sb_new (&p->path);
3603 sb_add_string (&p->path, optarg);
3604 if (paths_tail)
3605 paths_tail->next = p;
3606 else
3607 paths_head = p;
3608 paths_tail = p;
3609 }
3610 break;
3611 case 'p':
3612 print_line_number = 1;
3613 break;
3614 case 'c':
3615 comment_char = optarg[0];
3616 break;
3617 case 'a':
3618 alternate = 1;
3619 break;
3620 case 's':
3621 copysource = 1;
3622 break;
3623 case 'd':
3624 stats = 1;
3625 break;
3626 case 'D':
3627 do_define (optarg);
3628 break;
3629 case 'M':
3630 mri = 1;
3631 comment_char = ';';
3632 break;
3633 case 'h':
3634 show_help ();
3635 /*NOTREACHED*/
3636 case 'v':
3637 printf ("GNU %s version %s\n", program_name, program_version);
3638 exit (0);
3639 /*NOTREACHED*/
3640 case 0:
3641 break;
3642 default:
3643 show_usage (stderr, 1);
3644 /*NOTREACHED*/
3645 }
3646 }
3647
3648 process_init ();
3649
3650 macro_init (alternate, mri, 0, exp_get_abs);
3651
3652 if (out_name) {
3653 outfile = fopen (out_name, "w");
3654 if (!outfile)
3655 {
3656 fprintf (stderr, "%s: Can't open output file `%s'.\n",
3657 program_name, out_name);
3658 exit (1);
3659 }
3660 }
3661 else {
3662 outfile = stdout;
3663 }
3664
3665 chartype_init ();
3666 if (!outfile)
3667 outfile = stdout;
3668
3669 /* Process all the input files */
3670
3671 while (optind < argc)
3672 {
3673 if (new_file (argv[optind]))
3674 {
3675 process_file ();
3676 }
3677 else
3678 {
3679 fprintf (stderr, "%s: Can't open input file `%s'.\n",
3680 program_name, argv[optind]);
3681 exit (1);
3682 }
3683 optind++;
3684 }
3685
3686 quit ();
3687 return 0;
3688 }
3689
3690 /* This function is used because an abort in some of the other files
3691 may be compiled into as_abort because they include as.h. */
3692
3693 void
3694 as_abort (file, line, fn)
3695 const char *file, *fn;
3696 int line;
3697 {
3698 fprintf (stderr, "Internal error, aborting at %s line %d", file, line);
3699 if (fn)
3700 fprintf (stderr, " in %s", fn);
3701 fprintf (stderr, "\nPlease report this bug.\n");
3702 exit (1);
3703 }
This page took 0.208843 seconds and 4 git commands to generate.