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