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