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