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