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