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