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