]> git.pld-linux.org Git - packages/binutils.git/blame - binutils-gasp.patch
- updated to 2.18.50.0.9.
[packages/binutils.git] / binutils-gasp.patch
CommitLineData
3e3b8df7
PS
1--- binutils-2.17.50.0.13/gas/Makefile.am.orig 2007-03-16 16:48:29.000000000 +0100
2+++ binutils-2.17.50.0.13/gas/Makefile.am 2007-03-16 20:26:20.200480821 +0100
3@@ -199,7 +199,7 @@
2859501d
JB
4 symbols.c \
5 write.c
6
8adb9bcd
AM
7-CFILES = $(GAS_CFILES) itbl-ops.c cgen.c
8+CFILES = $(GAS_CFILES) gasp.c itbl-ops.c cgen.c
2859501d
JB
9
10 HFILES = \
11 as.h \
3e3b8df7 12@@ -455,7 +455,8 @@
2859501d
JB
13
14 # Note: GASP is now deprecated and has been removed. It is still
15 # available in the CVS archive or older binutils releases if it is needed.
16-noinst_PROGRAMS = as-new
17+# ...and it is needed for few packages in distribution.
18+noinst_PROGRAMS = as-new gasp-new
19 noinst_SCRIPTS = $(GDBINIT)
20 EXTRA_SCRIPTS = .gdbinit
21
3e3b8df7 22@@ -517,6 +518,10 @@
2859501d
JB
23 as.h asintl.h bignum.h bit_fix.h config.h emul.h expr.h flonum.h \
24 frags.h hash.h listing.h obj.h read.h symbols.h tc.h write.h
25
26+gasp_new_SOURCES = gasp.c macro.c sb.c hash.c
27+gasp_new_LDADD = ../libiberty/libiberty.a $(INTLLIBS)
28+gasp_new_DEPENDENCIES = ../libiberty/libiberty.a $(INTLDEPS)
29+
e85a30b2
AM
30 EXPECT = expect
31 RUNTEST = runtest
32 RUNTESTFLAGS=
3e3b8df7 33@@ -2146,6 +2151,8 @@
e78d5526
JB
34 subsegs.h struc-symbol.h
35 write.o: write.c subsegs.h $(INCDIR)/obstack.h output-file.h \
3e3b8df7 36 dwarf2dbg.h $(BFDDIR)/libbfd.h $(INCDIR)/hashtab.h
2859501d 37+gasp.o: gasp.c $(INCDIR)/getopt.h $(INCDIR)/safe-ctype.h \
3e3b8df7 38+ sb.h macro.h $(INCDIR)/xregex.h $(INCDIR)/xregex2.h
e78d5526
JB
39 itbl-ops.o: itbl-ops.c itbl-ops.h
40 e-crisaout.o: $(srcdir)/config/e-crisaout.c emul-target.h
41 e-criself.o: $(srcdir)/config/e-criself.c emul-target.h
3e3b8df7
PS
42--- binutils-2.17.50.0.13/gas/doc/Makefile.am.orig 2007-03-16 16:48:29.000000000 +0100
43+++ binutils-2.17.50.0.13/gas/doc/Makefile.am 2007-03-16 20:27:05.810679469 +0100
ca25d6cc
PS
44@@ -15,7 +15,7 @@
45
46 man_MANS = as.1
47
98acf085 48-info_TEXINFOS = as.texinfo
ca25d6cc
PS
49+info_TEXINFOS = as.texinfo gasp.texinfo
50 as_TEXINFOS = asconfig.texi $(CPU_DOCS)
51
52 AM_MAKEINFOFLAGS = -I "$(srcdir)" -I "$(top_srcdir)/../libiberty" \
e85a30b2
AM
53--- binutils-2.16.91.0.2.org/gas/doc/gasp.texinfo 1970-01-01 00:00:00.000000000 +0000
54+++ binutils-2.16.91.0.2/gas/doc/gasp.texinfo 2005-07-21 18:31:04.000000000 +0000
2859501d
JB
55@@ -0,0 +1,1456 @@
56+\input texinfo @c -*- Texinfo -*-
57+@setfilename gasp.info
58+@c
59+@c This file documents the assembly preprocessor "GASP"
60+@c
61+@c Copyright 1994, 1995, 2000, 2002 Free Software Foundation, Inc.
62+@c
63+@c Permission is granted to copy, distribute and/or modify this document
64+@c under the terms of the GNU Free Documentation License, Version 1.1
65+@c or any later version published by the Free Software Foundation;
66+@c with no Invariant Sections, with no Front-Cover Texts, and with no
67+@c Back-Cover Texts. A copy of the license is included in the
68+@c section entitled "GNU Free Documentation License".
69+
70+@ifinfo
71+@format
72+START-INFO-DIR-ENTRY
73+* gasp: (gasp). The GNU Assembler Preprocessor
74+END-INFO-DIR-ENTRY
75+@end format
76+@end ifinfo
77+
78+@syncodeindex ky cp
79+@syncodeindex fn cp
80+
81+@finalout
82+@setchapternewpage odd
83+@settitle GASP
84+@titlepage
85+@c FIXME boring title
86+@title GASP, an assembly preprocessor
87+@subtitle for GASP version 1
88+@sp 1
89+@subtitle March 1994
90+@author Roland Pesch
91+@page
92+
93+@tex
94+{\parskip=0pt \hfill Cygnus Support\par
95+}
96+@end tex
97+
98+@vskip 0pt plus 1filll
99+Copyright @copyright{} 1994, 1995, 2000, 2002 Free Software Foundation, Inc.
100+
101+ Permission is granted to copy, distribute and/or modify this document
102+ under the terms of the GNU Free Documentation License, Version 1.1
103+ or any later version published by the Free Software Foundation;
104+ with no Invariant Sections, with no Front-Cover Texts, and with no
105+ Back-Cover Texts. A copy of the license is included in the
106+ section entitled "GNU Free Documentation License".
107+
108+@end titlepage
109+
110+@ifinfo
111+Copyright @copyright{} 1994, 1995, 2000, 2002 Free Software Foundation, Inc.
112+
113+@ignore
114+Permission is granted to process this file through TeX and print the
115+results, provided the printed document carries a copying permission
116+notice identical to this one except for the removal of this paragraph
117+(this paragraph not being relevant to the printed manual).
118+@end ignore
119+
120+ Permission is granted to copy, distribute and/or modify this document
121+ under the terms of the GNU Free Documentation License, Version 1.1
122+ or any later version published by the Free Software Foundation;
123+ with no Invariant Sections, with no Front-Cover Texts, and with no
124+ Back-Cover Texts. A copy of the license is included in the
125+ section entitled "GNU Free Documentation License".
126+
127+
128+@node Top
129+@top GASP
130+
131+GASP is a preprocessor for assembly programs.
132+
133+This file describes version 1 of GASP.
134+
135+Steve Chamberlain wrote GASP; Roland Pesch wrote this manual.
136+
137+@menu
138+* Overview:: What is GASP?
139+* Invoking GASP:: Command line options.
140+* Commands:: Preprocessor commands.
141+* GNU Free Documentation License:: GNU Free Documentation License
142+* Index:: Index.
143+@end menu
144+@end ifinfo
145+
146+@node Overview
147+@chapter What is GASP?
148+
149+The primary purpose of the @sc{gnu} assembler is to assemble the output of
150+other programs---notably compilers. When you have to hand-code
151+specialized routines in assembly, that means the @sc{gnu} assembler is
152+an unfriendly processor: it has no directives for macros, conditionals,
153+or many other conveniences that you might expect.
154+
155+In some cases you can simply use the C preprocessor, or a generalized
156+preprocessor like @sc{m4}; but this can be awkward, since none of these
157+things are designed with assembly in mind.
158+
159+@sc{gasp} fills this need. It is expressly designed to provide the
160+facilities you need with hand-coded assembly code. Implementing it as a
161+preprocessor, rather than part of the assembler, allows the maximum
162+flexibility: you can use it with hand-coded assembly, without paying a
163+penalty of added complexity in the assembler you use for compiler
164+output.
165+
166+@emph{Note} The use of @sc{gasp} has now been deprecated. Anything
167+that it could do can now be done by the macro facilities built into
168+@sc{gas} itself. At some point in the future the @sc{gasp} sources will
169+be removed entirely from the binutils distribution.
170+
171+Here is a small example to give the flavor of @sc{gasp}. This input to
172+@sc{gasp}
173+
174+@cartouche
175+@example
176+ .MACRO saveregs from=8 to=14
177+count .ASSIGNA \from
178+ ! save r\from..r\to
179+ .AWHILE \&count LE \to
180+ mov r\&count,@@-sp
181+count .ASSIGNA \&count + 1
182+ .AENDW
183+ .ENDM
184+
185+ saveregs from=12
186+
187+bar: mov #H'dead+10,r0
188+foo .SDATAC "hello"<10>
189+ .END
190+@end example
191+@end cartouche
192+
193+@noindent
194+generates this assembly program:
195+
196+@cartouche
197+@example
198+ ! save r12..r14
199+ mov r12,@@-sp
200+ mov r13,@@-sp
201+ mov r14,@@-sp
202+
203+bar: mov #57005+10,r0
204+foo: .byte 6,104,101,108,108,111,10
205+@end example
206+@end cartouche
207+
208+@node Invoking GASP
209+@chapter Command Line Options
210+
211+@c FIXME! Or is there a simpler way, calling from GAS option?
212+The simplest way to use @sc{gasp} is to run it as a filter and assemble
213+its output. In Unix and its ilk, you can do this, for example:
214+
215+@c FIXME! GASP filename suffix convention?
216+@example
217+$ gasp prog.asm | as -o prog.o
218+@end example
219+
220+Naturally, there are also a few command-line options to allow you to
221+request variations on this basic theme. Here is the full set of
222+possibilities for the @sc{gasp} command line.
223+
224+@example
225+gasp [ -a | --alternate ]
226+ [ -c @var{char} | --commentchar @var{char} ]
227+ [ -d | --debug ] [ -h | --help ] [ -M | --mri ]
228+ [ -o @var{outfile} | --output @var{outfile} ]
229+ [ -p | --print ] [ -s | --copysource ]
230+ [ -u | --unreasonable ] [ -v | --version ]
231+ @var{infile} @dots{}
232+@end example
233+
234+@ftable @code
235+@item @var{infile} @dots{}
236+@c FIXME! Why not stdin as default infile?
237+The input file names. You must specify at least one input file; if you
238+specify more, @sc{gasp} preprocesses them all, concatenating the output
239+in the order you list the @var{infile} arguments.
240+
241+Mark the end of each input file with the preprocessor command
242+@code{.END}. @xref{Other Commands,, Miscellaneous commands}.
243+
244+@item -a
245+@itemx --alternate
246+Use alternative macro syntax. @xref{Alternate,, Alternate macro
247+syntax}, for a discussion of how this syntax differs from the default
248+@sc{gasp} syntax.
249+
250+@cindex comment character, changing
251+@cindex semicolon, as comment
252+@cindex exclamation mark, as comment
253+@cindex shriek, as comment
254+@cindex bang, as comment
255+@cindex @code{!} default comment char
256+@cindex @code{;} as comment char
257+@item -c '@var{char}'
258+@itemx --commentchar '@var{char}'
259+Use @var{char} as the comment character. The default comment character
260+is @samp{!}. For example, to use a semicolon as the comment character,
261+specify @w{@samp{-c ';'}} on the @sc{gasp} command line. Since
262+assembler command characters often have special significance to command
263+shells, it is a good idea to quote or escape @var{char} when you specify
264+a comment character.
265+
266+For the sake of simplicity, all examples in this manual use the default
267+comment character @samp{!}.
268+
269+@item -d
270+@itemx --debug
271+Show debugging statistics. In this version of @sc{gasp}, this option
272+produces statistics about the string buffers that @sc{gasp} allocates
273+internally. For each defined buffersize @var{s}, @sc{gasp} shows the
274+number of strings @var{n} that it allocated, with a line like this:
275+
276+@example
277+strings size @var{s} : @var{n}
278+@end example
279+
280+@noindent
281+@sc{gasp} displays these statistics on the standard error stream, when
282+done preprocessing.
283+
284+@item -h
285+@itemx --help
286+Display a summary of the @sc{gasp} command line options.
287+
288+@item -M
289+@itemx --mri
290+Use MRI compatibility mode. Using this option causes @sc{gasp} to
291+accept the syntax and pseudo-ops used by the Microtec Research
292+@code{ASM68K} assembler.
293+
294+@item -o @var{outfile}
295+@itemx --output @var{outfile}
296+Write the output in a file called @var{outfile}. If you do not use the
297+@samp{-o} option, @sc{gasp} writes its output on the standard output
298+stream.
299+
300+@item -p
301+@itemx --print
302+Print line numbers. @sc{gasp} obeys this option @emph{only} if you also
303+specify @samp{-s} to copy source lines to its output. With @samp{-s
304+-p}, @sc{gasp} displays the line number of each source line copied
305+(immediately after the comment character at the beginning of the line).
306+
307+@item -s
308+@itemx --copysource
309+Copy the source lines to the output file. Use this option
310+to see the effect of each preprocessor line on the @sc{gasp} output.
311+@sc{gasp} places a comment character (@samp{!} by default) at
312+the beginning of each source line it copies, so that you can use this
313+option and still assemble the result.
314+
315+@item -u
316+@itemx --unreasonable
317+Bypass ``unreasonable expansion'' limit. Since you can define @sc{gasp}
318+macros inside other macro definitions, the preprocessor normally
319+includes a sanity check. If your program requires more than 1,000
320+nested expansions, @sc{gasp} normally exits with an error message. Use
321+this option to turn off this check, allowing unlimited nested
322+expansions.
323+
324+@item -v
325+@itemx --version
326+Display the @sc{gasp} version number.
327+@end ftable
328+
329+@node Commands
330+@chapter Preprocessor Commands
331+
332+@sc{gasp} commands have a straightforward syntax that fits in well with
333+assembly conventions. In general, a command extends for a line, and may
334+have up to three fields: an optional label, the command itself, and
335+optional arguments to the command. You can write commands in upper or
336+lower case, though this manual shows them in upper case. @xref{Syntax
337+Details,, Details of the GASP syntax}, for more information.
338+
339+@menu
340+* Conditionals::
341+* Loops::
342+* Variables::
343+* Macros::
344+* Data::
345+* Listings::
346+* Other Commands::
347+* Syntax Details::
348+* Alternate::
349+@end menu
350+
351+@node Conditionals
352+@section Conditional assembly
353+
354+The conditional-assembly directives allow you to include or exclude
355+portions of an assembly depending on how a pair of expressions, or a
356+pair of strings, compare.
357+
358+The overall structure of conditionals is familiar from many other
359+contexts. @code{.AIF} marks the start of a conditional, and precedes
360+assembly for the case when the condition is true. An optional
361+@code{.AELSE} precedes assembly for the converse case, and an
362+@code{.AENDI} marks the end of the condition.
363+
364+@c FIXME! Why doesn't -u turn off this check?
365+You may nest conditionals up to a depth of 100; @sc{gasp} rejects
366+nesting beyond that, because it may indicate a bug in your macro
367+structure.
368+
369+@c FIXME! Why isn't there something like cpp's -D option? Conditionals
370+@c would be much more useful if there were.
371+Conditionals are primarily useful inside macro definitions, where you
372+often need different effects depending on argument values.
373+@xref{Macros,, Defining your own directives}, for details about defining
374+macros.
375+
376+@ftable @code
377+@item .AIF @var{expra} @var{cmp} @var{exprb}
378+@itemx .AIF "@var{stra}" @var{cmp} "@var{strb}"
379+
380+The governing condition goes on the same line as the @code{.AIF}
381+preprocessor command. You may compare either two strings, or two
382+expressions.
383+
384+When you compare strings, only two conditional @var{cmp} comparison
385+operators are available: @samp{EQ} (true if @var{stra} and @var{strb}
386+are identical), and @samp{NE} (the opposite).
387+
388+When you compare two expressions, @emph{both expressions must be
389+absolute} (@pxref{Expressions,, Arithmetic expressions in GASP}). You
390+can use these @var{cmp} comparison operators with expressions:
391+
392+@ftable @code
393+@item EQ
394+Are @var{expra} and @var{exprb} equal? (For strings, are @var{stra} and
395+@var{strb} identical?)
396+
397+@item NE
398+Are @var{expra} and @var{exprb} different? (For strings, are @var{stra}
399+and @var{strb} different?
400+
401+@item LT
402+Is @var{expra} less than @var{exprb}? (Not allowed for strings.)
403+
404+@item LE
405+Is @var{expra} less than or equal to @var{exprb}? (Not allowed for strings.)
406+
407+@item GT
408+Is @var{expra} greater than @var{exprb}? (Not allowed for strings.)
409+
410+@item GE
411+Is @var{expra} greater than or equal to @var{exprb}? (Not allowed for
412+strings.)
413+@end ftable
414+
415+@item .AELSE
416+Marks the start of assembly code to be included if the condition fails.
417+Optional, and only allowed within a conditional (between @code{.AIF} and
418+@code{.AENDI}).
419+
420+@item .AENDI
421+Marks the end of a conditional assembly.
422+@end ftable
423+
424+@node Loops
425+@section Repetitive sections of assembly
426+
427+Two preprocessor directives allow you to repeatedly issue copies of the
428+same block of assembly code.
429+
430+@ftable @code
431+@item .AREPEAT @var{aexp}
432+@itemx .AENDR
433+If you simply need to repeat the same block of assembly over and over a
434+fixed number of times, sandwich one instance of the repeated block
435+between @code{.AREPEAT} and @code{.AENDR}. Specify the number of
436+copies as @var{aexp} (which must be an absolute expression). For
437+example, this repeats two assembly statements three times in succession:
438+
439+@cartouche
440+@example
441+ .AREPEAT 3
442+ rotcl r2
443+ div1 r0,r1
444+ .AENDR
445+@end example
446+@end cartouche
447+
448+@item .AWHILE @var{expra} @var{cmp} @var{exprb}
449+@itemx .AENDW
450+@itemx .AWHILE @var{stra} @var{cmp} @var{strb}
451+@itemx .AENDW
452+To repeat a block of assembly depending on a conditional test, rather
453+than repeating it for a specific number of times, use @code{.AWHILE}.
454+@code{.AENDW} marks the end of the repeated block. The conditional
455+comparison works exactly the same way as for @code{.AIF}, with the same
456+comparison operators (@pxref{Conditionals,, Conditional assembly}).
457+
458+Since the terms of the comparison must be absolute expression,
459+@code{.AWHILE} is primarily useful within macros. @xref{Macros,,
460+Defining your own directives}.
461+@end ftable
462+
463+@cindex loops, breaking out of
464+@cindex breaking out of loops
465+You can use the @code{.EXITM} preprocessor directive to break out of
466+loops early (as well as to break out of macros). @xref{Macros,,
467+Defining your own directives}.
468+
469+@node Variables
470+@section Preprocessor variables
471+
472+You can use variables in @sc{gasp} to represent strings, registers, or
473+the results of expressions.
474+
475+You must distinguish two kinds of variables:
476+@enumerate
477+@item
478+Variables defined with @code{.EQU} or @code{.ASSIGN}. To evaluate this
479+kind of variable in your assembly output, simply mention its name. For
480+example, these two lines define and use a variable @samp{eg}:
481+
482+@cartouche
483+@example
484+eg .EQU FLIP-64
485+ @dots{}
486+ mov.l eg,r0
487+@end example
488+@end cartouche
489+
490+@emph{Do not use} this kind of variable in conditional expressions or
491+while loops; @sc{gasp} only evaluates these variables when writing
492+assembly output.
493+
494+@item
495+Variables for use during preprocessing. You can define these
496+with @code{.ASSIGNC} or @code{.ASSIGNA}. To evaluate this
497+kind of variable, write @samp{\&} before the variable name; for example,
498+
499+@cartouche
500+@example
501+opcit .ASSIGNA 47
502+ @dots{}
503+ .AWHILE \&opcit GT 0
504+ @dots{}
505+ .AENDW
506+@end example
507+@end cartouche
508+
509+@sc{gasp} treats macro arguments almost the same way, but to evaluate
510+them you use the prefix @samp{\} rather than @samp{\&}.
511+@xref{Macros,, Defining your own directives}.
512+@end enumerate
513+
514+@ftable @code
515+@item @var{pvar} .EQU @var{expr}
516+@c FIXME! Anything to beware of re GAS directive of same name?
517+Assign preprocessor variable @var{pvar} the value of the expression
518+@var{expr}. There are no restrictions on redefinition; use @samp{.EQU}
519+with the same @var{pvar} as often as you find it convenient.
520+
521+@item @var{pvar} .ASSIGN @var{expr}
522+Almost the same as @code{.EQU}, save that you may not redefine
523+@var{pvar} using @code{.ASSIGN} once it has a value.
524+@c FIXME!! Supposed to work this way, apparently, but on 9feb94 works
525+@c just like .EQU
526+
527+@item @var{pvar} .ASSIGNA @var{aexpr}
528+Define a variable with a numeric value, for use during preprocessing.
529+@var{aexpr} must be an absolute expression. You can redefine variables
530+with @code{.ASSIGNA} at any time.
531+
532+@item @var{pvar} .ASSIGNC "@var{str}"
533+Define a variable with a string value, for use during preprocessing.
534+You can redefine variables with @code{.ASSIGNC} at any time.
535+
536+@item @var{pvar} .REG (@var{register})
537+Use @code{.REG} to define a variable that represents a register. In
538+particular, @var{register} is @emph{not evaluated} as an expression.
539+You may use @code{.REG} at will to redefine register variables.
540+@end ftable
541+
542+All these directives accept the variable name in the ``label'' position,
543+that is at the left margin. You may specify a colon after the variable
544+name if you wish; the first example above could have started @samp{eg:}
545+with the same effect.
546+
547+@c pagebreak makes for better aesthetics---ensures macro and expansion together
548+@page
549+@node Macros
550+@section Defining your own directives
551+
552+The commands @code{.MACRO} and @code{.ENDM} allow you to define macros
553+that generate assembly output. You can use these macros with a syntax
554+similar to built-in @sc{gasp} or assembler directives. For example,
555+this definition specifies a macro @code{SUM} that adds together a range of
556+consecutive registers:
557+
558+@cartouche
559+@example
560+ .MACRO SUM FROM=0, TO=9
561+ ! \FROM \TO
562+ mov r\FROM,r10
563+COUNT .ASSIGNA \FROM+1
564+ .AWHILE \&COUNT LE \TO
565+ add r\&COUNT,r10
566+COUNT .ASSIGNA \&COUNT+1
567+ .AENDW
568+ .ENDM
569+@end example
570+@end cartouche
571+
572+@noindent
573+With that definition, @samp{SUM 0,5} generates this assembly output:
574+
575+@cartouche
576+@example
577+ ! 0 5
578+ mov r0,r10
579+ add r1,r10
580+ add r2,r10
581+ add r3,r10
582+ add r4,r10
583+ add r5,r10
584+@end example
585+@end cartouche
586+
587+@ftable @code
588+@item .MACRO @var{macname}
589+@itemx .MACRO @var{macname} @var{macargs} @dots{}
590+Begin the definition of a macro called @var{macname}. If your macro
591+definition requires arguments, specify their names after the macro name,
592+separated by commas or spaces. You can supply a default value for any
593+macro argument by following the name with @samp{=@var{deflt}}. For
594+example, these are all valid @code{.MACRO} statements:
595+
596+@table @code
597+@item .MACRO COMM
598+Begin the definition of a macro called @code{COMM}, which takes no
599+arguments.
600+
601+@item .MACRO PLUS1 P, P1
602+@itemx .MACRO PLUS1 P P1
603+Either statement begins the definition of a macro called @code{PLUS1},
604+which takes two arguments; within the macro definition, write
605+@samp{\P} or @samp{\P1} to evaluate the arguments.
606+
607+@item .MACRO RESERVE_STR P1=0 P2
608+Begin the definition of a macro called @code{RESERVE_STR}, with two
609+arguments. The first argument has a default value, but not the second.
610+After the definition is complete, you can call the macro either as
611+@samp{RESERVE_STR @var{a},@var{b}} (with @samp{\P1} evaluating to
612+@var{a} and @samp{\P2} evaluating to @var{b}), or as @samp{RESERVE_STR
613+,@var{b}} (with @samp{\P1} evaluating as the default, in this case
614+@samp{0}, and @samp{\P2} evaluating to @var{b}).
615+@end table
616+
617+When you call a macro, you can specify the argument values either by
618+position, or by keyword. For example, @samp{SUM 9,17} is equivalent to
619+@samp{SUM TO=17, FROM=9}. Macro arguments are preprocessor variables
620+similar to the variables you define with @samp{.ASSIGNA} or
621+@samp{.ASSIGNC}; in particular, you can use them in conditionals or for
622+loop control. (The only difference is the prefix you write to evaluate
623+the variable: for a macro argument, write @samp{\@var{argname}}, but for
624+a preprocessor variable, write @samp{\&@var{varname}}.)
625+
626+@item @var{name} .MACRO
627+@itemx @var{name} .MACRO ( @var{macargs} @dots{} )
628+@c FIXME check: I think no error _and_ no args recognized if I use form
629+@c NAME .MACRO ARG ARG
630+An alternative form of introducing a macro definition: specify the macro
631+name in the label position, and the arguments (if any) between
632+parentheses after the name. Defaulting rules and usage work the same
633+way as for the other macro definition syntax.
634+
635+@item .ENDM
636+Mark the end of a macro definition.
637+
638+@item .EXITM
639+Exit early from the current macro definition, @code{.AREPEAT} loop, or
640+@code{.AWHILE} loop.
641+
642+@cindex number of macros executed
643+@cindex macros, count executed
644+@item \@@
645+@sc{gasp} maintains a counter of how many macros it has
646+executed in this pseudo-variable; you can copy that number to your
647+output with @samp{\@@}, but @emph{only within a macro definition}.
648+
649+@item LOCAL @var{name} [ , @dots{} ]
650+@emph{Warning: @code{LOCAL} is only available if you select ``alternate
651+macro syntax'' with @samp{-a} or @samp{--alternate}.} @xref{Alternate,,
652+Alternate macro syntax}.
653+
654+Generate a string replacement for each of the @var{name} arguments, and
655+replace any instances of @var{name} in each macro expansion. The
656+replacement string is unique in the assembly, and different for each
657+separate macro expansion. @code{LOCAL} allows you to write macros that
658+define symbols, without fear of conflict between separate macro expansions.
659+@end ftable
660+
661+@node Data
662+@section Data output
663+
664+In assembly code, you often need to specify working areas of memory;
665+depending on the application, you may want to initialize such memory or
666+not. @sc{gasp} provides preprocessor directives to help you avoid
667+repetitive coding for both purposes.
668+
669+You can use labels as usual to mark the data areas.
670+
671+@menu
672+* Initialized::
673+* Uninitialized::
674+@end menu
675+
676+@node Initialized
677+@subsection Initialized data
678+
679+These are the @sc{gasp} directives for initialized data, and the standard
680+@sc{gnu} assembler directives they expand to:
681+
682+@ftable @code
683+@item .DATA @var{expr}, @var{expr}, @dots{}
684+@itemx .DATA.B @var{expr}, @var{expr}, @dots{}
685+@itemx .DATA.W @var{expr}, @var{expr}, @dots{}
686+@itemx .DATA.L @var{expr}, @var{expr}, @dots{}
687+Evaluate arithmetic expressions @var{expr}, and emit the corresponding
688+@code{as} directive (labelled with @var{lab}). The unqualified
689+@code{.DATA} emits @samp{.long}; @code{.DATA.B} emits @samp{.byte};
690+@code{.DATA.W} emits @samp{.short}; and @code{.DATA.L} emits
691+@samp{.long}.
692+
693+For example, @samp{foo .DATA 1,2,3} emits @samp{foo: .long 1,2,3}.
694+
695+@item .DATAB @var{repeat}, @var{expr}
696+@itemx .DATAB.B @var{repeat}, @var{expr}
697+@itemx .DATAB.W @var{repeat}, @var{expr}
698+@itemx .DATAB.L @var{repeat}, @var{expr}
699+@c FIXME! Looks like gasp accepts and ignores args after 2nd.
700+Make @code{as} emit @var{repeat} copies of the value of the expression
701+@var{expr} (using the @code{as} directive @code{.fill}).
702+@samp{.DATAB.B} repeats one-byte values; @samp{.DATAB.W} repeats
703+two-byte values; and @samp{.DATAB.L} repeats four-byte values.
704+@samp{.DATAB} without a suffix repeats four-byte values, just like
705+@samp{.DATAB.L}.
706+
707+@c FIXME! Allowing zero might be useful for edge conditions in macros.
708+@var{repeat} must be an absolute expression with a positive value.
709+
710+@item .SDATA "@var{str}" @dots{}
711+String data. Emits a concatenation of bytes, precisely as you specify
712+them (in particular, @emph{nothing is added to mark the end} of the
713+string). @xref{Constants,, String and numeric constants}, for details
714+about how to write strings. @code{.SDATA} concatenates multiple
715+arguments, making it easy to switch between string representations. You
716+can use commas to separate the individual arguments for clarity, if you
717+choose.
718+
719+@item .SDATAB @var{repeat}, "@var{str}" @dots{}
720+Repeated string data. The first argument specifies how many copies of
721+the string to emit; the remaining arguments specify the string, in the
722+same way as the arguments to @code{.SDATA}.
723+
724+@item .SDATAZ "@var{str}" @dots{}
725+Zero-terminated string data. Just like @code{.SDATA}, except that
726+@code{.SDATAZ} writes a zero byte at the end of the string.
727+
728+@item .SDATAC "@var{str}" @dots{}
729+Count-prefixed string data. Just like @code{.SDATA}, except that
730+@sc{gasp} precedes the string with a leading one-byte count. For
731+example, @samp{.SDATAC "HI"} generates @samp{.byte 2,72,73}. Since the
732+count field is only one byte, you can only use @code{.SDATAC} for
733+strings less than 256 bytes in length.
734+@end ftable
735+
736+@node Uninitialized
737+@subsection Uninitialized data
738+
739+@c FIXME! .space different on some platforms, notably HPPA. Config?
740+Use the @code{.RES}, @code{.SRES}, @code{.SRESC}, and @code{.SRESZ}
741+directives to reserve memory and leave it uninitialized. @sc{gasp}
742+resolves these directives to appropriate calls of the @sc{gnu}
743+@code{as} @code{.space} directive.
744+
745+@ftable @code
746+@item .RES @var{count}
747+@itemx .RES.B @var{count}
748+@itemx .RES.W @var{count}
749+@itemx .RES.L @var{count}
750+Reserve room for @var{count} uninitialized elements of data. The
751+suffix specifies the size of each element: @code{.RES.B} reserves
752+@var{count} bytes, @code{.RES.W} reserves @var{count} pairs of bytes,
753+and @code{.RES.L} reserves @var{count} quartets. @code{.RES} without a
754+suffix is equivalent to @code{.RES.L}.
755+
756+@item .SRES @var{count}
757+@itemx .SRES.B @var{count}
758+@itemx .SRES.W @var{count}
759+@itemx .SRES.L @var{count}
760+@c FIXME! This is boring. Shouldn't it at least have a different
761+@c default size? (e.g. the "S" suggests "string", for which .B
762+@c would be more appropriate)
763+@code{.SRES} is a synonym for @samp{.RES}.
764+
765+@item .SRESC @var{count}
766+@itemx .SRESC.B @var{count}
767+@itemx .SRESC.W @var{count}
768+@itemx .SRESC.L @var{count}
769+Like @code{.SRES}, but reserves space for @code{@var{count}+1} elements.
770+
771+@item .SRESZ @var{count}
772+@itemx .SRESZ.B @var{count}
773+@itemx .SRESZ.W @var{count}
774+@itemx .SRESZ.L @var{count}
775+Like @code{.SRES}, but reserves space for @code{@var{count}+1} elements.
776+@end ftable
777+
778+@node Listings
779+@section Assembly listing control
780+
781+The @sc{gasp} listing-control directives correspond to
782+related @sc{gnu} @code{as} directives.
783+
784+@ftable @code
785+@item .PRINT LIST
786+@itemx .PRINT NOLIST
787+Print control. This directive emits the @sc{gnu} @code{as} directive
788+@code{.list} or @code{.nolist}, according to its argument. @xref{List,,
789+@code{.list}, as.info, Using as}, for details on how these directives
790+interact.
791+
792+@item .FORM LIN=@var{ln}
793+@itemx .FORM COL=@var{cols}
794+@itemx .FORM LIN=@var{ln} COL=@var{cols}
795+Specify the page size for assembly listings: @var{ln} represents the
796+number of lines, and @var{cols} the number of columns. You may specify
797+either page dimension independently, or both together. If you do not
798+specify the number of lines, @sc{gasp} assumes 60 lines; if you do not
799+specify the number of columns, @sc{gasp} assumes 132 columns.
800+(Any values you may have specified in previous instances of @code{.FORM}
801+do @emph{not} carry over as defaults.) Emits the @code{.psize}
802+assembler directive.
803+
804+@item .HEADING @var{string}
805+Specify @var{string} as the title of your assembly listings. Emits
806+@samp{.title "@var{string}"}.
807+
808+@item .PAGE
809+Force a new page in assembly listings. Emits @samp{.eject}.
810+@end ftable
811+
812+@node Other Commands
813+@section Miscellaneous commands
814+
815+@ftable @code
816+@item .ALTERNATE
817+Use the alternate macro syntax henceforth in the assembly.
818+@xref{Alternate,, Alternate macro syntax}.
819+
820+@item .ORG
821+@c FIXME! This is very strange, since _GAS_ understands .org
822+This command is recognized, but not yet implemented. @sc{gasp}
823+generates an error message for programs that use @code{.ORG}.
824+
825+@item .RADIX @var{s}
826+@c FIXME no test cases in testsuite/gasp
827+@sc{gasp} understands numbers in any of base two, eight, ten, or
828+sixteen. You can encode the base explicitly in any numeric constant
829+(@pxref{Constants,, String and numeric constants}). If you write
830+numbers without an explicit indication of the base, the most recent
831+@samp{.RADIX @var{s}} command determines how they are interpreted.
832+@var{s} is a single letter, one of the following:
833+
834+@table @code
835+@item .RADIX B
836+Base 2.
837+
838+@item .RADIX Q
839+Base 8.
840+
841+@item .RADIX D
842+Base 10. This is the original default radix.
843+
844+@item .RADIX H
845+Base 16.
846+@end table
847+
848+You may specify the argument @var{s} in lower case (any of @samp{bqdh})
849+with the same effects.
850+
851+@item .EXPORT @var{name}
852+@itemx .GLOBAL @var{name}
853+@c FIXME! No test cases in testsuite/gasp
854+Declare @var{name} global (emits @samp{.global @var{name}}). The two
855+directives are synonymous.
856+
857+@item .PROGRAM
858+No effect: @sc{gasp} accepts this directive, and silently ignores it.
859+
860+@item .END
861+Mark end of each preprocessor file. @sc{gasp} issues a warning if it
862+reaches end of file without seeing this command.
863+
864+@item .INCLUDE "@var{str}"
865+Preprocess the file named by @var{str}, as if its contents appeared
866+where the @code{.INCLUDE} directive does. @sc{gasp} imposes a maximum
867+limit of 30 stacked include files, as a sanity check.
868+@c FIXME! Why is include depth not affected by -u?
869+
870+@item .ALIGN @var{size}
871+@c FIXME! Why is this not utterly pointless?
872+Evaluate the absolute expression @var{size}, and emit the assembly
873+instruction @samp{.align @var{size}} using the result.
874+@end ftable
875+
876+@node Syntax Details
877+@section Details of the GASP syntax
878+
879+Since @sc{gasp} is meant to work with assembly code, its statement
880+syntax has no surprises for the assembly programmer.
881+
882+@cindex whitespace
883+@emph{Whitespace} (blanks or tabs; @emph{not} newline) is partially
884+significant, in that it delimits up to three fields in a line. The
885+amount of whitespace does not matter; you may line up fields in separate
886+lines if you wish, but @sc{gasp} does not require that.
887+
888+@cindex fields of @sc{gasp} source line
889+@cindex label field
890+The @emph{first field}, an optional @dfn{label}, must be flush left in a
891+line (with no leading whitespace) if it appears at all. You may use a
892+colon after the label if you wish; @sc{gasp} neither requires the colon
893+nor objects to it (but will not include it as part of the label name).
894+
895+@cindex directive field
896+The @emph{second field}, which must appear after some whitespace,
897+contains a @sc{gasp} or assembly @dfn{directive}.
898+
899+@cindex argument fields
900+Any @emph{further fields} on a line are @dfn{arguments} to the
901+directive; you can separate them from one another using either commas or
902+whitespace.
903+
904+@menu
905+* Markers::
906+* Constants::
907+* Symbols::
908+* Expressions::
909+* String Builtins::
910+@end menu
911+
912+@node Markers
913+@subsection Special syntactic markers
914+
915+@sc{gasp} recognizes a few special markers: to delimit comments, to
916+continue a statement on the next line, to separate symbols from other
917+characters, and to copy text to the output literally. (One other
918+special marker, @samp{\@@}, works only within macro definitions;
919+@pxref{Macros,, Defining your own directives}.)
920+
921+@cindex comments
922+The trailing part of any @sc{gasp} source line may be a @dfn{comment}.
923+A comment begins with the first unquoted comment character (@samp{!} by
924+default), or an escaped or doubled comment character (@samp{\!} or
925+@samp{!!} by default), and extends to the end of a line. You can
926+specify what comment character to use with the @samp{-c} option
927+(@pxref{Invoking GASP,, Command Line Options}). The two kinds of
928+comment markers lead to slightly different treatment:
929+
930+@table @code
931+@item !
932+A single, un-escaped comment character generates an assembly comment in
933+the @sc{gasp} output. @sc{gasp} evaluates any preprocessor variables
934+(macro arguments, or variables defined with @code{.ASSIGNA} or
935+@code{.ASSIGNC}) present. For example, a macro that begins like this
936+
937+@example
938+ .MACRO SUM FROM=0, TO=9
939+ ! \FROM \TO
940+@end example
941+
942+@noindent
943+issues as the first line of output a comment that records the
944+values you used to call the macro.
945+
946+@c comments, preprocessor-only
947+@c preprocessor-only comments
948+@c GASP-only comments
949+@item \!
950+@itemx !!
951+Either an escaped comment character, or a double comment character,
952+marks a @sc{gasp} source comment. @sc{gasp} does not copy such comments
953+to the assembly output.
954+@end table
955+
956+@cindex continuation character
957+@kindex +
958+To @emph{continue a statement} on the next line of the file, begin the
959+second line with the character @samp{+}.
960+
961+@cindex literal copy to output
962+@cindex copying literally to output
963+@cindex preprocessing, avoiding
964+@cindex avoiding preprocessing
965+Occasionally you may want to prevent @sc{gasp} from preprocessing some
966+particular bit of text. To @emph{copy literally} from the @sc{gasp}
967+source to its output, place @samp{\(} before the string to copy, and
968+@samp{)} at the end. For example, write @samp{\(\!)} if you need the
969+characters @samp{\!} in your assembly output.
970+
971+@cindex symbol separator
972+@cindex text, separating from symbols
973+@cindex symbols, separating from text
974+To @emph{separate a preprocessor variable} from text to appear
975+immediately after its value, write a single quote (@code{'}). For
976+example, @samp{.SDATA "\P'1"} writes a string built by concatenating the
977+value of @code{P} and the digit @samp{1}. (You cannot achieve this by
978+writing just @samp{\P1}, since @samp{P1} is itself a valid name for a
979+preprocessor variable.)
980+
981+@node Constants
982+@subsection String and numeric constants
983+
984+There are two ways of writing @dfn{string constants} in @sc{gasp}: as
985+literal text, and by numeric byte value. Specify a string literal
986+between double quotes (@code{"@var{str}"}). Specify an individual
987+numeric byte value as an absolute expression between angle brackets
988+(@code{<@var{expr}>}. Directives that output strings allow you to
989+specify any number of either kind of value, in whatever order is
990+convenient, and concatenate the result. (Alternate syntax mode
991+introduces a number of alternative string notations; @pxref{Alternate,,
992+Alternate macro syntax}.)
993+
994+@c Details of numeric notation, e.g. base prefixes
995+You can write @dfn{numeric constants} either in a specific base, or in
996+whatever base is currently selected (either 10, or selected by the most
997+recent @code{.RADIX}).
998+
999+To write a number in a @emph{specific base}, use the pattern
1000+@code{@var{s}'@var{ddd}}: a base specifier character @var{s}, followed
1001+by a single quote followed by digits @var{ddd}. The base specifier
1002+character matches those you can specify with @code{.RADIX}: @samp{B} for
1003+base 2, @samp{Q} for base 8, @samp{D} for base 10, and @samp{H} for base
1004+16. (You can write this character in lower case if you prefer.)
1005+
1006+You can write floating point constants using the same syntax recognised
1007+by GAS @ref{Flonums,,Flonums,as,The GNU Assembler.}. A constraint is
1008+that these constants will be interpreted as decimal values irrespective
1009+of the currently selected base.
1010+
1011+@c FIXME! What are rules for recognizing number in deflt base? Whatever
1012+@c is left over after parsing other things??
1013+
1014+@node Symbols
1015+@subsection Symbols
1016+
1017+@sc{gasp} recognizes symbol names that start with any alphabetic character,
1018+@samp{_}, or @samp{$}, and continue with any of the same characters or
1019+with digits. Label names follow the same rules.
1020+
1021+@node Expressions
1022+@subsection Arithmetic expressions in GASP
1023+
1024+@cindex absolute expressions
1025+@cindex relocatable expressions
1026+There are two kinds of expressions, depending on their result:
1027+@dfn{absolute} expressions, which resolve to a constant (that is, they
1028+do not involve any values unknown to @sc{gasp}), and @dfn{relocatable}
1029+expressions, which must reduce to the form
1030+
1031+@example
1032+@var{addsym}+@var{const}-@var{subsym}
1033+@end example
1034+
1035+@noindent
1036+where @var{addsym} and @var{subsym} are assembly symbols of unknown
1037+value, and @var{const} is a constant.
1038+
1039+Arithmetic for @sc{gasp} expressions follows very similar rules to C.
1040+You can use parentheses to change precedence; otherwise, arithmetic
1041+primitives have decreasing precedence in the order of the following
1042+list.
1043+
1044+@enumerate
1045+@item
1046+Single-argument @code{+} (identity), @code{-} (arithmetic opposite), or
1047+@code{~} (bitwise negation). @emph{The argument must be an absolute
1048+expression.}
1049+
1050+@item
1051+@code{*} (multiplication) and @code{/} (division). @emph{Both arguments
1052+must be absolute expressions.}
1053+
1054+@item
1055+@code{+} (addition) and @code{-} (subtraction). @emph{At least one argument
1056+must be absolute.}
1057+@c FIXME! Actually, subtraction doesn't check for this.
1058+
1059+@item
1060+@code{&} (bitwise and). @emph{Both arguments must be absolute.}
1061+
1062+@item
1063+@c FIXME! I agree ~ is a better notation than ^ for xor, but is the
1064+@c improvement worth differing from C?
1065+@code{|} (bitwise or) and @code{~} (bitwise exclusive or; @code{^} in
1066+C). @emph{Both arguments must be absolute.}
1067+@end enumerate
1068+
1069+@node String Builtins
1070+@subsection String primitives
1071+
1072+You can use these primitives to manipulate strings (in the argument
1073+field of @sc{gasp} statements):
1074+
1075+@ftable @code
1076+@item .LEN("@var{str}")
1077+Calculate the length of string @code{"@var{str}"}, as an absolute
1078+expression. For example, @samp{.RES.B .LEN("sample")} reserves six
1079+bytes of memory.
1080+
1081+@item .INSTR("@var{string}", "@var{seg}", @var{ix})
1082+Search for the first occurrence of @var{seg} after position @var{ix} of
1083+@var{string}. For example, @samp{.INSTR("ABCDEFG", "CDE", 0)} evaluates
1084+to the absolute result @code{2}.
1085+
1086+The result is @code{-1} if @var{seg} does not occur in @var{string}
1087+after position @var{ix}.
1088+
1089+@item .SUBSTR("@var{string}",@var{start},@var{len})
1090+The substring of @var{string} beginning at byte number @var{start} and
1091+extending for @var{len} bytes.
1092+@end ftable
1093+
1094+@node Alternate
1095+@section Alternate macro syntax
1096+
1097+If you specify @samp{-a} or @samp{--alternate} on the @sc{gasp} command
1098+line, the preprocessor uses somewhat different syntax. This syntax is
1099+reminiscent of the syntax of Phar Lap macro assembler, but it
1100+is @emph{not} meant to be a full emulation of Phar Lap or similar
1101+assemblers. In particular, @sc{gasp} does not support directives such
1102+as @code{DB} and @code{IRP}, even in alternate syntax mode.
1103+
1104+In particular, @samp{-a} (or @samp{--alternate}) elicits these
1105+differences:
1106+
1107+@table @emph
1108+@item Preprocessor directives
1109+You can use @sc{gasp} preprocessor directives without a leading @samp{.}
1110+dot. For example, you can write @samp{SDATA} with the same effect as
1111+@samp{.SDATA}.
1112+
1113+@item LOCAL
1114+One additional directive, @code{LOCAL}, is available. @xref{Macros,,
1115+Defining your own directives}, for an explanation of how to use
1116+@code{LOCAL}.
1117+
1118+@need 2000
1119+@item String delimiters
1120+You can write strings delimited in these other ways besides
1121+@code{"@var{string}"}:
1122+
1123+@table @code
1124+@item '@var{string}'
1125+You can delimit strings with single-quote charaters.
1126+
1127+@item <@var{string}>
1128+You can delimit strings with matching angle brackets.
1129+@end table
1130+
1131+@item single-character string escape
1132+To include any single character literally in a string (even if the
1133+character would otherwise have some special meaning), you can prefix the
1134+character with @samp{!} (an exclamation mark). For example, you can
1135+write @samp{<4.3 !> 5.4!!>} to get the literal text @samp{4.3 > 5.4!}.
1136+
1137+@item Expression results as strings
1138+You can write @samp{%@var{expr}} to evaluate the expression @var{expr}
1139+and use the result as a string.
1140+@end table
1141+
1142+@node GNU Free Documentation License
1143+@chapter GNU Free Documentation License
1144+
1145+ GNU Free Documentation License
1146+
1147+ Version 1.1, March 2000
1148+
1149+ Copyright (C) 2000 Free Software Foundation, Inc.
1150+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1151+
1152+ Everyone is permitted to copy and distribute verbatim copies
1153+ of this license document, but changing it is not allowed.
1154+
1155+
1156+0. PREAMBLE
1157+
1158+The purpose of this License is to make a manual, textbook, or other
1159+written document "free" in the sense of freedom: to assure everyone
1160+the effective freedom to copy and redistribute it, with or without
1161+modifying it, either commercially or noncommercially. Secondarily,
1162+this License preserves for the author and publisher a way to get
1163+credit for their work, while not being considered responsible for
1164+modifications made by others.
1165+
1166+This License is a kind of "copyleft", which means that derivative
1167+works of the document must themselves be free in the same sense. It
1168+complements the GNU General Public License, which is a copyleft
1169+license designed for free software.
1170+
1171+We have designed this License in order to use it for manuals for free
1172+software, because free software needs free documentation: a free
1173+program should come with manuals providing the same freedoms that the
1174+software does. But this License is not limited to software manuals;
1175+it can be used for any textual work, regardless of subject matter or
1176+whether it is published as a printed book. We recommend this License
1177+principally for works whose purpose is instruction or reference.
1178+
1179+
1180+1. APPLICABILITY AND DEFINITIONS
1181+
1182+This License applies to any manual or other work that contains a
1183+notice placed by the copyright holder saying it can be distributed
1184+under the terms of this License. The "Document", below, refers to any
1185+such manual or work. Any member of the public is a licensee, and is
1186+addressed as "you".
1187+
1188+A "Modified Version" of the Document means any work containing the
1189+Document or a portion of it, either copied verbatim, or with
1190+modifications and/or translated into another language.
1191+
1192+A "Secondary Section" is a named appendix or a front-matter section of
1193+the Document that deals exclusively with the relationship of the
1194+publishers or authors of the Document to the Document's overall subject
1195+(or to related matters) and contains nothing that could fall directly
1196+within that overall subject. (For example, if the Document is in part a
1197+textbook of mathematics, a Secondary Section may not explain any
1198+mathematics.) The relationship could be a matter of historical
1199+connection with the subject or with related matters, or of legal,
1200+commercial, philosophical, ethical or political position regarding
1201+them.
1202+
1203+The "Invariant Sections" are certain Secondary Sections whose titles
1204+are designated, as being those of Invariant Sections, in the notice
1205+that says that the Document is released under this License.
1206+
1207+The "Cover Texts" are certain short passages of text that are listed,
1208+as Front-Cover Texts or Back-Cover Texts, in the notice that says that
1209+the Document is released under this License.
1210+
1211+A "Transparent" copy of the Document means a machine-readable copy,
1212+represented in a format whose specification is available to the
1213+general public, whose contents can be viewed and edited directly and
1214+straightforwardly with generic text editors or (for images composed of
1215+pixels) generic paint programs or (for drawings) some widely available
1216+drawing editor, and that is suitable for input to text formatters or
1217+for automatic translation to a variety of formats suitable for input
1218+to text formatters. A copy made in an otherwise Transparent file
1219+format whose markup has been designed to thwart or discourage
1220+subsequent modification by readers is not Transparent. A copy that is
1221+not "Transparent" is called "Opaque".
1222+
1223+Examples of suitable formats for Transparent copies include plain
1224+ASCII without markup, Texinfo input format, LaTeX input format, SGML
1225+or XML using a publicly available DTD, and standard-conforming simple
1226+HTML designed for human modification. Opaque formats include
1227+PostScript, PDF, proprietary formats that can be read and edited only
1228+by proprietary word processors, SGML or XML for which the DTD and/or
1229+processing tools are not generally available, and the
1230+machine-generated HTML produced by some word processors for output
1231+purposes only.
1232+
1233+The "Title Page" means, for a printed book, the title page itself,
1234+plus such following pages as are needed to hold, legibly, the material
1235+this License requires to appear in the title page. For works in
1236+formats which do not have any title page as such, "Title Page" means
1237+the text near the most prominent appearance of the work's title,
1238+preceding the beginning of the body of the text.
1239+
1240+
1241+2. VERBATIM COPYING
1242+
1243+You may copy and distribute the Document in any medium, either
1244+commercially or noncommercially, provided that this License, the
1245+copyright notices, and the license notice saying this License applies
1246+to the Document are reproduced in all copies, and that you add no other
1247+conditions whatsoever to those of this License. You may not use
1248+technical measures to obstruct or control the reading or further
1249+copying of the copies you make or distribute. However, you may accept
1250+compensation in exchange for copies. If you distribute a large enough
1251+number of copies you must also follow the conditions in section 3.
1252+
1253+You may also lend copies, under the same conditions stated above, and
1254+you may publicly display copies.
1255+
1256+
1257+3. COPYING IN QUANTITY
1258+
1259+If you publish printed copies of the Document numbering more than 100,
1260+and the Document's license notice requires Cover Texts, you must enclose
1261+the copies in covers that carry, clearly and legibly, all these Cover
1262+Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on
1263+the back cover. Both covers must also clearly and legibly identify
1264+you as the publisher of these copies. The front cover must present
1265+the full title with all words of the title equally prominent and
1266+visible. You may add other material on the covers in addition.
1267+Copying with changes limited to the covers, as long as they preserve
1268+the title of the Document and satisfy these conditions, can be treated
1269+as verbatim copying in other respects.
1270+
1271+If the required texts for either cover are too voluminous to fit
1272+legibly, you should put the first ones listed (as many as fit
1273+reasonably) on the actual cover, and continue the rest onto adjacent
1274+pages.
1275+
1276+If you publish or distribute Opaque copies of the Document numbering
1277+more than 100, you must either include a machine-readable Transparent
1278+copy along with each Opaque copy, or state in or with each Opaque copy
1279+a publicly-accessible computer-network location containing a complete
1280+Transparent copy of the Document, free of added material, which the
1281+general network-using public has access to download anonymously at no
1282+charge using public-standard network protocols. If you use the latter
1283+option, you must take reasonably prudent steps, when you begin
1284+distribution of Opaque copies in quantity, to ensure that this
1285+Transparent copy will remain thus accessible at the stated location
1286+until at least one year after the last time you distribute an Opaque
1287+copy (directly or through your agents or retailers) of that edition to
1288+the public.
1289+
1290+It is requested, but not required, that you contact the authors of the
1291+Document well before redistributing any large number of copies, to give
1292+them a chance to provide you with an updated version of the Document.
1293+
1294+
1295+4. MODIFICATIONS
1296+
1297+You may copy and distribute a Modified Version of the Document under
1298+the conditions of sections 2 and 3 above, provided that you release
1299+the Modified Version under precisely this License, with the Modified
1300+Version filling the role of the Document, thus licensing distribution
1301+and modification of the Modified Version to whoever possesses a copy
1302+of it. In addition, you must do these things in the Modified Version:
1303+
1304+A. Use in the Title Page (and on the covers, if any) a title distinct
1305+ from that of the Document, and from those of previous versions
1306+ (which should, if there were any, be listed in the History section
1307+ of the Document). You may use the same title as a previous version
1308+ if the original publisher of that version gives permission.
1309+B. List on the Title Page, as authors, one or more persons or entities
1310+ responsible for authorship of the modifications in the Modified
1311+ Version, together with at least five of the principal authors of the
1312+ Document (all of its principal authors, if it has less than five).
1313+C. State on the Title page the name of the publisher of the
1314+ Modified Version, as the publisher.
1315+D. Preserve all the copyright notices of the Document.
1316+E. Add an appropriate copyright notice for your modifications
1317+ adjacent to the other copyright notices.
1318+F. Include, immediately after the copyright notices, a license notice
1319+ giving the public permission to use the Modified Version under the
1320+ terms of this License, in the form shown in the Addendum below.
1321+G. Preserve in that license notice the full lists of Invariant Sections
1322+ and required Cover Texts given in the Document's license notice.
1323+H. Include an unaltered copy of this License.
1324+I. Preserve the section entitled "History", and its title, and add to
1325+ it an item stating at least the title, year, new authors, and
1326+ publisher of the Modified Version as given on the Title Page. If
1327+ there is no section entitled "History" in the Document, create one
1328+ stating the title, year, authors, and publisher of the Document as
1329+ given on its Title Page, then add an item describing the Modified
1330+ Version as stated in the previous sentence.
1331+J. Preserve the network location, if any, given in the Document for
1332+ public access to a Transparent copy of the Document, and likewise
1333+ the network locations given in the Document for previous versions
1334+ it was based on. These may be placed in the "History" section.
1335+ You may omit a network location for a work that was published at
1336+ least four years before the Document itself, or if the original
1337+ publisher of the version it refers to gives permission.
1338+K. In any section entitled "Acknowledgements" or "Dedications",
1339+ preserve the section's title, and preserve in the section all the
1340+ substance and tone of each of the contributor acknowledgements
1341+ and/or dedications given therein.
1342+L. Preserve all the Invariant Sections of the Document,
1343+ unaltered in their text and in their titles. Section numbers
1344+ or the equivalent are not considered part of the section titles.
1345+M. Delete any section entitled "Endorsements". Such a section
1346+ may not be included in the Modified Version.
1347+N. Do not retitle any existing section as "Endorsements"
1348+ or to conflict in title with any Invariant Section.
1349+
1350+If the Modified Version includes new front-matter sections or
1351+appendices that qualify as Secondary Sections and contain no material
1352+copied from the Document, you may at your option designate some or all
1353+of these sections as invariant. To do this, add their titles to the
1354+list of Invariant Sections in the Modified Version's license notice.
1355+These titles must be distinct from any other section titles.
1356+
1357+You may add a section entitled "Endorsements", provided it contains
1358+nothing but endorsements of your Modified Version by various
1359+parties--for example, statements of peer review or that the text has
1360+been approved by an organization as the authoritative definition of a
1361+standard.
1362+
1363+You may add a passage of up to five words as a Front-Cover Text, and a
1364+passage of up to 25 words as a Back-Cover Text, to the end of the list
1365+of Cover Texts in the Modified Version. Only one passage of
1366+Front-Cover Text and one of Back-Cover Text may be added by (or
1367+through arrangements made by) any one entity. If the Document already
1368+includes a cover text for the same cover, previously added by you or
1369+by arrangement made by the same entity you are acting on behalf of,
1370+you may not add another; but you may replace the old one, on explicit
1371+permission from the previous publisher that added the old one.
1372+
1373+The author(s) and publisher(s) of the Document do not by this License
1374+give permission to use their names for publicity for or to assert or
1375+imply endorsement of any Modified Version.
1376+
1377+
1378+5. COMBINING DOCUMENTS
1379+
1380+You may combine the Document with other documents released under this
1381+License, under the terms defined in section 4 above for modified
1382+versions, provided that you include in the combination all of the
1383+Invariant Sections of all of the original documents, unmodified, and
1384+list them all as Invariant Sections of your combined work in its
1385+license notice.
1386+
1387+The combined work need only contain one copy of this License, and
1388+multiple identical Invariant Sections may be replaced with a single
1389+copy. If there are multiple Invariant Sections with the same name but
1390+different contents, make the title of each such section unique by
1391+adding at the end of it, in parentheses, the name of the original
1392+author or publisher of that section if known, or else a unique number.
1393+Make the same adjustment to the section titles in the list of
1394+Invariant Sections in the license notice of the combined work.
1395+
1396+In the combination, you must combine any sections entitled "History"
1397+in the various original documents, forming one section entitled
1398+"History"; likewise combine any sections entitled "Acknowledgements",
1399+and any sections entitled "Dedications". You must delete all sections
1400+entitled "Endorsements."
1401+
1402+
1403+6. COLLECTIONS OF DOCUMENTS
1404+
1405+You may make a collection consisting of the Document and other documents
1406+released under this License, and replace the individual copies of this
1407+License in the various documents with a single copy that is included in
1408+the collection, provided that you follow the rules of this License for
1409+verbatim copying of each of the documents in all other respects.
1410+
1411+You may extract a single document from such a collection, and distribute
1412+it individually under this License, provided you insert a copy of this
1413+License into the extracted document, and follow this License in all
1414+other respects regarding verbatim copying of that document.
1415+
1416+
1417+7. AGGREGATION WITH INDEPENDENT WORKS
1418+
1419+A compilation of the Document or its derivatives with other separate
1420+and independent documents or works, in or on a volume of a storage or
1421+distribution medium, does not as a whole count as a Modified Version
1422+of the Document, provided no compilation copyright is claimed for the
1423+compilation. Such a compilation is called an "aggregate", and this
1424+License does not apply to the other self-contained works thus compiled
1425+with the Document, on account of their being thus compiled, if they
1426+are not themselves derivative works of the Document.
1427+
1428+If the Cover Text requirement of section 3 is applicable to these
1429+copies of the Document, then if the Document is less than one quarter
1430+of the entire aggregate, the Document's Cover Texts may be placed on
1431+covers that surround only the Document within the aggregate.
1432+Otherwise they must appear on covers around the whole aggregate.
1433+
1434+
1435+8. TRANSLATION
1436+
1437+Translation is considered a kind of modification, so you may
1438+distribute translations of the Document under the terms of section 4.
1439+Replacing Invariant Sections with translations requires special
1440+permission from their copyright holders, but you may include
1441+translations of some or all Invariant Sections in addition to the
1442+original versions of these Invariant Sections. You may include a
1443+translation of this License provided that you also include the
1444+original English version of this License. In case of a disagreement
1445+between the translation and the original English version of this
1446+License, the original English version will prevail.
1447+
1448+
1449+9. TERMINATION
1450+
1451+You may not copy, modify, sublicense, or distribute the Document except
1452+as expressly provided for under this License. Any other attempt to
1453+copy, modify, sublicense or distribute the Document is void, and will
1454+automatically terminate your rights under this License. However,
1455+parties who have received copies, or rights, from you under this
1456+License will not have their licenses terminated so long as such
1457+parties remain in full compliance.
1458+
1459+
1460+10. FUTURE REVISIONS OF THIS LICENSE
1461+
1462+The Free Software Foundation may publish new, revised versions
1463+of the GNU Free Documentation License from time to time. Such new
1464+versions will be similar in spirit to the present version, but may
1465+differ in detail to address new problems or concerns. See
1466+http://www.gnu.org/copyleft/.
1467+
1468+Each version of the License is given a distinguishing version number.
1469+If the Document specifies that a particular numbered version of this
1470+License "or any later version" applies to it, you have the option of
1471+following the terms and conditions either of that specified version or
1472+of any later version that has been published (not as a draft) by the
1473+Free Software Foundation. If the Document does not specify a version
1474+number of this License, you may choose any version ever published (not
1475+as a draft) by the Free Software Foundation.
1476+
1477+
1478+ADDENDUM: How to use this License for your documents
1479+
1480+To use this License in a document you have written, include a copy of
1481+the License in the document and put the following copyright and
1482+license notices just after the title page:
1483+
1484+@smallexample
1485+ Copyright (c) YEAR YOUR NAME.
1486+ Permission is granted to copy, distribute and/or modify this document
1487+ under the terms of the GNU Free Documentation License, Version 1.1
1488+ or any later version published by the Free Software Foundation;
1489+ with the Invariant Sections being LIST THEIR TITLES, with the
1490+ Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST.
1491+ A copy of the license is included in the section entitled "GNU
1492+ Free Documentation License".
1493+@end smallexample
1494+
1495+If you have no Invariant Sections, write "with no Invariant Sections"
1496+instead of saying which ones are invariant. If you have no
1497+Front-Cover Texts, write "no Front-Cover Texts" instead of
1498+"Front-Cover Texts being LIST"; likewise for Back-Cover Texts.
1499+
1500+If your document contains nontrivial examples of program code, we
1501+recommend releasing these examples in parallel under your choice of
1502+free software license, such as the GNU General Public License,
1503+to permit their use in free software.
1504+
1505+@node Index
1506+@unnumbered Index
1507+
1508+@printindex cp
1509+
1510+@contents
1511+@bye
34c762af
JB
1512--- binutils-2.17.50.0.2/gas/gasp.c.orig 1970-01-01 01:00:00.000000000 +0100
1513+++ binutils-2.17.50.0.2/gas/gasp.c 2006-06-07 11:22:13.774440000 +0200
1514@@ -0,0 +1,3999 @@
2859501d
JB
1515+/* gasp.c - Gnu assembler preprocessor main program.
1516+ Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
1517+ Free Software Foundation, Inc.
1518+
1519+ Written by Steve and Judy Chamberlain of Cygnus Support,
1520+ sac@cygnus.com
1521+
1522+ This file is part of GASP, the GNU Assembler Preprocessor.
1523+
1524+ GASP is free software; you can redistribute it and/or modify
1525+ it under the terms of the GNU General Public License as published by
1526+ the Free Software Foundation; either version 2, or (at your option)
1527+ any later version.
1528+
1529+ GASP is distributed in the hope that it will be useful,
1530+ but WITHOUT ANY WARRANTY; without even the implied warranty of
1531+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1532+ GNU General Public License for more details.
1533+
1534+ You should have received a copy of the GNU General Public License
1535+ along with GASP; see the file COPYING. If not, write to the Free
1536+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
1537+ 02111-1307, USA. */
1538+
1539+/*
1540+This program translates the input macros and stuff into a form
1541+suitable for gas to consume.
1542+
1543+ gasp [-sdhau] [-c char] [-o <outfile>] <infile>*
1544+
1545+ -s copy source to output
1546+ -c <char> comments are started with <char> instead of !
1547+ -u allow unreasonable stuff
1548+ -p print line numbers
1549+ -d print debugging stats
1550+ -s semi colons start comments
1551+ -a use alternate syntax
1552+ Pseudo ops can start with or without a .
1553+ Labels have to be in first column.
1554+ -I specify include dir
1555+ Macro arg parameters subsituted by name, don't need the &.
1556+ String can start with ' too.
1557+ Strings can be surrounded by <..>
1558+ A %<exp> in a string evaluates the expression
1559+ Literal char in a string with !
1560+*/
1561+
1562+#include "config.h"
3e3b8df7 1563+#include "bfdver.h"
2859501d
JB
1564+
1565+#include <assert.h>
1566+#include <stdio.h>
1567+#include <string.h>
1568+#include "getopt.h"
1569+
1570+#ifdef HAVE_STDLIB_H
1571+#include <stdlib.h>
1572+#endif
1573+
1574+#ifdef NEED_MALLOC_DECLARATION
1575+extern char *malloc ();
1576+#endif
1577+
1578+#include "ansidecl.h"
1579+#include "libiberty.h"
1580+#include "safe-ctype.h"
1581+#include "sb.h"
1582+#include "macro.h"
1583+#include "asintl.h"
1584+#include "xregex.h"
1585+
1586+char *program_version = "1.2";
1587+
1588+/* This is normally declared in as.h, but we don't include that. We
1589+ need the function because other files linked with gasp.c might call
1590+ it. */
1591+extern void as_abort PARAMS ((const char *, int, const char *));
1592+
1593+/* The default obstack chunk size. If we set this to zero, the
1594+ obstack code will use whatever will fit in a 4096 byte block. This
1595+ is used by the hash table code used by macro.c. */
1596+int chunksize = 0;
1597+
1598+#define MAX_INCLUDES 30 /* Maximum include depth. */
1599+#define MAX_REASONABLE 1000 /* Maximum number of expansions. */
1600+
1601+int unreasonable; /* -u on command line. */
1602+int stats; /* -d on command line. */
1603+int print_line_number; /* -p flag on command line. */
1604+int copysource; /* -c flag on command line. */
1605+int warnings; /* Number of WARNINGs generated so far. */
1606+int errors; /* Number of ERRORs generated so far. */
1607+int fatals; /* Number of fatal ERRORs generated so far (either 0 or 1). */
1608+int alternate = 0; /* -a on command line. */
1609+int mri = 0; /* -M on command line. */
1610+char comment_char = '!';
1611+int radix = 10; /* Default radix. */
1612+
1613+int had_end; /* Seen .END. */
1614+
1615+/* The output stream. */
1616+FILE *outfile;
1617+
1618+/* The attributes of each character are stored as a bit pattern
1619+ chartype, which gives us quick tests. */
1620+
1621+#define FIRSTBIT 1
1622+#define NEXTBIT 2
1623+#define SEPBIT 4
1624+#define WHITEBIT 8
1625+#define COMMENTBIT 16
1626+#define BASEBIT 32
1627+#define ISCOMMENTCHAR(x) (chartype[(unsigned char)(x)] & COMMENTBIT)
1628+#define ISFIRSTCHAR(x) (chartype[(unsigned char)(x)] & FIRSTBIT)
1629+#define ISNEXTCHAR(x) (chartype[(unsigned char)(x)] & NEXTBIT)
1630+#define ISSEP(x) (chartype[(unsigned char)(x)] & SEPBIT)
1631+#define ISWHITE(x) (chartype[(unsigned char)(x)] & WHITEBIT)
1632+#define ISBASE(x) (chartype[(unsigned char)(x)] & BASEBIT)
1633+static char chartype[256];
1634+
1635+/* Conditional assembly uses the `ifstack'. Each aif pushes another
1636+ entry onto the stack, and sets the on flag if it should. The aelse
1637+ sets hadelse, and toggles on. An aend pops a level. We limit to
1638+ 100 levels of nesting, not because we're facists pigs with read
1639+ only minds, but because more than 100 levels of nesting is probably
1640+ a bug in the user's macro structure. */
1641+
1642+#define IFNESTING 100
1643+struct {
1644+ int on; /* Is the level being output. */
1645+ int hadelse; /* Has an aelse been seen. */
1646+} ifstack[IFNESTING];
1647+
1648+int ifi;
1649+
1650+/* The final and intermediate results of expression evaluation are kept in
1651+ exp_t's. Note that a symbol is not an sb, but a pointer into the input
1652+ line. It must be coped somewhere safe before the next line is read in. */
1653+
1654+typedef struct {
1655+ char *name;
1656+ int len;
1657+} symbol;
1658+
1659+typedef struct {
1660+ int value; /* Constant part. */
1661+ symbol add_symbol; /* Name part. */
1662+ symbol sub_symbol; /* Name part. */
1663+} exp_t;
1664+
1665+/* Hashing is done in a pretty standard way. A hash_table has a
1666+ pointer to a vector of pointers to hash_entrys, and the size of the
1667+ vector. A hash_entry contains a union of all the info we like to
1668+ store in hash table. If there is a hash collision, hash_entries
1669+ with the same hash are kept in a chain. */
1670+
1671+/* What the data in a hash_entry means. */
1672+typedef enum {
1673+ hash_integer, /* Name->integer mapping. */
1674+ hash_string, /* Name->string mapping. */
1675+ hash_macro, /* Name is a macro. */
1676+ hash_formal /* Name is a formal argument. */
1677+} hash_type;
1678+
1679+typedef struct hs {
1680+ sb key; /* Symbol name. */
1681+ hash_type type; /* Symbol meaning. */
1682+ union {
1683+ sb s;
1684+ int i;
1685+ struct macro_struct *m;
1686+ struct formal_struct *f;
1687+ } value;
1688+ struct hs *next; /* Next hash_entry with same hash key. */
1689+} hash_entry;
1690+
1691+typedef struct {
1692+ hash_entry **table;
1693+ int size;
1694+} hash_table;
1695+
1696+/* How we nest files and expand macros etc.
1697+
1698+ We keep a stack of of include_stack structs. Each include file
1699+ pushes a new level onto the stack. We keep an sb with a pushback
1700+ too. unget chars are pushed onto the pushback sb, getchars first
1701+ checks the pushback sb before reading from the input stream.
1702+
1703+ Small things are expanded by adding the text of the item onto the
1704+ pushback sb. Larger items are grown by pushing a new level and
1705+ allocating the entire pushback buf for the item. Each time
1706+ something like a macro is expanded, the stack index is changed. We
1707+ can then perform an exitm by popping all entries off the stack with
1708+ the same stack index. If we're being reasonable, we can detect
1709+ recusive expansion by checking the index is reasonably small. */
1710+
1711+typedef enum {
1712+ include_file, include_repeat, include_while, include_macro
1713+} include_type;
1714+
1715+struct include_stack {
1716+ sb pushback; /* Current pushback stream. */
1717+ int pushback_index; /* Next char to read from stream. */
1718+ FILE *handle; /* Open file. */
1719+ sb name; /* Name of file. */
1720+ int linecount; /* Number of lines read so far. */
1721+ include_type type;
1722+ int index; /* Index of this layer. */
1723+} include_stack[MAX_INCLUDES];
1724+
1725+struct include_stack *sp;
1726+#define isp (sp - include_stack)
1727+
1728+/* Include file list. */
1729+
1730+typedef struct include_path {
1731+ struct include_path *next;
1732+ sb path;
1733+} include_path;
1734+
1735+include_path *paths_head;
1736+include_path *paths_tail;
1737+
1738+static void quit PARAMS ((void));
1739+static void hash_new_table PARAMS ((int, hash_table *));
1740+static int hash PARAMS ((sb *));
1741+static hash_entry *hash_create PARAMS ((hash_table *, sb *));
1742+static void hash_add_to_string_table PARAMS ((hash_table *, sb *, sb *, int));
1743+static void hash_add_to_int_table PARAMS ((hash_table *, sb *, int));
1744+static hash_entry *hash_lookup PARAMS ((hash_table *, sb *));
1745+static void checkconst PARAMS ((int, exp_t *));
1746+static int is_flonum PARAMS ((int, sb *));
1747+static int chew_flonum PARAMS ((int, sb *, sb *));
1748+static int sb_strtol PARAMS ((int, sb *, int, int *));
1749+static int level_0 PARAMS ((int, sb *, exp_t *));
1750+static int level_1 PARAMS ((int, sb *, exp_t *));
1751+static int level_2 PARAMS ((int, sb *, exp_t *));
1752+static int level_3 PARAMS ((int, sb *, exp_t *));
1753+static int level_4 PARAMS ((int, sb *, exp_t *));
1754+static int level_5 PARAMS ((int, sb *, exp_t *));
1755+static int exp_parse PARAMS ((int, sb *, exp_t *));
1756+static void exp_string PARAMS ((exp_t *, sb *));
1757+static int exp_get_abs PARAMS ((const char *, int, sb *, int *));
1758+#if 0
1759+static void strip_comments PARAMS ((sb *));
1760+#endif
1761+static void unget PARAMS ((int));
1762+static void include_buf PARAMS ((sb *, sb *, include_type, int));
1763+static void include_print_where_line PARAMS ((FILE *));
1764+static void include_print_line PARAMS ((FILE *));
1765+static int get_line PARAMS ((sb *));
1766+static int grab_label PARAMS ((sb *, sb *));
1767+static void change_base PARAMS ((int, sb *, sb *));
1768+static void do_end PARAMS ((sb *));
1769+static void do_assign PARAMS ((int, int, sb *));
1770+static void do_radix PARAMS ((sb *));
1771+static int get_opsize PARAMS ((int, sb *, int *));
1772+static int eol PARAMS ((int, sb *));
1773+static void do_data PARAMS ((int, sb *, int));
1774+static void do_datab PARAMS ((int, sb *));
1775+static void do_align PARAMS ((int, sb *));
1776+static void do_res PARAMS ((int, sb *, int));
1777+static void do_export PARAMS ((sb *));
1778+static void do_print PARAMS ((int, sb *));
1779+static void do_heading PARAMS ((int, sb *));
1780+static void do_page PARAMS ((void));
1781+static void do_form PARAMS ((int, sb *));
1782+static int get_any_string PARAMS ((int, sb *, sb *, int, int));
1783+static int skip_openp PARAMS ((int, sb *));
1784+static int skip_closep PARAMS ((int, sb *));
1785+static int dolen PARAMS ((int, sb *, sb *));
1786+static int doinstr PARAMS ((int, sb *, sb *));
1787+static int dosubstr PARAMS ((int, sb *, sb *));
1788+static void process_assigns PARAMS ((int, sb *, sb *));
1789+static int get_and_process PARAMS ((int, sb *, sb *));
1790+static void process_file PARAMS ((void));
1791+static void free_old_entry PARAMS ((hash_entry *));
1792+static void do_assigna PARAMS ((int, sb *));
1793+static void do_assignc PARAMS ((int, sb *));
1794+static void do_reg PARAMS ((int, sb *));
1795+static int condass_lookup_name PARAMS ((sb *, int, sb *, int));
1796+static int whatcond PARAMS ((int, sb *, int *));
1797+static int istrue PARAMS ((int, sb *));
1798+static void do_aif PARAMS ((int, sb *));
1799+static void do_aelse PARAMS ((void));
1800+static void do_aendi PARAMS ((void));
1801+static int condass_on PARAMS ((void));
1802+static void do_if PARAMS ((int, sb *, int));
1803+static int get_mri_string PARAMS ((int, sb *, sb *, int));
1804+static void do_ifc PARAMS ((int, sb *, int));
1805+static void do_aendr PARAMS ((void));
1806+static void do_awhile PARAMS ((int, sb *));
1807+static void do_aendw PARAMS ((void));
1808+static void do_exitm PARAMS ((void));
1809+static void do_arepeat PARAMS ((int, sb *));
1810+static void do_endm PARAMS ((void));
1811+static void do_irp PARAMS ((int, sb *, int));
1812+static void do_local PARAMS ((int, sb *));
1813+static void do_macro PARAMS ((int, sb *));
1814+static int macro_op PARAMS ((int, sb *));
1815+static int getstring PARAMS ((int, sb *, sb *));
1816+static void do_sdata PARAMS ((int, sb *, int));
1817+static void do_sdatab PARAMS ((int, sb *));
1818+static int new_file PARAMS ((const char *));
1819+static void do_include PARAMS ((int, sb *));
1820+static void include_pop PARAMS ((void));
1821+static int get PARAMS ((void));
1822+static int linecount PARAMS ((void));
1823+static int include_next_index PARAMS ((void));
1824+static void chartype_init PARAMS ((void));
1825+static int process_pseudo_op PARAMS ((int, sb *, sb *));
1826+static void add_keyword PARAMS ((const char *, int));
1827+static void process_init PARAMS ((void));
1828+static void do_define PARAMS ((const char *));
1829+static void show_usage PARAMS ((FILE *, int));
1830+static void show_help PARAMS ((void));
1831+
1684d5ca
JB
1832+/* --- functions recently removed from sb.c --- */
1833+
1834+/* put a null at the end of the sb at in and return the start of the
1835+ * string, so that it can be used as an arg to printf %s. */
1836+
1837+static char *
1838+sb_name (sb *in)
1839+{
1840+ /* stick a null on the end of the string */
1841+ sb_add_char (in, 0);
1842+ return in->ptr;
1843+}
1844+
1845+/* print the sb at ptr to the output file */
1846+
1847+static void
1848+sb_print (FILE *outfile, sb *ptr)
1849+{
1850+ int i;
1851+ int nc = 0;
1852+
1853+ for (i = 0; i < ptr->len; i++)
1854+ {
1855+ if (nc)
1856+ {
1857+ fprintf (outfile, ",");
1858+ }
1859+ fprintf (outfile, "%d", ptr->ptr[i]);
1860+ nc = 1;
1861+ }
1862+}
1863+
1864+/* print the sb at ptr to the output file */
1865+
1866+static void
1867+sb_print_at (FILE *outfile, int idx, sb *ptr)
1868+{
1869+ int i;
1870+ for (i = idx; i < ptr->len; i++)
1871+ putc (ptr->ptr[i], outfile);
1872+}
1873+
2859501d
JB
1874+#define FATAL(x) \
1875+ do \
1876+ { \
1877+ include_print_where_line (stderr); \
1878+ fprintf x; \
1879+ fatals++; \
1880+ quit (); \
1881+ } \
1882+ while (0)
1883+
1884+#define ERROR(x) \
1885+ do \
1886+ { \
1887+ include_print_where_line (stderr); \
1888+ fprintf x; \
1889+ errors++; \
1890+ } \
1891+ while (0)
1892+
1893+#define WARNING(x) \
1894+ do \
1895+ { \
1896+ include_print_where_line (stderr); \
1897+ fprintf x; \
1898+ warnings++; \
1899+ } \
1900+ while (0)
1901+
1902+/* Exit the program and return the right ERROR code. */
1903+
1904+static void
1905+quit ()
1906+{
1907+ int exitcode;
1908+ if (fatals + errors)
1909+ exitcode = 1;
1910+ else
1911+ exitcode = 0;
1912+
2859501d
JB
1913+ exit (exitcode);
1914+}
1915+
1916+/* Hash table maintenance. */
1917+
1918+/* Build a new hash table with size buckets
1919+ and fill in the info at ptr. */
1920+
1921+static void
1922+hash_new_table (size, ptr)
1923+ int size;
1924+ hash_table *ptr;
1925+{
1926+ int i;
1927+ ptr->size = size;
1928+ ptr->table = (hash_entry **) xmalloc (size * (sizeof (hash_entry *)));
1929+ /* Fill with null-pointer, not zero-bit-pattern. */
1930+ for (i = 0; i < size; i++)
1931+ ptr->table[i] = 0;
1932+}
1933+
1934+/* Calculate and return the hash value of the sb at key. */
1935+
1936+static int
1937+hash (key)
1938+ sb *key;
1939+{
1940+ int k = 0x1234;
1941+ int i;
1942+ char *p = key->ptr;
1943+ for (i = 0; i < key->len; i++)
1944+ {
1945+ k ^= (k << 2) ^ *p;
1946+ p++;
1947+ }
1948+ return k & 0xf0fff;
1949+}
1950+
1951+/* Look up key in hash_table tab. If present, then return it,
1952+ otherwise build a new one and fill it with hash_integer. */
1953+
1954+static hash_entry *
1955+hash_create (tab, key)
1956+ hash_table *tab;
1957+ sb *key;
1958+{
1959+ int k = hash (key) % tab->size;
1960+ hash_entry *p;
1961+ hash_entry **table = tab->table;
1962+
1963+ p = table[k];
1964+
1965+ while (1)
1966+ {
1967+ if (!p)
1968+ {
1969+ hash_entry *n = (hash_entry *) xmalloc (sizeof (hash_entry));
1970+ n->next = table[k];
1971+ sb_new (&n->key);
1972+ sb_add_sb (&n->key, key);
1973+ table[k] = n;
1974+ n->type = hash_integer;
1975+ return n;
1976+ }
1977+ if (strncmp (table[k]->key.ptr, key->ptr, key->len) == 0)
1978+ {
1979+ return p;
1980+ }
1981+ p = p->next;
1982+ }
1983+}
1984+
1985+/* Add sb name with key into hash_table tab.
1986+ If replacing old value and again, then ERROR. */
1987+
1988+static void
1989+hash_add_to_string_table (tab, key, name, again)
1990+ hash_table *tab;
1991+ sb *key;
1992+ sb *name;
1993+ int again;
1994+{
1995+ hash_entry *ptr = hash_create (tab, key);
1996+ if (ptr->type == hash_integer)
1997+ {
1998+ sb_new (&ptr->value.s);
1999+ }
2000+ if (ptr->value.s.len)
2001+ {
2002+ if (!again)
2003+ ERROR ((stderr, _("redefinition not allowed\n")));
2004+ }
2005+
2006+ ptr->type = hash_string;
2007+ sb_reset (&ptr->value.s);
2008+
2009+ sb_add_sb (&ptr->value.s, name);
2010+}
2011+
2012+/* Add integer name to hash_table tab with sb key. */
2013+
2014+static void
2015+hash_add_to_int_table (tab, key, name)
2016+ hash_table *tab;
2017+ sb *key;
2018+ int name;
2019+{
2020+ hash_entry *ptr = hash_create (tab, key);
2021+ ptr->value.i = name;
2022+}
2023+
2024+/* Look up sb key in hash_table tab.
2025+ If found, return hash_entry result, else 0. */
2026+
2027+static hash_entry *
2028+hash_lookup (tab, key)
2029+ hash_table *tab;
2030+ sb *key;
2031+{
2032+ int k = hash (key) % tab->size;
2033+ hash_entry **table = tab->table;
2034+ hash_entry *p = table[k];
2035+ while (p)
2036+ {
2037+ if (p->key.len == key->len
2038+ && strncmp (p->key.ptr, key->ptr, key->len) == 0)
2039+ return p;
2040+ p = p->next;
2041+ }
2042+ return 0;
2043+}
2044+
2045+/* expressions
2046+
2047+ are handled in a really simple recursive decent way. each bit of
2048+ the machine takes an index into an sb and a pointer to an exp_t,
2049+ modifies the *exp_t and returns the index of the first character
2050+ past the part of the expression parsed.
2051+
2052+ expression precedence:
2053+ ( )
2054+ unary + - ~
2055+ * /
2056+ + -
2057+ &
2058+ | ~
2059+*/
2060+
2061+/* Make sure that the exp_t at term is constant.
2062+ If not the give the op ERROR. */
2063+
2064+static void
2065+checkconst (op, term)
2066+ int op;
2067+ exp_t *term;
2068+{
2069+ if (term->add_symbol.len
2070+ || term->sub_symbol.len)
2071+ {
2072+ ERROR ((stderr, _("the %c operator cannot take non-absolute arguments.\n"), op));
2073+ }
2074+}
2075+
2076+/* Chew the flonum from the string starting at idx. Adjust idx to
2077+ point to the next character after the flonum. */
2078+
2079+static int
2080+chew_flonum (idx, string, out)
2081+ int idx;
2082+ sb *string;
2083+ sb *out;
2084+{
2085+ sb buf;
2086+ regex_t reg;
2087+ regmatch_t match;
2088+
2089+ /* Duplicate and null terminate `string'. */
2090+ sb_new (&buf);
2091+ sb_add_sb (&buf, string);
2092+ sb_add_char (&buf, '\0');
2093+
2094+ if (regcomp (&reg, "([0-9]*\\.[0-9]+([eE][+-]?[0-9]+)?)", REG_EXTENDED) != 0)
2095+ return idx;
2096+ if (regexec (&reg, &buf.ptr[idx], 1, &match, 0) != 0)
2097+ return idx;
2098+
2099+ /* Copy the match to the output. */
2100+ assert (match.rm_eo >= match.rm_so);
2101+ sb_add_buffer (out, &buf.ptr[idx], match.rm_eo - match.rm_so);
2102+
2103+ sb_kill (&buf);
2104+ regfree (&reg);
2105+ idx += match.rm_eo;
2106+ return idx;
2107+}
2108+
2109+static int
2110+is_flonum (idx, string)
2111+ int idx;
2112+ sb *string;
2113+{
2114+ sb buf;
2115+ regex_t reg;
2116+ int rc;
2117+
2118+ /* Duplicate and null terminate `string'. */
2119+ sb_new (&buf);
2120+ sb_add_sb (&buf, string);
2121+ sb_add_char (&buf, '\0');
2122+
2123+ if (regcomp (&reg, "^[0-9]*\\.[0-9]+([eE][+-]?[0-9]+)?", REG_EXTENDED) != 0)
2124+ return 0;
2125+
2126+ rc = regexec (&reg, &buf.ptr[idx], 0, NULL, 0);
2127+ sb_kill (&buf);
2128+ regfree (&reg);
2129+ return (rc == 0);
2130+}
2131+
2132+/* Turn the number in string at idx into a number of base, fill in
2133+ ptr, and return the index of the first character not in the number. */
2134+
2135+static int
2136+sb_strtol (idx, string, base, ptr)
2137+ int idx;
2138+ sb *string;
2139+ int base;
2140+ int *ptr;
2141+{
2142+ int value = 0;
2143+ idx = sb_skip_white (idx, string);
2144+
2145+ while (idx < string->len)
2146+ {
2147+ int ch = string->ptr[idx];
2148+ int dig = 0;
2149+ if (ISDIGIT (ch))
2150+ dig = ch - '0';
2151+ else if (ch >= 'a' && ch <= 'f')
2152+ dig = ch - 'a' + 10;
2153+ else if (ch >= 'A' && ch <= 'F')
2154+ dig = ch - 'A' + 10;
2155+ else
2156+ break;
2157+
2158+ if (dig >= base)
2159+ break;
2160+
2161+ value = value * base + dig;
2162+ idx++;
2163+ }
2164+ *ptr = value;
2165+ return idx;
2166+}
2167+
2168+static int
2169+level_0 (idx, string, lhs)
2170+ int idx;
2171+ sb *string;
2172+ exp_t *lhs;
2173+{
2174+ lhs->add_symbol.len = 0;
2175+ lhs->add_symbol.name = 0;
2176+
2177+ lhs->sub_symbol.len = 0;
2178+ lhs->sub_symbol.name = 0;
2179+
2180+ idx = sb_skip_white (idx, string);
2181+
2182+ lhs->value = 0;
2183+
2184+ if (ISDIGIT (string->ptr[idx]))
2185+ {
2186+ idx = sb_strtol (idx, string, 10, &lhs->value);
2187+ }
2188+ else if (ISFIRSTCHAR (string->ptr[idx]))
2189+ {
2190+ int len = 0;
2191+ lhs->add_symbol.name = string->ptr + idx;
2192+ while (idx < string->len && ISNEXTCHAR (string->ptr[idx]))
2193+ {
2194+ idx++;
2195+ len++;
2196+ }
2197+ lhs->add_symbol.len = len;
2198+ }
2199+ else if (string->ptr[idx] == '"')
2200+ {
2201+ sb acc;
2202+ sb_new (&acc);
2203+ ERROR ((stderr, _("string where expression expected.\n")));
2204+ idx = getstring (idx, string, &acc);
2205+ sb_kill (&acc);
2206+ }
2207+ else
2208+ {
2209+ ERROR ((stderr, _("can't find primary in expression.\n")));
2210+ idx++;
2211+ }
2212+ return sb_skip_white (idx, string);
2213+}
2214+
2215+static int
2216+level_1 (idx, string, lhs)
2217+ int idx;
2218+ sb *string;
2219+ exp_t *lhs;
2220+{
2221+ idx = sb_skip_white (idx, string);
2222+
2223+ switch (string->ptr[idx])
2224+ {
2225+ case '+':
2226+ idx = level_1 (idx + 1, string, lhs);
2227+ break;
2228+ case '~':
2229+ idx = level_1 (idx + 1, string, lhs);
2230+ checkconst ('~', lhs);
2231+ lhs->value = ~lhs->value;
2232+ break;
2233+ case '-':
2234+ {
2235+ symbol t;
2236+ idx = level_1 (idx + 1, string, lhs);
2237+ lhs->value = -lhs->value;
2238+ t = lhs->add_symbol;
2239+ lhs->add_symbol = lhs->sub_symbol;
2240+ lhs->sub_symbol = t;
2241+ break;
2242+ }
2243+ case '(':
2244+ idx++;
2245+ idx = level_5 (sb_skip_white (idx, string), string, lhs);
2246+ if (string->ptr[idx] != ')')
2247+ ERROR ((stderr, _("misplaced closing parens.\n")));
2248+ else
2249+ idx++;
2250+ break;
2251+ default:
2252+ idx = level_0 (idx, string, lhs);
2253+ break;
2254+ }
2255+ return sb_skip_white (idx, string);
2256+}
2257+
2258+static int
2259+level_2 (idx, string, lhs)
2260+ int idx;
2261+ sb *string;
2262+ exp_t *lhs;
2263+{
2264+ exp_t rhs;
2265+
2266+ idx = level_1 (idx, string, lhs);
2267+
2268+ while (idx < string->len && (string->ptr[idx] == '*'
2269+ || string->ptr[idx] == '/'))
2270+ {
2271+ char op = string->ptr[idx++];
2272+ idx = level_1 (idx, string, &rhs);
2273+ switch (op)
2274+ {
2275+ case '*':
2276+ checkconst ('*', lhs);
2277+ checkconst ('*', &rhs);
2278+ lhs->value *= rhs.value;
2279+ break;
2280+ case '/':
2281+ checkconst ('/', lhs);
2282+ checkconst ('/', &rhs);
2283+ if (rhs.value == 0)
2284+ ERROR ((stderr, _("attempt to divide by zero.\n")));
2285+ else
2286+ lhs->value /= rhs.value;
2287+ break;
2288+ }
2289+ }
2290+ return sb_skip_white (idx, string);
2291+}
2292+
2293+static int
2294+level_3 (idx, string, lhs)
2295+ int idx;
2296+ sb *string;
2297+ exp_t *lhs;
2298+{
2299+ exp_t rhs;
2300+
2301+ idx = level_2 (idx, string, lhs);
2302+
2303+ while (idx < string->len
2304+ && (string->ptr[idx] == '+'
2305+ || string->ptr[idx] == '-'))
2306+ {
2307+ char op = string->ptr[idx++];
2308+ idx = level_2 (idx, string, &rhs);
2309+ switch (op)
2310+ {
2311+ case '+':
2312+ lhs->value += rhs.value;
2313+ if (lhs->add_symbol.name && rhs.add_symbol.name)
2314+ {
2315+ ERROR ((stderr, _("can't add two relocatable expressions\n")));
2316+ }
2317+ /* Change nn+symbol to symbol + nn. */
2318+ if (rhs.add_symbol.name)
2319+ {
2320+ lhs->add_symbol = rhs.add_symbol;
2321+ }
2322+ break;
2323+ case '-':
2324+ lhs->value -= rhs.value;
2325+ lhs->sub_symbol = rhs.add_symbol;
2326+ break;
2327+ }
2328+ }
2329+ return sb_skip_white (idx, string);
2330+}
2331+
2332+static int
2333+level_4 (idx, string, lhs)
2334+ int idx;
2335+ sb *string;
2336+ exp_t *lhs;
2337+{
2338+ exp_t rhs;
2339+
2340+ idx = level_3 (idx, string, lhs);
2341+
2342+ while (idx < string->len &&
2343+ string->ptr[idx] == '&')
2344+ {
2345+ char op = string->ptr[idx++];
2346+ idx = level_3 (idx, string, &rhs);
2347+ switch (op)
2348+ {
2349+ case '&':
2350+ checkconst ('&', lhs);
2351+ checkconst ('&', &rhs);
2352+ lhs->value &= rhs.value;
2353+ break;
2354+ }
2355+ }
2356+ return sb_skip_white (idx, string);
2357+}
2358+
2359+static int
2360+level_5 (idx, string, lhs)
2361+ int idx;
2362+ sb *string;
2363+ exp_t *lhs;
2364+{
2365+ exp_t rhs;
2366+
2367+ idx = level_4 (idx, string, lhs);
2368+
2369+ while (idx < string->len
2370+ && (string->ptr[idx] == '|' || string->ptr[idx] == '~'))
2371+ {
2372+ char op = string->ptr[idx++];
2373+ idx = level_4 (idx, string, &rhs);
2374+ switch (op)
2375+ {
2376+ case '|':
2377+ checkconst ('|', lhs);
2378+ checkconst ('|', &rhs);
2379+ lhs->value |= rhs.value;
2380+ break;
2381+ case '~':
2382+ checkconst ('~', lhs);
2383+ checkconst ('~', &rhs);
2384+ lhs->value ^= rhs.value;
2385+ break;
2386+ }
2387+ }
2388+ return sb_skip_white (idx, string);
2389+}
2390+
2391+/* Parse the expression at offset idx into string, fill up res with
2392+ the result. Return the index of the first char past the
2393+ expression. */
2394+
2395+static int
2396+exp_parse (idx, string, res)
2397+ int idx;
2398+ sb *string;
2399+ exp_t *res;
2400+{
2401+ return level_5 (sb_skip_white (idx, string), string, res);
2402+}
2403+
2404+/* Turn the expression at exp into text and glue it onto the end of
2405+ string. */
2406+
2407+static void
2408+exp_string (exp, string)
2409+ exp_t *exp;
2410+ sb *string;
2411+{
2412+ int np = 0;
2413+ int ad = 0;
2414+ sb_reset (string);
2415+
2416+ if (exp->add_symbol.len)
2417+ {
2418+ sb_add_buffer (string, exp->add_symbol.name, exp->add_symbol.len);
2419+ np = 1;
2420+ ad = 1;
2421+ }
2422+ if (exp->value)
2423+ {
2424+ char buf[20];
2425+ if (np)
2426+ sb_add_char (string, '+');
2427+ sprintf (buf, "%d", exp->value);
2428+ sb_add_string (string, buf);
2429+ np = 1;
2430+ ad = 1;
2431+ }
2432+ if (exp->sub_symbol.len)
2433+ {
2434+ sb_add_char (string, '-');
2435+ sb_add_buffer (string, exp->add_symbol.name, exp->add_symbol.len);
2436+ np = 0;
2437+ ad = 1;
2438+ }
2439+
2440+ if (!ad)
2441+ sb_add_char (string, '0');
2442+}
2443+
2444+/* Parse the expression at offset idx into sb in. Return the value in
2445+ val. If the expression is not constant, give ERROR emsg. Return
2446+ the index of the first character past the end of the expression. */
2447+
2448+static int
2449+exp_get_abs (emsg, idx, in, val)
2450+ const char *emsg;
2451+ int idx;
2452+ sb *in;
2453+ int *val;
2454+{
2455+ exp_t res;
2456+ idx = exp_parse (idx, in, &res);
2457+ if (res.add_symbol.len || res.sub_symbol.len)
2458+ ERROR ((stderr, "%s", emsg));
2459+ *val = res.value;
2460+ return idx;
2461+}
2462+
2463+/* Current label parsed from line. */
2464+sb label;
2465+
2466+/* Hash table for all assigned variables. */
2467+hash_table assign_hash_table;
2468+
2469+/* Hash table for keyword. */
2470+hash_table keyword_hash_table;
2471+
2472+/* Hash table for eq variables. */
2473+hash_table vars;
2474+
2475+#define in_comment ';'
2476+
2477+#if 0
2478+static void
2479+strip_comments (out)
2480+ sb *out;
2481+{
2482+ char *s = out->ptr;
2483+ int i = 0;
2484+ for (i = 0; i < out->len; i++)
2485+ {
2486+ if (ISCOMMENTCHAR (s[i]))
2487+ {
2488+ out->len = i;
2489+ return;
2490+ }
2491+ }
2492+}
2493+#endif
2494+
2495+/* Push back character ch so that it can be read again. */
2496+
2497+static void
2498+unget (ch)
2499+ int ch;
2500+{
2501+ if (ch == '\n')
2502+ {
2503+ sp->linecount--;
2504+ }
2505+ if (sp->pushback_index)
2506+ sp->pushback_index--;
2507+ else
2508+ sb_add_char (&sp->pushback, ch);
2509+}
2510+
2511+/* Push the sb ptr onto the include stack, with the given name, type
2512+ and index. */
2513+
2514+static void
2515+include_buf (name, ptr, type, index)
2516+ sb *name;
2517+ sb *ptr;
2518+ include_type type;
2519+ int index;
2520+{
2521+ sp++;
2522+ if (sp - include_stack >= MAX_INCLUDES)
2523+ FATAL ((stderr, _("unreasonable nesting.\n")));
2524+ sb_new (&sp->name);
2525+ sb_add_sb (&sp->name, name);
2526+ sp->handle = 0;
2527+ sp->linecount = 1;
2528+ sp->pushback_index = 0;
2529+ sp->type = type;
2530+ sp->index = index;
2531+ sb_new (&sp->pushback);
2532+ sb_add_sb (&sp->pushback, ptr);
2533+}
2534+
2535+/* Used in ERROR messages, print info on where the include stack is
2536+ onto file. */
2537+
2538+static void
2539+include_print_where_line (file)
2540+ FILE *file;
2541+{
2542+ struct include_stack *p = include_stack + 1;
2543+
2544+ while (p <= sp)
2545+ {
2546+ fprintf (file, "%s:%d ", sb_name (&p->name), p->linecount - 1);
2547+ p++;
2548+ }
2549+}
2550+
2551+/* Used in listings, print the line number onto file. */
2552+
2553+static void
2554+include_print_line (file)
2555+ FILE *file;
2556+{
2557+ int n;
2558+ struct include_stack *p = include_stack + 1;
2559+
2560+ n = fprintf (file, "%4d", p->linecount);
2561+ p++;
2562+ while (p <= sp)
2563+ {
2564+ n += fprintf (file, ".%d", p->linecount);
2565+ p++;
2566+ }
2567+ while (n < 8 * 3)
2568+ {
2569+ fprintf (file, " ");
2570+ n++;
2571+ }
2572+}
2573+
2574+/* Read a line from the top of the include stack into sb in. */
2575+
2576+static int
2577+get_line (in)
2578+ sb *in;
2579+{
2580+ int online = 0;
2eacf7fd 2581+ int more = 1, ch = 0;
2859501d
JB
2582+
2583+ if (copysource)
2584+ {
2585+ putc (comment_char, outfile);
2586+ if (print_line_number)
2587+ include_print_line (outfile);
2588+ }
2589+
2590+ while (1)
2591+ {
2eacf7fd 2592+ ch = get ();
2859501d
JB
2593+
2594+ while (ch == '\r')
2595+ ch = get ();
2596+
2597+ if (ch == EOF)
2598+ {
2599+ if (online)
2600+ {
2601+ WARNING ((stderr, _("End of file not at start of line.\n")));
2602+ if (copysource)
2603+ putc ('\n', outfile);
2604+ ch = '\n';
2605+ }
2606+ else
2607+ more = 0;
2608+ break;
2609+ }
2610+
2611+ if (copysource)
2612+ {
2613+ putc (ch, outfile);
2614+ }
2615+
2616+ if (ch == '\n')
2617+ {
2618+ ch = get ();
2619+ online = 0;
2620+ if (ch == '+')
2621+ {
2622+ /* Continued line. */
2623+ if (copysource)
2624+ {
2625+ putc (comment_char, outfile);
2626+ putc ('+', outfile);
2627+ }
2628+ ch = get ();
2629+ }
2630+ else
2631+ {
2632+ if (ch != EOF)
2633+ unget (ch);
2eacf7fd 2634+ ch = '\n'; break;
2859501d
JB
2635+ }
2636+ }
2637+ else
2638+ {
2639+ sb_add_char (in, ch);
2640+ }
2641+ online++;
2642+ }
2643+
2eacf7fd 2644+ return more ? ch : 0;
2859501d
JB
2645+}
2646+
2647+/* Find a label from sb in and put it in out. */
2648+
2649+static int
2650+grab_label (in, out)
2651+ sb *in;
2652+ sb *out;
2653+{
2654+ int i = 0;
2655+ sb_reset (out);
2656+ if (ISFIRSTCHAR (in->ptr[i]) || in->ptr[i] == '\\')
2657+ {
2658+ sb_add_char (out, in->ptr[i]);
2659+ i++;
2660+ while ((ISNEXTCHAR (in->ptr[i])
2661+ || in->ptr[i] == '\\'
2662+ || in->ptr[i] == '&')
2663+ && i < in->len)
2664+ {
2665+ sb_add_char (out, in->ptr[i]);
2666+ i++;
2667+ }
2668+ }
2669+ return i;
2670+}
2671+
2672+/* Find all strange base stuff and turn into decimal. Also
2673+ find all the other numbers and convert them from the default radix. */
2674+
2675+static void
2676+change_base (idx, in, out)
2677+ int idx;
2678+ sb *in;
2679+ sb *out;
2680+{
2681+ char buffer[20];
2682+
2683+ while (idx < in->len)
2684+ {
2685+ if (in->ptr[idx] == '\\'
2686+ && idx + 1 < in->len
2687+ && in->ptr[idx + 1] == '(')
2688+ {
2689+ idx += 2;
2690+ while (idx < in->len
2691+ && in->ptr[idx] != ')')
2692+ {
2693+ sb_add_char (out, in->ptr[idx]);
2694+ idx++;
2695+ }
2696+ if (idx < in->len)
2697+ idx++;
2698+ }
2699+ else if (idx < in->len - 1 && in->ptr[idx + 1] == '\'' && ! mri)
2700+ {
2701+ int base;
2702+ int value;
2703+ switch (in->ptr[idx])
2704+ {
2705+ case 'b':
2706+ case 'B':
2707+ base = 2;
2708+ break;
2709+ case 'q':
2710+ case 'Q':
2711+ base = 8;
2712+ break;
2713+ case 'h':
2714+ case 'H':
2715+ base = 16;
2716+ break;
2717+ case 'd':
2718+ case 'D':
2719+ base = 10;
2720+ break;
2721+ default:
2722+ ERROR ((stderr, _("Illegal base character %c.\n"), in->ptr[idx]));
2723+ base = 10;
2724+ break;
2725+ }
2726+
2727+ idx = sb_strtol (idx + 2, in, base, &value);
2728+ sprintf (buffer, "%d", value);
2729+ sb_add_string (out, buffer);
2730+ }
2731+ else if (ISFIRSTCHAR (in->ptr[idx]))
2732+ {
2733+ /* Copy entire names through quickly. */
2734+ sb_add_char (out, in->ptr[idx]);
2735+ idx++;
2736+ while (idx < in->len && ISNEXTCHAR (in->ptr[idx]))
2737+ {
2738+ sb_add_char (out, in->ptr[idx]);
2739+ idx++;
2740+ }
2741+ }
2742+ else if (is_flonum (idx, in))
2743+ {
2744+ idx = chew_flonum (idx, in, out);
2745+ }
2746+ else if (ISDIGIT (in->ptr[idx]))
2747+ {
2748+ int value;
2749+ /* All numbers must start with a digit, let's chew it and
2750+ spit out decimal. */
2751+ idx = sb_strtol (idx, in, radix, &value);
2752+ sprintf (buffer, "%d", value);
2753+ sb_add_string (out, buffer);
2754+
2755+ /* Skip all undigsested letters. */
2756+ while (idx < in->len && ISNEXTCHAR (in->ptr[idx]))
2757+ {
2758+ sb_add_char (out, in->ptr[idx]);
2759+ idx++;
2760+ }
2761+ }
2762+ else if (in->ptr[idx] == '"' || in->ptr[idx] == '\'')
2763+ {
2764+ char tchar = in->ptr[idx];
2765+ /* Copy entire names through quickly. */
2766+ sb_add_char (out, in->ptr[idx]);
2767+ idx++;
2768+ while (idx < in->len && in->ptr[idx] != tchar)
2769+ {
2770+ sb_add_char (out, in->ptr[idx]);
2771+ idx++;
2772+ }
2773+ }
2774+ else
2775+ {
2776+ /* Nothing special, just pass it through. */
2777+ sb_add_char (out, in->ptr[idx]);
2778+ idx++;
2779+ }
2780+ }
2781+
2782+}
2783+
2784+/* .end */
2785+
2786+static void
2787+do_end (in)
2788+ sb *in;
2789+{
2790+ had_end = 1;
2791+ if (mri)
2792+ fprintf (outfile, "%s\n", sb_name (in));
2793+}
2794+
2795+/* .assign */
2796+
2797+static void
2798+do_assign (again, idx, in)
2799+ int again;
2800+ int idx;
2801+ sb *in;
2802+{
2803+ /* Stick label in symbol table with following value. */
2804+ exp_t e;
2805+ sb acc;
2806+
2807+ sb_new (&acc);
2808+ idx = exp_parse (idx, in, &e);
2809+ exp_string (&e, &acc);
2810+ hash_add_to_string_table (&assign_hash_table, &label, &acc, again);
2811+ sb_kill (&acc);
2812+}
2813+
2814+/* .radix [b|q|d|h] */
2815+
2816+static void
2817+do_radix (ptr)
2818+ sb *ptr;
2819+{
2820+ int idx = sb_skip_white (0, ptr);
2821+ switch (ptr->ptr[idx])
2822+ {
2823+ case 'B':
2824+ case 'b':
2825+ radix = 2;
2826+ break;
2827+ case 'q':
2828+ case 'Q':
2829+ radix = 8;
2830+ break;
2831+ case 'd':
2832+ case 'D':
2833+ radix = 10;
2834+ break;
2835+ case 'h':
2836+ case 'H':
2837+ radix = 16;
2838+ break;
2839+ default:
2840+ ERROR ((stderr, _("radix is %c must be one of b, q, d or h"), radix));
2841+ }
2842+}
2843+
2844+/* Parse off a .b, .w or .l. */
2845+
2846+static int
2847+get_opsize (idx, in, size)
2848+ int idx;
2849+ sb *in;
2850+ int *size;
2851+{
2852+ *size = 4;
2853+ if (in->ptr[idx] == '.')
2854+ {
2855+ idx++;
2856+ }
2857+ switch (in->ptr[idx])
2858+ {
2859+ case 'b':
2860+ case 'B':
2861+ *size = 1;
2862+ break;
2863+ case 'w':
2864+ case 'W':
2865+ *size = 2;
2866+ break;
2867+ case 'l':
2868+ case 'L':
2869+ *size = 4;
2870+ break;
2871+ case ' ':
2872+ case '\t':
2873+ break;
2874+ default:
2875+ ERROR ((stderr, _("size must be one of b, w or l, is %c.\n"), in->ptr[idx]));
2876+ break;
2877+ }
2878+ idx++;
2879+
2880+ return idx;
2881+}
2882+
2883+static int
2884+eol (idx, line)
2885+ int idx;
2886+ sb *line;
2887+{
2888+ idx = sb_skip_white (idx, line);
2889+ if (idx < line->len
2890+ && ISCOMMENTCHAR(line->ptr[idx]))
2891+ return 1;
2892+ if (idx >= line->len)
2893+ return 1;
2894+ return 0;
2895+}
2896+
2897+/* .data [.b|.w|.l] <data>*
2898+ or d[bwl] <data>* */
2899+
2900+static void
2901+do_data (idx, in, size)
2902+ int idx;
2903+ sb *in;
2904+ int size;
2905+{
2906+ int opsize = 4;
2907+ char *opname = ".yikes!";
2908+ sb acc;
2909+ sb_new (&acc);
2910+
2911+ if (!size)
2912+ {
2913+ idx = get_opsize (idx, in, &opsize);
2914+ }
2915+ else
2916+ {
2917+ opsize = size;
2918+ }
2919+ switch (opsize)
2920+ {
2921+ case 4:
2922+ opname = ".long";
2923+ break;
2924+ case 2:
2925+ opname = ".short";
2926+ break;
2927+ case 1:
2928+ opname = ".byte";
2929+ break;
2930+ }
2931+
2932+ fprintf (outfile, "%s\t", opname);
2933+
2934+ idx = sb_skip_white (idx, in);
2935+
2936+ if (alternate
2937+ && idx < in->len
2938+ && in->ptr[idx] == '"')
2939+ {
2940+ int i;
2941+ idx = getstring (idx, in, &acc);
2942+ for (i = 0; i < acc.len; i++)
2943+ {
2944+ if (i)
2945+ fprintf (outfile, ",");
2946+ fprintf (outfile, "%d", acc.ptr[i]);
2947+ }
2948+ }
2949+ else
2950+ {
2951+ while (!eol (idx, in))
2952+ {
2953+ exp_t e;
2954+ idx = exp_parse (idx, in, &e);
2955+ exp_string (&e, &acc);
2956+ sb_add_char (&acc, 0);
2957+ fprintf (outfile, "%s", acc.ptr);
2958+ if (idx < in->len && in->ptr[idx] == ',')
2959+ {
2960+ fprintf (outfile, ",");
2961+ idx++;
2962+ }
2963+ }
2964+ }
2965+ sb_kill (&acc);
2966+ sb_print_at (outfile, idx, in);
2967+ fprintf (outfile, "\n");
2968+}
2969+
2970+/* .datab [.b|.w|.l] <repeat>,<fill> */
2971+
2972+static void
2973+do_datab (idx, in)
2974+ int idx;
2975+ sb *in;
2976+{
2977+ int opsize;
2978+ int repeat;
2979+ int fill;
2980+
2981+ idx = get_opsize (idx, in, &opsize);
2982+
2983+ idx = exp_get_abs (_("datab repeat must be constant.\n"), idx, in, &repeat);
2984+ idx = sb_skip_comma (idx, in);
2985+ idx = exp_get_abs (_("datab data must be absolute.\n"), idx, in, &fill);
2986+
2987+ fprintf (outfile, ".fill\t%d,%d,%d\n", repeat, opsize, fill);
2988+}
2989+
2990+/* .align <size> */
2991+
2992+static void
2993+do_align (idx, in)
2994+ int idx;
2995+ sb *in;
2996+{
2997+ int al, have_fill, fill;
2998+
2999+ idx = exp_get_abs (_("align needs absolute expression.\n"), idx, in, &al);
3000+ idx = sb_skip_white (idx, in);
3001+ have_fill = 0;
3002+ fill = 0;
3003+ if (! eol (idx, in))
3004+ {
3005+ idx = sb_skip_comma (idx, in);
3006+ idx = exp_get_abs (_(".align needs absolute fill value.\n"), idx, in,
3007+ &fill);
3008+ have_fill = 1;
3009+ }
3010+
3011+ fprintf (outfile, ".align %d", al);
3012+ if (have_fill)
3013+ fprintf (outfile, ",%d", fill);
3014+ fprintf (outfile, "\n");
3015+}
3016+
3017+/* .res[.b|.w|.l] <size> */
3018+
3019+static void
3020+do_res (idx, in, type)
3021+ int idx;
3022+ sb *in;
3023+ int type;
3024+{
3025+ int size = 4;
3026+ int count = 0;
3027+
3028+ idx = get_opsize (idx, in, &size);
3029+ while (!eol (idx, in))
3030+ {
3031+ idx = sb_skip_white (idx, in);
3032+ if (in->ptr[idx] == ',')
3033+ idx++;
3034+ idx = exp_get_abs (_("res needs absolute expression for fill count.\n"), idx, in, &count);
3035+
3036+ if (type == 'c' || type == 'z')
3037+ count++;
3038+
3039+ fprintf (outfile, ".space %d\n", count * size);
3040+ }
3041+}
3042+
3043+/* .export */
3044+
3045+static void
3046+do_export (in)
3047+ sb *in;
3048+{
3049+ fprintf (outfile, ".global %s\n", sb_name (in));
3050+}
3051+
3052+/* .print [list] [nolist] */
3053+
3054+static void
3055+do_print (idx, in)
3056+ int idx;
3057+ sb *in;
3058+{
3059+ idx = sb_skip_white (idx, in);
3060+ while (idx < in->len)
3061+ {
3062+ if (strncasecmp (in->ptr + idx, "LIST", 4) == 0)
3063+ {
3064+ fprintf (outfile, ".list\n");
3065+ idx += 4;
3066+ }
3067+ else if (strncasecmp (in->ptr + idx, "NOLIST", 6) == 0)
3068+ {
3069+ fprintf (outfile, ".nolist\n");
3070+ idx += 6;
3071+ }
3072+ idx++;
3073+ }
3074+}
3075+
3076+/* .head */
3077+
3078+static void
3079+do_heading (idx, in)
3080+ int idx;
3081+ sb *in;
3082+{
3083+ sb head;
3084+ sb_new (&head);
3085+ idx = getstring (idx, in, &head);
3086+ fprintf (outfile, ".title \"%s\"\n", sb_name (&head));
3087+ sb_kill (&head);
3088+}
3089+
3090+/* .page */
3091+
3092+static void
3093+do_page ()
3094+{
3095+ fprintf (outfile, ".eject\n");
3096+}
3097+
3098+/* .form [lin=<value>] [col=<value>] */
3099+
3100+static void
3101+do_form (idx, in)
3102+ int idx;
3103+ sb *in;
3104+{
3105+ int lines = 60;
3106+ int columns = 132;
3107+ idx = sb_skip_white (idx, in);
3108+
3109+ while (idx < in->len)
3110+ {
3111+
3112+ if (strncasecmp (in->ptr + idx, "LIN=", 4) == 0)
3113+ {
3114+ idx += 4;
3115+ idx = exp_get_abs (_("form LIN= needs absolute expresssion.\n"), idx, in, &lines);
3116+ }
3117+
3118+ if (strncasecmp (in->ptr + idx, _("COL="), 4) == 0)
3119+ {
3120+ idx += 4;
3121+ idx = exp_get_abs (_("form COL= needs absolute expresssion.\n"), idx, in, &columns);
3122+ }
3123+
3124+ idx++;
3125+ }
3126+ fprintf (outfile, ".psize %d,%d\n", lines, columns);
3127+
3128+}
3129+
3130+/* Fetch string from the input stream,
3131+ rules:
3132+ 'Bxyx<whitespace> -> return 'Bxyza
3133+ %<char> -> return string of decimal value of x
3134+ "<string>" -> return string
3135+ xyx<whitespace> -> return xyz
3136+*/
3137+
3138+static int
3139+get_any_string (idx, in, out, expand, pretend_quoted)
3140+ int idx;
3141+ sb *in;
3142+ sb *out;
3143+ int expand;
3144+ int pretend_quoted;
3145+{
3146+ sb_reset (out);
3147+ idx = sb_skip_white (idx, in);
3148+
3149+ if (idx < in->len)
3150+ {
3151+ if (in->len > 2 && in->ptr[idx + 1] == '\'' && ISBASE (in->ptr[idx]))
3152+ {
3153+ while (!ISSEP (in->ptr[idx]))
3154+ sb_add_char (out, in->ptr[idx++]);
3155+ }
3156+ else if (in->ptr[idx] == '%'
3157+ && alternate
3158+ && expand)
3159+ {
3160+ int val;
3161+ char buf[20];
3162+ /* Turns the next expression into a string. */
3163+ /* xgettext: no-c-format */
3164+ idx = exp_get_abs (_("% operator needs absolute expression"),
3165+ idx + 1,
3166+ in,
3167+ &val);
3168+ sprintf (buf, "%d", val);
3169+ sb_add_string (out, buf);
3170+ }
3171+ else if (in->ptr[idx] == '"'
3172+ || in->ptr[idx] == '<'
3173+ || (alternate && in->ptr[idx] == '\''))
3174+ {
3175+ if (alternate && expand)
3176+ {
3177+ /* Keep the quotes. */
3178+ sb_add_char (out, '\"');
3179+
3180+ idx = getstring (idx, in, out);
3181+ sb_add_char (out, '\"');
3182+
3183+ }
3184+ else
3185+ {
3186+ idx = getstring (idx, in, out);
3187+ }
3188+ }
3189+ else
3190+ {
3191+ while (idx < in->len
3192+ && (in->ptr[idx] == '"'
3193+ || in->ptr[idx] == '\''
3194+ || pretend_quoted
3195+ || !ISSEP (in->ptr[idx])))
3196+ {
3197+ if (in->ptr[idx] == '"'
3198+ || in->ptr[idx] == '\'')
3199+ {
3200+ char tchar = in->ptr[idx];
3201+ sb_add_char (out, in->ptr[idx++]);
3202+ while (idx < in->len
3203+ && in->ptr[idx] != tchar)
3204+ sb_add_char (out, in->ptr[idx++]);
3205+ if (idx == in->len)
3206+ return idx;
3207+ }
3208+ sb_add_char (out, in->ptr[idx++]);
3209+ }
3210+ }
3211+ }
3212+
3213+ return idx;
3214+}
3215+
3216+/* Skip along sb in starting at idx, suck off whitespace a ( and more
3217+ whitespace. Return the idx of the next char. */
3218+
3219+static int
3220+skip_openp (idx, in)
3221+ int idx;
3222+ sb *in;
3223+{
3224+ idx = sb_skip_white (idx, in);
3225+ if (in->ptr[idx] != '(')
3226+ ERROR ((stderr, _("misplaced ( .\n")));
3227+ idx = sb_skip_white (idx + 1, in);
3228+ return idx;
3229+}
3230+
3231+/* Skip along sb in starting at idx, suck off whitespace a ) and more
3232+ whitespace. Return the idx of the next char. */
3233+
3234+static int
3235+skip_closep (idx, in)
3236+ int idx;
3237+ sb *in;
3238+{
3239+ idx = sb_skip_white (idx, in);
3240+ if (in->ptr[idx] != ')')
3241+ ERROR ((stderr, _("misplaced ).\n")));
3242+ idx = sb_skip_white (idx + 1, in);
3243+ return idx;
3244+}
3245+
3246+/* .len */
3247+
3248+static int
3249+dolen (idx, in, out)
3250+ int idx;
3251+ sb *in;
3252+ sb *out;
3253+{
3254+
3255+ sb stringout;
3256+ char buffer[10];
3257+
3258+ sb_new (&stringout);
3259+ idx = skip_openp (idx, in);
3260+ idx = get_and_process (idx, in, &stringout);
3261+ idx = skip_closep (idx, in);
3262+ sprintf (buffer, "%d", stringout.len);
3263+ sb_add_string (out, buffer);
3264+
3265+ sb_kill (&stringout);
3266+ return idx;
3267+}
3268+
3269+/* .instr */
3270+
3271+static int
3272+doinstr (idx, in, out)
3273+ int idx;
3274+ sb *in;
3275+ sb *out;
3276+{
3277+ sb string;
3278+ sb search;
3279+ int i;
3280+ int start;
3281+ int res;
3282+ char buffer[10];
3283+
3284+ sb_new (&string);
3285+ sb_new (&search);
3286+ idx = skip_openp (idx, in);
3287+ idx = get_and_process (idx, in, &string);
3288+ idx = sb_skip_comma (idx, in);
3289+ idx = get_and_process (idx, in, &search);
3290+ idx = sb_skip_comma (idx, in);
3291+ if (ISDIGIT (in->ptr[idx]))
3292+ {
3293+ idx = exp_get_abs (_(".instr needs absolute expresson.\n"), idx, in, &start);
3294+ }
3295+ else
3296+ {
3297+ start = 0;
3298+ }
3299+ idx = skip_closep (idx, in);
3300+ res = -1;
3301+ for (i = start; i < string.len; i++)
3302+ {
3303+ if (strncmp (string.ptr + i, search.ptr, search.len) == 0)
3304+ {
3305+ res = i;
3306+ break;
3307+ }
3308+ }
3309+ sprintf (buffer, "%d", res);
3310+ sb_add_string (out, buffer);
3311+ sb_kill (&string);
3312+ sb_kill (&search);
3313+ return idx;
3314+}
3315+
3316+static int
3317+dosubstr (idx, in, out)
3318+ int idx;
3319+ sb *in;
3320+ sb *out;
3321+{
3322+ sb string;
3323+ int pos;
3324+ int len;
3325+ sb_new (&string);
3326+
3327+ idx = skip_openp (idx, in);
3328+ idx = get_and_process (idx, in, &string);
3329+ idx = sb_skip_comma (idx, in);
3330+ idx = exp_get_abs (_("need absolute position.\n"), idx, in, &pos);
3331+ idx = sb_skip_comma (idx, in);
3332+ idx = exp_get_abs (_("need absolute length.\n"), idx, in, &len);
3333+ idx = skip_closep (idx, in);
3334+
3335+ if (len < 0 || pos < 0 ||
3336+ pos > string.len
3337+ || pos + len > string.len)
3338+ {
3339+ sb_add_string (out, " ");
3340+ }
3341+ else
3342+ {
3343+ sb_add_char (out, '"');
3344+ while (len > 0)
3345+ {
3346+ sb_add_char (out, string.ptr[pos++]);
3347+ len--;
3348+ }
3349+ sb_add_char (out, '"');
3350+ }
3351+ sb_kill (&string);
3352+ return idx;
3353+}
3354+
3355+/* Scan line, change tokens in the hash table to their replacements. */
3356+
3357+static void
3358+process_assigns (idx, in, buf)
3359+ int idx;
3360+ sb *in;
3361+ sb *buf;
3362+{
3363+ while (idx < in->len)
3364+ {
3365+ hash_entry *ptr;
3366+ if (in->ptr[idx] == '\\'
3367+ && idx + 1 < in->len
3368+ && in->ptr[idx + 1] == '(')
3369+ {
3370+ do
3371+ {
3372+ sb_add_char (buf, in->ptr[idx]);
3373+ idx++;
3374+ }
3375+ while (idx < in->len && in->ptr[idx - 1] != ')');
3376+ }
3377+ else if (in->ptr[idx] == '\\'
3378+ && idx + 1 < in->len
3379+ && in->ptr[idx + 1] == '&')
3380+ {
3381+ idx = condass_lookup_name (in, idx + 2, buf, 1);
3382+ }
3383+ else if (in->ptr[idx] == '\\'
3384+ && idx + 1 < in->len
3385+ && in->ptr[idx + 1] == '$')
3386+ {
3387+ idx = condass_lookup_name (in, idx + 2, buf, 0);
3388+ }
3389+ else if (idx + 3 < in->len
3390+ && in->ptr[idx] == '.'
3391+ && TOUPPER (in->ptr[idx + 1]) == 'L'
3392+ && TOUPPER (in->ptr[idx + 2]) == 'E'
3393+ && TOUPPER (in->ptr[idx + 3]) == 'N')
3394+ idx = dolen (idx + 4, in, buf);
3395+ else if (idx + 6 < in->len
3396+ && in->ptr[idx] == '.'
3397+ && TOUPPER (in->ptr[idx + 1]) == 'I'
3398+ && TOUPPER (in->ptr[idx + 2]) == 'N'
3399+ && TOUPPER (in->ptr[idx + 3]) == 'S'
3400+ && TOUPPER (in->ptr[idx + 4]) == 'T'
3401+ && TOUPPER (in->ptr[idx + 5]) == 'R')
3402+ idx = doinstr (idx + 6, in, buf);
3403+ else if (idx + 7 < in->len
3404+ && in->ptr[idx] == '.'
3405+ && TOUPPER (in->ptr[idx + 1]) == 'S'
3406+ && TOUPPER (in->ptr[idx + 2]) == 'U'
3407+ && TOUPPER (in->ptr[idx + 3]) == 'B'
3408+ && TOUPPER (in->ptr[idx + 4]) == 'S'
3409+ && TOUPPER (in->ptr[idx + 5]) == 'T'
3410+ && TOUPPER (in->ptr[idx + 6]) == 'R')
3411+ idx = dosubstr (idx + 7, in, buf);
3412+ else if (ISFIRSTCHAR (in->ptr[idx]))
3413+ {
3414+ /* May be a simple name subsitution, see if we have a word. */
3415+ sb acc;
3416+ int cur = idx + 1;
3417+ while (cur < in->len
3418+ && (ISNEXTCHAR (in->ptr[cur])))
3419+ cur++;
3420+
3421+ sb_new (&acc);
3422+ sb_add_buffer (&acc, in->ptr + idx, cur - idx);
3423+ ptr = hash_lookup (&assign_hash_table, &acc);
3424+ if (ptr)
3425+ {
3426+ /* Found a definition for it. */
3427+ sb_add_sb (buf, &ptr->value.s);
3428+ }
3429+ else
3430+ {
3431+ /* No definition, just copy the word. */
3432+ sb_add_sb (buf, &acc);
3433+ }
3434+ sb_kill (&acc);
3435+ idx = cur;
3436+ }
3437+ else
3438+ {
3439+ sb_add_char (buf, in->ptr[idx++]);
3440+ }
3441+ }
3442+}
3443+
3444+static int
3445+get_and_process (idx, in, out)
3446+ int idx;
3447+ sb *in;
3448+ sb *out;
3449+{
3450+ sb t;
3451+ sb_new (&t);
3452+ idx = get_any_string (idx, in, &t, 1, 0);
3453+ process_assigns (0, &t, out);
3454+ sb_kill (&t);
3455+ return idx;
3456+}
3457+
3458+static void
3459+process_file ()
3460+{
3461+ sb line;
3462+ sb t1, t2;
3463+ sb acc;
3464+ sb label_in;
3465+ int more;
3466+
3467+ sb_new (&line);
3468+ sb_new (&t1);
3469+ sb_new (&t2);
3470+ sb_new (&acc);
3471+ sb_new (&label_in);
3472+ sb_reset (&line);
3473+ more = get_line (&line);
3474+ while (more)
3475+ {
3476+ /* Find any label and pseudo op that we're intested in. */
3477+ int l;
3478+ if (line.len == 0)
3479+ {
3480+ if (condass_on ())
3481+ fprintf (outfile, "\n");
3482+ }
3483+ else if (mri
3484+ && (line.ptr[0] == '*'
3485+ || line.ptr[0] == '!'))
3486+ {
3487+ /* MRI line comment. */
3488+ fprintf (outfile, "%s", sb_name (&line));
3489+ }
3490+ else
3491+ {
3492+ l = grab_label (&line, &label_in);
3493+ sb_reset (&label);
3494+
3495+ if (line.ptr[l] == ':')
3496+ l++;
3497+ while (ISWHITE (line.ptr[l]) && l < line.len)
3498+ l++;
3499+
3500+ if (label_in.len)
3501+ {
3502+ int do_assigns;
3503+
3504+ /* Munge the label, unless this is EQU or ASSIGN. */
3505+ do_assigns = 1;
3506+ if (l < line.len
3507+ && (line.ptr[l] == '.' || alternate || mri))
3508+ {
3509+ int lx = l;
3510+
3511+ if (line.ptr[lx] == '.')
3512+ ++lx;
3513+ if (lx + 3 <= line.len
3514+ && strncasecmp ("EQU", line.ptr + lx, 3) == 0
3515+ && (lx + 3 == line.len
3516+ || ! ISFIRSTCHAR (line.ptr[lx + 3])))
3517+ do_assigns = 0;
3518+ else if (lx + 6 <= line.len
3519+ && strncasecmp ("ASSIGN", line.ptr + lx, 6) == 0
3520+ && (lx + 6 == line.len
3521+ || ! ISFIRSTCHAR (line.ptr[lx + 6])))
3522+ do_assigns = 0;
3523+ }
3524+
3525+ if (do_assigns)
3526+ process_assigns (0, &label_in, &label);
3527+ else
3528+ sb_add_sb (&label, &label_in);
3529+ }
3530+
3531+ if (l < line.len)
3532+ {
3533+ if (process_pseudo_op (l, &line, &acc))
3534+ {
3535+
3536+ }
3537+ else if (condass_on ())
3538+ {
3539+ if (macro_op (l, &line))
3540+ {
3541+
3542+ }
3543+ else
3544+ {
3545+ {
3546+ if (label.len)
3547+ {
3548+ fprintf (outfile, "%s:\t", sb_name (&label));
3549+ }
3550+ else
3551+ fprintf (outfile, "\t");
3552+ sb_reset (&t1);
3553+ process_assigns (l, &line, &t1);
3554+ sb_reset (&t2);
3555+ change_base (0, &t1, &t2);
3556+ fprintf (outfile, "%s\n", sb_name (&t2));
3557+ }
3558+ }
3559+ }
3560+ }
3561+ else
3562+ {
3563+ /* Only a label on this line. */
3564+ if (label.len && condass_on ())
3565+ {
3566+ fprintf (outfile, "%s:\n", sb_name (&label));
3567+ }
3568+ }
3569+ }
3570+
3571+ if (had_end)
3572+ break;
3573+ sb_reset (&line);
3574+ more = get_line (&line);
3575+ }
3576+
3577+ if (!had_end && !mri)
3578+ WARNING ((stderr, _("END missing from end of file.\n")));
3579+}
3580+
3581+static void
3582+free_old_entry (ptr)
3583+ hash_entry *ptr;
3584+{
3585+ if (ptr)
3586+ {
3587+ if (ptr->type == hash_string)
3588+ sb_kill (&ptr->value.s);
3589+ }
3590+}
3591+
3592+/* name: .ASSIGNA <value> */
3593+
3594+static void
3595+do_assigna (idx, in)
3596+ int idx;
3597+ sb *in;
3598+{
3599+ sb tmp;
3600+ int val;
3601+ sb_new (&tmp);
3602+
3603+ process_assigns (idx, in, &tmp);
3604+ idx = exp_get_abs (_(".ASSIGNA needs constant expression argument.\n"), 0, &tmp, &val);
3605+
3606+ if (!label.len)
3607+ {
3608+ ERROR ((stderr, _(".ASSIGNA without label.\n")));
3609+ }
3610+ else
3611+ {
3612+ hash_entry *ptr = hash_create (&vars, &label);
3613+ free_old_entry (ptr);
3614+ ptr->type = hash_integer;
3615+ ptr->value.i = val;
3616+ }
3617+ sb_kill (&tmp);
3618+}
3619+
3620+/* name: .ASSIGNC <string> */
3621+
3622+static void
3623+do_assignc (idx, in)
3624+ int idx;
3625+ sb *in;
3626+{
3627+ sb acc;
3628+ sb_new (&acc);
3629+ idx = getstring (idx, in, &acc);
3630+
3631+ if (!label.len)
3632+ {
3633+ ERROR ((stderr, _(".ASSIGNS without label.\n")));
3634+ }
3635+ else
3636+ {
3637+ hash_entry *ptr = hash_create (&vars, &label);
3638+ free_old_entry (ptr);
3639+ ptr->type = hash_string;
3640+ sb_new (&ptr->value.s);
3641+ sb_add_sb (&ptr->value.s, &acc);
3642+ }
3643+ sb_kill (&acc);
3644+}
3645+
3646+/* name: .REG (reg) */
3647+
3648+static void
3649+do_reg (idx, in)
3650+ int idx;
3651+ sb *in;
3652+{
3653+ /* Remove reg stuff from inside parens. */
3654+ sb what;
3655+ if (!mri)
3656+ idx = skip_openp (idx, in);
3657+ else
3658+ idx = sb_skip_white (idx, in);
3659+ sb_new (&what);
3660+ while (idx < in->len
3661+ && (mri
3662+ ? ! eol (idx, in)
3663+ : in->ptr[idx] != ')'))
3664+ {
3665+ sb_add_char (&what, in->ptr[idx]);
3666+ idx++;
3667+ }
3668+ hash_add_to_string_table (&assign_hash_table, &label, &what, 1);
3669+ sb_kill (&what);
3670+}
3671+
3672+static int
3673+condass_lookup_name (inbuf, idx, out, warn)
3674+ sb *inbuf;
3675+ int idx;
3676+ sb *out;
3677+ int warn;
3678+{
3679+ hash_entry *ptr;
3680+ sb condass_acc;
3681+ sb_new (&condass_acc);
3682+
3683+ while (idx < inbuf->len
3684+ && ISNEXTCHAR (inbuf->ptr[idx]))
3685+ {
3686+ sb_add_char (&condass_acc, inbuf->ptr[idx++]);
3687+ }
3688+
3689+ if (inbuf->ptr[idx] == '\'')
3690+ idx++;
3691+ ptr = hash_lookup (&vars, &condass_acc);
3692+
3693+ if (!ptr)
3694+ {
3695+ if (warn)
3696+ {
3697+ WARNING ((stderr, _("Can't find preprocessor variable %s.\n"), sb_name (&condass_acc)));
3698+ }
3699+ else
3700+ {
3701+ sb_add_string (out, "0");
3702+ }
3703+ }
3704+ else
3705+ {
3706+ if (ptr->type == hash_integer)
3707+ {
3708+ char buffer[30];
3709+ sprintf (buffer, "%d", ptr->value.i);
3710+ sb_add_string (out, buffer);
3711+ }
3712+ else
3713+ {
3714+ sb_add_sb (out, &ptr->value.s);
3715+ }
3716+ }
3717+ sb_kill (&condass_acc);
3718+ return idx;
3719+}
3720+
3721+#define EQ 1
3722+#define NE 2
3723+#define GE 3
3724+#define LT 4
3725+#define LE 5
3726+#define GT 6
3727+#define NEVER 7
3728+
3729+static int
3730+whatcond (idx, in, val)
3731+ int idx;
3732+ sb *in;
3733+ int *val;
3734+{
3735+ int cond;
3736+
3737+ idx = sb_skip_white (idx, in);
3738+ cond = NEVER;
3739+ if (idx + 1 < in->len)
3740+ {
3741+ char *p;
3742+ char a, b;
3743+
3744+ p = in->ptr + idx;
3745+ a = TOUPPER (p[0]);
3746+ b = TOUPPER (p[1]);
3747+ if (a == 'E' && b == 'Q')
3748+ cond = EQ;
3749+ else if (a == 'N' && b == 'E')
3750+ cond = NE;
3751+ else if (a == 'L' && b == 'T')
3752+ cond = LT;
3753+ else if (a == 'L' && b == 'E')
3754+ cond = LE;
3755+ else if (a == 'G' && b == 'T')
3756+ cond = GT;
3757+ else if (a == 'G' && b == 'E')
3758+ cond = GE;
3759+ }
3760+ if (cond == NEVER)
3761+ {
3762+ ERROR ((stderr, _("Comparison operator must be one of EQ, NE, LT, LE, GT or GE.\n")));
3763+ cond = NEVER;
3764+ }
3765+ idx = sb_skip_white (idx + 2, in);
3766+ *val = cond;
3767+ return idx;
3768+}
3769+
3770+static int
3771+istrue (idx, in)
3772+ int idx;
3773+ sb *in;
3774+{
3775+ int res;
3776+ sb acc_a;
3777+ sb cond;
3778+ sb acc_b;
3779+ sb_new (&acc_a);
3780+ sb_new (&cond);
3781+ sb_new (&acc_b);
3782+ idx = sb_skip_white (idx, in);
3783+
3784+ if (in->ptr[idx] == '"')
3785+ {
3786+ int cond;
3787+ int same;
3788+ /* This is a string comparision. */
3789+ idx = getstring (idx, in, &acc_a);
3790+ idx = whatcond (idx, in, &cond);
3791+ idx = getstring (idx, in, &acc_b);
3792+ same = acc_a.len == acc_b.len
3793+ && (strncmp (acc_a.ptr, acc_b.ptr, acc_a.len) == 0);
3794+
3795+ if (cond != EQ && cond != NE)
3796+ {
3797+ ERROR ((stderr, _("Comparison operator for strings must be EQ or NE\n")));
3798+ res = 0;
3799+ }
3800+ else
3801+ res = (cond != EQ) ^ same;
3802+ }
3803+ else
3804+ /* This is a numeric expression. */
3805+ {
3806+ int vala;
3807+ int valb;
3808+ int cond;
3809+ idx = exp_get_abs (_("Conditional operator must have absolute operands.\n"), idx, in, &vala);
3810+ idx = whatcond (idx, in, &cond);
3811+ idx = sb_skip_white (idx, in);
3812+ if (in->ptr[idx] == '"')
3813+ {
3814+ WARNING ((stderr, _("String compared against expression.\n")));
3815+ res = 0;
3816+ }
3817+ else
3818+ {
3819+ idx = exp_get_abs (_("Conditional operator must have absolute operands.\n"), idx, in, &valb);
3820+ switch (cond)
3821+ {
3822+ default:
3823+ res = 42;
3824+ break;
3825+ case EQ:
3826+ res = vala == valb;
3827+ break;
3828+ case NE:
3829+ res = vala != valb;
3830+ break;
3831+ case LT:
3832+ res = vala < valb;
3833+ break;
3834+ case LE:
3835+ res = vala <= valb;
3836+ break;
3837+ case GT:
3838+ res = vala > valb;
3839+ break;
3840+ case GE:
3841+ res = vala >= valb;
3842+ break;
3843+ case NEVER:
3844+ res = 0;
3845+ break;
3846+ }
3847+ }
3848+ }
3849+
3850+ sb_kill (&acc_a);
3851+ sb_kill (&cond);
3852+ sb_kill (&acc_b);
3853+ return res;
3854+}
3855+
3856+/* .AIF */
3857+
3858+static void
3859+do_aif (idx, in)
3860+ int idx;
3861+ sb *in;
3862+{
3863+ if (ifi >= IFNESTING)
3864+ {
3865+ FATAL ((stderr, _("AIF nesting unreasonable.\n")));
3866+ }
3867+ ifi++;
3868+ ifstack[ifi].on = ifstack[ifi - 1].on ? istrue (idx, in) : 0;
3869+ ifstack[ifi].hadelse = 0;
3870+}
3871+
3872+/* .AELSE */
3873+
3874+static void
3875+do_aelse ()
3876+{
3877+ ifstack[ifi].on = ifstack[ifi - 1].on ? !ifstack[ifi].on : 0;
3878+ if (ifstack[ifi].hadelse)
3879+ {
3880+ ERROR ((stderr, _("Multiple AELSEs in AIF.\n")));
3881+ }
3882+ ifstack[ifi].hadelse = 1;
3883+}
3884+
3885+/* .AENDI */
3886+
3887+static void
3888+do_aendi ()
3889+{
3890+ if (ifi != 0)
3891+ {
3892+ ifi--;
3893+ }
3894+ else
3895+ {
3896+ ERROR ((stderr, _("AENDI without AIF.\n")));
3897+ }
3898+}
3899+
3900+static int
3901+condass_on ()
3902+{
3903+ return ifstack[ifi].on;
3904+}
3905+
3906+/* MRI IFEQ, IFNE, IFLT, IFLE, IFGE, IFGT. */
3907+
3908+static void
3909+do_if (idx, in, cond)
3910+ int idx;
3911+ sb *in;
3912+ int cond;
3913+{
3914+ int val;
3915+ int res;
3916+
3917+ if (ifi >= IFNESTING)
3918+ {
3919+ FATAL ((stderr, _("IF nesting unreasonable.\n")));
3920+ }
3921+
3922+ idx = exp_get_abs (_("Conditional operator must have absolute operands.\n"),
3923+ idx, in, &val);
3924+ switch (cond)
3925+ {
3926+ default:
3927+ case EQ: res = val == 0; break;
3928+ case NE: res = val != 0; break;
3929+ case LT: res = val < 0; break;
3930+ case LE: res = val <= 0; break;
3931+ case GE: res = val >= 0; break;
3932+ case GT: res = val > 0; break;
3933+ }
3934+
3935+ ifi++;
3936+ ifstack[ifi].on = ifstack[ifi - 1].on ? res : 0;
3937+ ifstack[ifi].hadelse = 0;
3938+}
3939+
3940+/* Get a string for the MRI IFC or IFNC pseudo-ops. */
3941+
3942+static int
3943+get_mri_string (idx, in, val, terminator)
3944+ int idx;
3945+ sb *in;
3946+ sb *val;
3947+ int terminator;
3948+{
3949+ idx = sb_skip_white (idx, in);
3950+
3951+ if (idx < in->len
3952+ && in->ptr[idx] == '\'')
3953+ {
3954+ sb_add_char (val, '\'');
3955+ for (++idx; idx < in->len; ++idx)
3956+ {
3957+ sb_add_char (val, in->ptr[idx]);
3958+ if (in->ptr[idx] == '\'')
3959+ {
3960+ ++idx;
3961+ if (idx >= in->len
3962+ || in->ptr[idx] != '\'')
3963+ break;
3964+ }
3965+ }
3966+ idx = sb_skip_white (idx, in);
3967+ }
3968+ else
3969+ {
3970+ int i;
3971+
3972+ while (idx < in->len
3973+ && in->ptr[idx] != terminator)
3974+ {
3975+ sb_add_char (val, in->ptr[idx]);
3976+ ++idx;
3977+ }
3978+ i = val->len - 1;
3979+ while (i >= 0 && ISWHITE (val->ptr[i]))
3980+ --i;
3981+ val->len = i + 1;
3982+ }
3983+
3984+ return idx;
3985+}
3986+
3987+/* MRI IFC, IFNC */
3988+
3989+static void
3990+do_ifc (idx, in, ifnc)
3991+ int idx;
3992+ sb *in;
3993+ int ifnc;
3994+{
3995+ sb first;
3996+ sb second;
3997+ int res;
3998+
3999+ if (ifi >= IFNESTING)
4000+ {
4001+ FATAL ((stderr, _("IF nesting unreasonable.\n")));
4002+ }
4003+
4004+ sb_new (&first);
4005+ sb_new (&second);
4006+
4007+ idx = get_mri_string (idx, in, &first, ',');
4008+
4009+ if (idx >= in->len || in->ptr[idx] != ',')
4010+ {
4011+ ERROR ((stderr, _("Bad format for IF or IFNC.\n")));
4012+ return;
4013+ }
4014+
4015+ idx = get_mri_string (idx + 1, in, &second, ';');
4016+
4017+ res = (first.len == second.len
4018+ && strncmp (first.ptr, second.ptr, first.len) == 0);
4019+ res ^= ifnc;
4020+
4021+ ifi++;
4022+ ifstack[ifi].on = ifstack[ifi - 1].on ? res : 0;
4023+ ifstack[ifi].hadelse = 0;
4024+}
4025+
4026+/* .ENDR */
4027+
4028+static void
4029+do_aendr ()
4030+{
4031+ if (!mri)
4032+ ERROR ((stderr, _("AENDR without a AREPEAT.\n")));
4033+ else
4034+ ERROR ((stderr, _("ENDR without a REPT.\n")));
4035+}
4036+
4037+/* .AWHILE */
4038+
4039+static void
4040+do_awhile (idx, in)
4041+ int idx;
4042+ sb *in;
4043+{
4044+ int line = linecount ();
4045+ sb exp;
4046+ sb sub;
4047+ int doit;
4048+
4049+ sb_new (&sub);
4050+ sb_new (&exp);
4051+
4052+ process_assigns (idx, in, &exp);
4053+ doit = istrue (0, &exp);
4054+
4055+ if (! buffer_and_nest ("AWHILE", "AENDW", &sub, get_line))
4056+ FATAL ((stderr, _("AWHILE without a AENDW at %d.\n"), line - 1));
4057+
4058+ /* Turn
4059+ .AWHILE exp
4060+ foo
4061+ .AENDW
4062+ into
4063+ foo
4064+ .AWHILE exp
4065+ foo
4066+ .ENDW
4067+ */
4068+
4069+ if (doit)
4070+ {
4071+ int index = include_next_index ();
4072+
4073+ sb copy;
4074+ sb_new (&copy);
4075+ sb_add_sb (&copy, &sub);
4076+ sb_add_sb (&copy, in);
4077+ sb_add_string (&copy, "\n");
4078+ sb_add_sb (&copy, &sub);
4079+ sb_add_string (&copy, "\t.AENDW\n");
4080+ /* Push another WHILE. */
4081+ include_buf (&exp, &copy, include_while, index);
4082+ sb_kill (&copy);
4083+ }
4084+ sb_kill (&exp);
4085+ sb_kill (&sub);
4086+}
4087+
4088+/* .AENDW */
4089+
4090+static void
4091+do_aendw ()
4092+{
4093+ ERROR ((stderr, _("AENDW without a AENDW.\n")));
4094+}
4095+
4096+/* .EXITM
4097+
4098+ Pop things off the include stack until the type and index changes. */
4099+
4100+static void
4101+do_exitm ()
4102+{
4103+ include_type type = sp->type;
4104+ if (type == include_repeat
4105+ || type == include_while
4106+ || type == include_macro)
4107+ {
4108+ int index = sp->index;
4109+ include_pop ();
4110+ while (sp->index == index
4111+ && sp->type == type)
4112+ {
4113+ include_pop ();
4114+ }
4115+ }
4116+}
4117+
4118+/* .AREPEAT */
4119+
4120+static void
4121+do_arepeat (idx, in)
4122+ int idx;
4123+ sb *in;
4124+{
4125+ int line = linecount ();
4126+ sb exp; /* Buffer with expression in it. */
4127+ sb copy; /* Expanded repeat block. */
4128+ sb sub; /* Contents of AREPEAT. */
4129+ int rc;
4130+ int ret;
4131+ char buffer[30];
4132+
4133+ sb_new (&exp);
4134+ sb_new (&copy);
4135+ sb_new (&sub);
4136+ process_assigns (idx, in, &exp);
4137+ idx = exp_get_abs (_("AREPEAT must have absolute operand.\n"), 0, &exp, &rc);
4138+ if (!mri)
4139+ ret = buffer_and_nest ("AREPEAT", "AENDR", &sub, get_line);
4140+ else
4141+ ret = buffer_and_nest ("REPT", "ENDR", &sub, get_line);
4142+ if (! ret)
4143+ FATAL ((stderr, _("AREPEAT without a AENDR at %d.\n"), line - 1));
4144+ if (rc > 0)
4145+ {
4146+ /* Push back the text following the repeat, and another repeat block
4147+ so
4148+ .AREPEAT 20
4149+ foo
4150+ .AENDR
4151+ gets turned into
4152+ foo
4153+ .AREPEAT 19
4154+ foo
4155+ .AENDR
4156+ */
4157+ int index = include_next_index ();
4158+ sb_add_sb (&copy, &sub);
4159+ if (rc > 1)
4160+ {
4161+ if (!mri)
4162+ sprintf (buffer, "\t.AREPEAT %d\n", rc - 1);
4163+ else
4164+ sprintf (buffer, "\tREPT %d\n", rc - 1);
4165+ sb_add_string (&copy, buffer);
4166+ sb_add_sb (&copy, &sub);
4167+ if (!mri)
4168+ sb_add_string (&copy, " .AENDR\n");
4169+ else
4170+ sb_add_string (&copy, " ENDR\n");
4171+ }
4172+
4173+ include_buf (&exp, &copy, include_repeat, index);
4174+ }
4175+ sb_kill (&exp);
4176+ sb_kill (&sub);
4177+ sb_kill (&copy);
4178+}
4179+
4180+/* .ENDM */
4181+
4182+static void
4183+do_endm ()
4184+{
4185+ ERROR ((stderr, _(".ENDM without a matching .MACRO.\n")));
4186+}
4187+
4188+/* MRI IRP pseudo-op. */
4189+
4190+static void
4191+do_irp (idx, in, irpc)
4192+ int idx;
4193+ sb *in;
4194+ int irpc;
4195+{
4196+ const char *err;
4197+ sb out;
4198+
4199+ sb_new (&out);
4200+
4201+ err = expand_irp (irpc, idx, in, &out, get_line, comment_char);
4202+ if (err != NULL)
4203+ ERROR ((stderr, "%s\n", err));
4204+
4205+ fprintf (outfile, "%s", sb_terminate (&out));
4206+
4207+ sb_kill (&out);
4208+}
4209+
4210+/* Macro processing. */
4211+
4212+/* Parse off LOCAL n1, n2,... Invent a label name for it. */
4213+
4214+static void
4215+do_local (idx, line)
4216+ int idx ATTRIBUTE_UNUSED;
4217+ sb *line ATTRIBUTE_UNUSED;
4218+{
4219+ ERROR ((stderr, _("LOCAL outside of MACRO")));
4220+}
4221+
4222+static void
4223+do_macro (idx, in)
4224+ int idx;
4225+ sb *in;
4226+{
4227+ const char *err;
4228+ int line = linecount ();
4229+
1684d5ca 4230+ err = define_macro (idx, in, &label, get_line, "[gasp]", line, (const char **) NULL);
2859501d
JB
4231+ if (err != NULL)
4232+ ERROR ((stderr, _("macro at line %d: %s\n"), line - 1, err));
4233+}
4234+
4235+static int
4236+macro_op (idx, in)
4237+ int idx;
4238+ sb *in;
4239+{
4240+ const char *err;
4241+ sb out;
4242+ sb name;
4243+
4244+ if (! macro_defined)
4245+ return 0;
4246+
4247+ sb_terminate (in);
4248+ if (! check_macro (in->ptr + idx, &out, comment_char, &err, NULL))
4249+ return 0;
4250+
4251+ if (err != NULL)
4252+ ERROR ((stderr, "%s\n", err));
4253+
4254+ sb_new (&name);
4255+ sb_add_string (&name, _("macro expansion"));
4256+
4257+ include_buf (&name, &out, include_macro, include_next_index ());
4258+
4259+ sb_kill (&name);
4260+ sb_kill (&out);
4261+
4262+ return 1;
4263+}
4264+
4265+/* String handling. */
4266+
4267+static int
4268+getstring (idx, in, acc)
4269+ int idx;
4270+ sb *in;
4271+ sb *acc;
4272+{
4273+ idx = sb_skip_white (idx, in);
4274+
4275+ while (idx < in->len
4276+ && (in->ptr[idx] == '"'
4277+ || in->ptr[idx] == '<'
4278+ || (in->ptr[idx] == '\'' && alternate)))
4279+ {
4280+ if (in->ptr[idx] == '<')
4281+ {
4282+ if (alternate || mri)
4283+ {
4284+ int nest = 0;
4285+ idx++;
4286+ while ((in->ptr[idx] != '>' || nest)
4287+ && idx < in->len)
4288+ {
4289+ if (in->ptr[idx] == '!')
4290+ {
4291+ idx++;
4292+ sb_add_char (acc, in->ptr[idx++]);
4293+ }
4294+ else
4295+ {
4296+ if (in->ptr[idx] == '>')
4297+ nest--;
4298+ if (in->ptr[idx] == '<')
4299+ nest++;
4300+ sb_add_char (acc, in->ptr[idx++]);
4301+ }
4302+ }
4303+ idx++;
4304+ }
4305+ else
4306+ {
4307+ int code;
4308+ idx++;
4309+ idx = exp_get_abs (_("Character code in string must be absolute expression.\n"),
4310+ idx, in, &code);
4311+ sb_add_char (acc, code);
4312+
4313+ if (in->ptr[idx] != '>')
4314+ ERROR ((stderr, _("Missing > for character code.\n")));
4315+ idx++;
4316+ }
4317+ }
4318+ else if (in->ptr[idx] == '"' || in->ptr[idx] == '\'')
4319+ {
4320+ char tchar = in->ptr[idx];
4321+ idx++;
4322+ while (idx < in->len)
4323+ {
4324+ if (alternate && in->ptr[idx] == '!')
4325+ {
4326+ idx++;
4327+ sb_add_char (acc, in->ptr[idx++]);
4328+ }
4329+ else
4330+ {
4331+ if (in->ptr[idx] == tchar)
4332+ {
4333+ idx++;
4334+ if (idx >= in->len || in->ptr[idx] != tchar)
4335+ break;
4336+ }
4337+ sb_add_char (acc, in->ptr[idx]);
4338+ idx++;
4339+ }
4340+ }
4341+ }
4342+ }
4343+
4344+ return idx;
4345+}
4346+
4347+/* .SDATA[C|Z] <string> */
4348+
4349+static void
4350+do_sdata (idx, in, type)
4351+ int idx;
4352+ sb *in;
4353+ int type;
4354+{
4355+ int nc = 0;
4356+ int pidx = -1;
4357+ sb acc;
4358+ sb_new (&acc);
4359+ fprintf (outfile, ".byte\t");
4360+
4361+ while (!eol (idx, in))
4362+ {
4363+ int i;
4364+ sb_reset (&acc);
4365+ idx = sb_skip_white (idx, in);
4366+ while (!eol (idx, in))
4367+ {
4368+ pidx = idx = get_any_string (idx, in, &acc, 0, 1);
4369+ if (type == 'c')
4370+ {
4371+ if (acc.len > 255)
4372+ {
4373+ ERROR ((stderr, _("string for SDATAC longer than 255 characters (%d).\n"), acc.len));
4374+ }
4375+ fprintf (outfile, "%d", acc.len);
4376+ nc = 1;
4377+ }
4378+
4379+ for (i = 0; i < acc.len; i++)
4380+ {
4381+ if (nc)
4382+ {
4383+ fprintf (outfile, ",");
4384+ }
4385+ fprintf (outfile, "%d", acc.ptr[i]);
4386+ nc = 1;
4387+ }
4388+
4389+ if (type == 'z')
4390+ {
4391+ if (nc)
4392+ fprintf (outfile, ",");
4393+ fprintf (outfile, "0");
4394+ }
4395+ idx = sb_skip_comma (idx, in);
4396+ if (idx == pidx)
4397+ break;
4398+ }
4399+ if (!alternate && in->ptr[idx] != ',' && idx != in->len)
4400+ {
4401+ fprintf (outfile, "\n");
4402+ ERROR ((stderr, _("illegal character in SDATA line (0x%x).\n"),
4403+ in->ptr[idx]));
4404+ break;
4405+ }
4406+ idx++;
4407+ }
4408+ sb_kill (&acc);
4409+ fprintf (outfile, "\n");
4410+}
4411+
4412+/* .SDATAB <count> <string> */
4413+
4414+static void
4415+do_sdatab (idx, in)
4416+ int idx;
4417+ sb *in;
4418+{
4419+ int repeat;
4420+ int i;
4421+ sb acc;
4422+ sb_new (&acc);
4423+
4424+ idx = exp_get_abs (_("Must have absolute SDATAB repeat count.\n"), idx, in, &repeat);
4425+ if (repeat <= 0)
4426+ {
4427+ ERROR ((stderr, _("Must have positive SDATAB repeat count (%d).\n"), repeat));
4428+ repeat = 1;
4429+ }
4430+
4431+ idx = sb_skip_comma (idx, in);
4432+ idx = getstring (idx, in, &acc);
4433+
4434+ for (i = 0; i < repeat; i++)
4435+ {
4436+ if (i)
4437+ fprintf (outfile, "\t");
4438+ fprintf (outfile, ".byte\t");
4439+ sb_print (outfile, &acc);
4440+ fprintf (outfile, "\n");
4441+ }
4442+ sb_kill (&acc);
4443+
4444+}
4445+
4446+static int
4447+new_file (name)
4448+ const char *name;
4449+{
4450+ FILE *newone = fopen (name, "r");
4451+ if (!newone)
4452+ return 0;
4453+
4454+ if (isp == MAX_INCLUDES)
4455+ FATAL ((stderr, _("Unreasonable include depth (%ld).\n"), (long) isp));
4456+
4457+ sp++;
4458+ sp->handle = newone;
4459+
4460+ sb_new (&sp->name);
4461+ sb_add_string (&sp->name, name);
4462+
4463+ sp->linecount = 1;
4464+ sp->pushback_index = 0;
4465+ sp->type = include_file;
4466+ sp->index = 0;
4467+ sb_new (&sp->pushback);
4468+ return 1;
4469+}
4470+
4471+static void
4472+do_include (idx, in)
4473+ int idx;
4474+ sb *in;
4475+{
4476+ sb t;
4477+ sb cat;
4478+ include_path *includes;
4479+
4480+ sb_new (&t);
4481+ sb_new (&cat);
4482+
4483+ if (! mri)
4484+ idx = getstring (idx, in, &t);
4485+ else
4486+ {
4487+ idx = sb_skip_white (idx, in);
4488+ while (idx < in->len && ! ISWHITE (in->ptr[idx]))
4489+ {
4490+ sb_add_char (&t, in->ptr[idx]);
4491+ ++idx;
4492+ }
4493+ }
4494+
4495+ for (includes = paths_head; includes; includes = includes->next)
4496+ {
4497+ sb_reset (&cat);
4498+ sb_add_sb (&cat, &includes->path);
4499+ sb_add_char (&cat, '/');
4500+ sb_add_sb (&cat, &t);
4501+ if (new_file (sb_name (&cat)))
4502+ {
4503+ break;
4504+ }
4505+ }
4506+ if (!includes)
4507+ {
4508+ if (! new_file (sb_name (&t)))
4509+ FATAL ((stderr, _("Can't open include file `%s'.\n"), sb_name (&t)));
4510+ }
4511+ sb_kill (&cat);
4512+ sb_kill (&t);
4513+}
4514+
4515+static void
4516+include_pop ()
4517+{
4518+ if (sp != include_stack)
4519+ {
4520+ if (sp->handle)
4521+ fclose (sp->handle);
4522+ sp--;
4523+ }
4524+}
4525+
4526+/* Get the next character from the include stack. If there's anything
4527+ in the pushback buffer, take that first. If we're at eof, pop from
4528+ the stack and try again. Keep the linecount up to date. */
4529+
4530+static int
4531+get ()
4532+{
4533+ int r;
4534+
4535+ if (sp->pushback.len != sp->pushback_index)
4536+ {
4537+ r = (char) (sp->pushback.ptr[sp->pushback_index++]);
4538+ /* When they've all gone, reset the pointer. */
4539+ if (sp->pushback_index == sp->pushback.len)
4540+ {
4541+ sp->pushback.len = 0;
4542+ sp->pushback_index = 0;
4543+ }
4544+ }
4545+ else if (sp->handle)
4546+ {
4547+ r = getc (sp->handle);
4548+ }
4549+ else
4550+ r = EOF;
4551+
4552+ if (r == EOF && isp)
4553+ {
4554+ include_pop ();
4555+ r = get ();
4556+ while (r == EOF && isp)
4557+ {
4558+ include_pop ();
4559+ r = get ();
4560+ }
4561+ return r;
4562+ }
4563+ if (r == '\n')
4564+ {
4565+ sp->linecount++;
4566+ }
4567+
4568+ return r;
4569+}
4570+
4571+static int
4572+linecount ()
4573+{
4574+ return sp->linecount;
4575+}
4576+
4577+static int
4578+include_next_index ()
4579+{
4580+ static int index;
4581+ if (!unreasonable
4582+ && index > MAX_REASONABLE)
4583+ FATAL ((stderr, _("Unreasonable expansion (-u turns off check).\n")));
4584+ return ++index;
4585+}
4586+
4587+/* Initialize the chartype vector. */
4588+
4589+static void
4590+chartype_init ()
4591+{
4592+ int x;
4593+ for (x = 0; x < 256; x++)
4594+ {
4595+ if (ISALPHA (x) || x == '_' || x == '$')
4596+ chartype[x] |= FIRSTBIT;
4597+
4598+ if (mri && x == '.')
4599+ chartype[x] |= FIRSTBIT;
4600+
4601+ if (ISDIGIT (x) || ISALPHA (x) || x == '_' || x == '$')
4602+ chartype[x] |= NEXTBIT;
4603+
4604+ if (x == ' ' || x == '\t' || x == ',' || x == '"' || x == ';'
4605+ || x == '"' || x == '<' || x == '>' || x == ')' || x == '(')
4606+ chartype[x] |= SEPBIT;
4607+
4608+ if (x == 'b' || x == 'B'
4609+ || x == 'q' || x == 'Q'
4610+ || x == 'h' || x == 'H'
4611+ || x == 'd' || x == 'D')
4612+ chartype [x] |= BASEBIT;
4613+
4614+ if (x == ' ' || x == '\t')
4615+ chartype[x] |= WHITEBIT;
4616+
4617+ if (x == comment_char)
4618+ chartype[x] |= COMMENTBIT;
4619+ }
4620+}
4621+
4622+/* What to do with all the keywords. */
4623+#define PROCESS 0x1000 /* Run substitution over the line. */
4624+#define LAB 0x2000 /* Spit out the label. */
4625+
4626+#define K_EQU (PROCESS|1)
4627+#define K_ASSIGN (PROCESS|2)
4628+#define K_REG (PROCESS|3)
4629+#define K_ORG (PROCESS|4)
4630+#define K_RADIX (PROCESS|5)
4631+#define K_DATA (LAB|PROCESS|6)
4632+#define K_DATAB (LAB|PROCESS|7)
4633+#define K_SDATA (LAB|PROCESS|8)
4634+#define K_SDATAB (LAB|PROCESS|9)
4635+#define K_SDATAC (LAB|PROCESS|10)
4636+#define K_SDATAZ (LAB|PROCESS|11)
4637+#define K_RES (LAB|PROCESS|12)
4638+#define K_SRES (LAB|PROCESS|13)
4639+#define K_SRESC (LAB|PROCESS|14)
4640+#define K_SRESZ (LAB|PROCESS|15)
4641+#define K_EXPORT (LAB|PROCESS|16)
4642+#define K_GLOBAL (LAB|PROCESS|17)
4643+#define K_PRINT (LAB|PROCESS|19)
4644+#define K_FORM (LAB|PROCESS|20)
4645+#define K_HEADING (LAB|PROCESS|21)
4646+#define K_PAGE (LAB|PROCESS|22)
4647+#define K_IMPORT (LAB|PROCESS|23)
4648+#define K_PROGRAM (LAB|PROCESS|24)
4649+#define K_END (PROCESS|25)
4650+#define K_INCLUDE (PROCESS|26)
4651+#define K_IGNORED (PROCESS|27)
4652+#define K_ASSIGNA (PROCESS|28)
4653+#define K_ASSIGNC (29)
4654+#define K_AIF (PROCESS|30)
4655+#define K_AELSE (PROCESS|31)
4656+#define K_AENDI (PROCESS|32)
4657+#define K_AREPEAT (PROCESS|33)
4658+#define K_AENDR (PROCESS|34)
4659+#define K_AWHILE (35)
4660+#define K_AENDW (PROCESS|36)
4661+#define K_EXITM (37)
4662+#define K_MACRO (PROCESS|38)
4663+#define K_ENDM (39)
4664+#define K_ALIGN (PROCESS|LAB|40)
4665+#define K_ALTERNATE (41)
4666+#define K_DB (LAB|PROCESS|42)
4667+#define K_DW (LAB|PROCESS|43)
4668+#define K_DL (LAB|PROCESS|44)
4669+#define K_LOCAL (45)
4670+#define K_IFEQ (PROCESS|46)
4671+#define K_IFNE (PROCESS|47)
4672+#define K_IFLT (PROCESS|48)
4673+#define K_IFLE (PROCESS|49)
4674+#define K_IFGE (PROCESS|50)
4675+#define K_IFGT (PROCESS|51)
4676+#define K_IFC (PROCESS|52)
4677+#define K_IFNC (PROCESS|53)
4678+#define K_IRP (PROCESS|54)
4679+#define K_IRPC (PROCESS|55)
4680+
4681+struct keyword {
4682+ char *name;
4683+ int code;
4684+ int extra;
4685+};
4686+
4687+static struct keyword kinfo[] = {
4688+ { "EQU", K_EQU, 0 },
4689+ { "ALTERNATE", K_ALTERNATE, 0 },
4690+ { "ASSIGN", K_ASSIGN, 0 },
4691+ { "REG", K_REG, 0 },
4692+ { "ORG", K_ORG, 0 },
4693+ { "RADIX", K_RADIX, 0 },
4694+ { "DATA", K_DATA, 0 },
4695+ { "DB", K_DB, 0 },
4696+ { "DW", K_DW, 0 },
4697+ { "DL", K_DL, 0 },
4698+ { "DATAB", K_DATAB, 0 },
4699+ { "SDATA", K_SDATA, 0 },
4700+ { "SDATAB", K_SDATAB, 0 },
4701+ { "SDATAZ", K_SDATAZ, 0 },
4702+ { "SDATAC", K_SDATAC, 0 },
4703+ { "RES", K_RES, 0 },
4704+ { "SRES", K_SRES, 0 },
4705+ { "SRESC", K_SRESC, 0 },
4706+ { "SRESZ", K_SRESZ, 0 },
4707+ { "EXPORT", K_EXPORT, 0 },
4708+ { "GLOBAL", K_GLOBAL, 0 },
4709+ { "PRINT", K_PRINT, 0 },
4710+ { "FORM", K_FORM, 0 },
4711+ { "HEADING", K_HEADING, 0 },
4712+ { "PAGE", K_PAGE, 0 },
4713+ { "PROGRAM", K_IGNORED, 0 },
4714+ { "END", K_END, 0 },
4715+ { "INCLUDE", K_INCLUDE, 0 },
4716+ { "ASSIGNA", K_ASSIGNA, 0 },
4717+ { "ASSIGNC", K_ASSIGNC, 0 },
4718+ { "AIF", K_AIF, 0 },
4719+ { "AELSE", K_AELSE, 0 },
4720+ { "AENDI", K_AENDI, 0 },
4721+ { "AREPEAT", K_AREPEAT, 0 },
4722+ { "AENDR", K_AENDR, 0 },
4723+ { "EXITM", K_EXITM, 0 },
4724+ { "MACRO", K_MACRO, 0 },
4725+ { "ENDM", K_ENDM, 0 },
4726+ { "AWHILE", K_AWHILE, 0 },
4727+ { "ALIGN", K_ALIGN, 0 },
4728+ { "AENDW", K_AENDW, 0 },
4729+ { "ALTERNATE", K_ALTERNATE, 0 },
4730+ { "LOCAL", K_LOCAL, 0 },
4731+ { NULL, 0, 0 }
4732+};
4733+
4734+/* Although the conditional operators are handled by gas, we need to
4735+ handle them here as well, in case they are used in a recursive
4736+ macro to end the recursion. */
4737+
4738+static struct keyword mrikinfo[] = {
4739+ { "IFEQ", K_IFEQ, 0 },
4740+ { "IFNE", K_IFNE, 0 },
4741+ { "IFLT", K_IFLT, 0 },
4742+ { "IFLE", K_IFLE, 0 },
4743+ { "IFGE", K_IFGE, 0 },
4744+ { "IFGT", K_IFGT, 0 },
4745+ { "IFC", K_IFC, 0 },
4746+ { "IFNC", K_IFNC, 0 },
4747+ { "ELSEC", K_AELSE, 0 },
4748+ { "ENDC", K_AENDI, 0 },
4749+ { "MEXIT", K_EXITM, 0 },
4750+ { "REPT", K_AREPEAT, 0 },
4751+ { "IRP", K_IRP, 0 },
4752+ { "IRPC", K_IRPC, 0 },
4753+ { "ENDR", K_AENDR, 0 },
4754+ { NULL, 0, 0 }
4755+};
4756+
4757+/* Look for a pseudo op on the line. If one's there then call
4758+ its handler. */
4759+
4760+static int
4761+process_pseudo_op (idx, line, acc)
4762+ int idx;
4763+ sb *line;
4764+ sb *acc;
4765+{
4766+ int oidx = idx;
4767+
4768+ if (line->ptr[idx] == '.' || alternate || mri)
4769+ {
4770+ /* Scan forward and find pseudo name. */
4771+ char *in;
4772+ hash_entry *ptr;
4773+
4774+ char *s;
4775+ char *e;
4776+ if (line->ptr[idx] == '.')
4777+ idx++;
4778+ in = line->ptr + idx;
4779+ s = in;
4780+ e = s;
4781+ sb_reset (acc);
4782+
4783+ while (idx < line->len && *e && ISFIRSTCHAR (*e))
4784+ {
4785+ sb_add_char (acc, *e);
4786+ e++;
4787+ idx++;
4788+ }
4789+
4790+ ptr = hash_lookup (&keyword_hash_table, acc);
4791+
4792+ if (!ptr)
4793+ {
4794+#if 0
4795+ /* This one causes lots of pain when trying to preprocess
4796+ ordinary code. */
4797+ WARNING ((stderr, _("Unrecognised pseudo op `%s'.\n"),
4798+ sb_name (acc)));
4799+#endif
4800+ return 0;
4801+ }
4802+ if (ptr->value.i & LAB)
4803+ {
4804+ /* Output the label. */
4805+ if (label.len)
4806+ {
4807+ fprintf (outfile, "%s:\t", sb_name (&label));
4808+ }
4809+ else
4810+ fprintf (outfile, "\t");
4811+ }
4812+
4813+ if (mri && ptr->value.i == K_END)
4814+ {
4815+ sb t;
4816+
4817+ sb_new (&t);
4818+ sb_add_buffer (&t, line->ptr + oidx, idx - oidx);
4819+ fprintf (outfile, "\t%s", sb_name (&t));
4820+ sb_kill (&t);
4821+ }
4822+
4823+ if (ptr->value.i & PROCESS)
4824+ {
4825+ /* Polish the rest of the line before handling the pseudo op. */
4826+#if 0
4827+ strip_comments (line);
4828+#endif
4829+ sb_reset (acc);
4830+ process_assigns (idx, line, acc);
4831+ sb_reset (line);
4832+ change_base (0, acc, line);
4833+ idx = 0;
4834+ }
4835+ if (!condass_on ())
4836+ {
4837+ switch (ptr->value.i)
4838+ {
4839+ case K_AIF:
4840+ do_aif (idx, line);
4841+ break;
4842+ case K_AELSE:
4843+ do_aelse ();
4844+ break;
4845+ case K_AENDI:
4846+ do_aendi ();
4847+ break;
4848+ }
4849+ return 1;
4850+ }
4851+ else
4852+ {
4853+ switch (ptr->value.i)
4854+ {
4855+ case K_ALTERNATE:
4856+ alternate = 1;
4857+ macro_init (1, mri, 0, exp_get_abs);
4858+ return 1;
4859+ case K_AELSE:
4860+ do_aelse ();
4861+ return 1;
4862+ case K_AENDI:
4863+ do_aendi ();
4864+ return 1;
4865+ case K_ORG:
4866+ ERROR ((stderr, _("ORG command not allowed.\n")));
4867+ break;
4868+ case K_RADIX:
4869+ do_radix (line);
4870+ return 1;
4871+ case K_DB:
4872+ do_data (idx, line, 1);
4873+ return 1;
4874+ case K_DW:
4875+ do_data (idx, line, 2);
4876+ return 1;
4877+ case K_DL:
4878+ do_data (idx, line, 4);
4879+ return 1;
4880+ case K_DATA:
4881+ do_data (idx, line, 0);
4882+ return 1;
4883+ case K_DATAB:
4884+ do_datab (idx, line);
4885+ return 1;
4886+ case K_SDATA:
4887+ do_sdata (idx, line, 0);
4888+ return 1;
4889+ case K_SDATAB:
4890+ do_sdatab (idx, line);
4891+ return 1;
4892+ case K_SDATAC:
4893+ do_sdata (idx, line, 'c');
4894+ return 1;
4895+ case K_SDATAZ:
4896+ do_sdata (idx, line, 'z');
4897+ return 1;
4898+ case K_ASSIGN:
4899+ do_assign (0, 0, line);
4900+ return 1;
4901+ case K_AIF:
4902+ do_aif (idx, line);
4903+ return 1;
4904+ case K_AREPEAT:
4905+ do_arepeat (idx, line);
4906+ return 1;
4907+ case K_AENDW:
4908+ do_aendw ();
4909+ return 1;
4910+ case K_AWHILE:
4911+ do_awhile (idx, line);
4912+ return 1;
4913+ case K_AENDR:
4914+ do_aendr ();
4915+ return 1;
4916+ case K_EQU:
4917+ do_assign (1, idx, line);
4918+ return 1;
4919+ case K_ALIGN:
4920+ do_align (idx, line);
4921+ return 1;
4922+ case K_RES:
4923+ do_res (idx, line, 0);
4924+ return 1;
4925+ case K_SRES:
4926+ do_res (idx, line, 's');
4927+ return 1;
4928+ case K_INCLUDE:
4929+ do_include (idx, line);
4930+ return 1;
4931+ case K_LOCAL:
4932+ do_local (idx, line);
4933+ return 1;
4934+ case K_MACRO:
4935+ do_macro (idx, line);
4936+ return 1;
4937+ case K_ENDM:
4938+ do_endm ();
4939+ return 1;
4940+ case K_SRESC:
4941+ do_res (idx, line, 'c');
4942+ return 1;
4943+ case K_PRINT:
4944+ do_print (idx, line);
4945+ return 1;
4946+ case K_FORM:
4947+ do_form (idx, line);
4948+ return 1;
4949+ case K_HEADING:
4950+ do_heading (idx, line);
4951+ return 1;
4952+ case K_PAGE:
4953+ do_page ();
4954+ return 1;
4955+ case K_GLOBAL:
4956+ case K_EXPORT:
4957+ do_export (line);
4958+ return 1;
4959+ case K_IMPORT:
4960+ return 1;
4961+ case K_SRESZ:
4962+ do_res (idx, line, 'z');
4963+ return 1;
4964+ case K_IGNORED:
4965+ return 1;
4966+ case K_END:
4967+ do_end (line);
4968+ return 1;
4969+ case K_ASSIGNA:
4970+ do_assigna (idx, line);
4971+ return 1;
4972+ case K_ASSIGNC:
4973+ do_assignc (idx, line);
4974+ return 1;
4975+ case K_EXITM:
4976+ do_exitm ();
4977+ return 1;
4978+ case K_REG:
4979+ do_reg (idx, line);
4980+ return 1;
4981+ case K_IFEQ:
4982+ do_if (idx, line, EQ);
4983+ return 1;
4984+ case K_IFNE:
4985+ do_if (idx, line, NE);
4986+ return 1;
4987+ case K_IFLT:
4988+ do_if (idx, line, LT);
4989+ return 1;
4990+ case K_IFLE:
4991+ do_if (idx, line, LE);
4992+ return 1;
4993+ case K_IFGE:
4994+ do_if (idx, line, GE);
4995+ return 1;
4996+ case K_IFGT:
4997+ do_if (idx, line, GT);
4998+ return 1;
4999+ case K_IFC:
5000+ do_ifc (idx, line, 0);
5001+ return 1;
5002+ case K_IFNC:
5003+ do_ifc (idx, line, 1);
5004+ return 1;
5005+ case K_IRP:
5006+ do_irp (idx, line, 0);
5007+ return 1;
5008+ case K_IRPC:
5009+ do_irp (idx, line, 1);
5010+ return 1;
5011+ }
5012+ }
5013+ }
5014+ return 0;
5015+}
5016+
5017+/* Add a keyword to the hash table. */
5018+
5019+static void
5020+add_keyword (name, code)
5021+ const char *name;
5022+ int code;
5023+{
5024+ sb label;
5025+ int j;
5026+
5027+ sb_new (&label);
5028+ sb_add_string (&label, name);
5029+
5030+ hash_add_to_int_table (&keyword_hash_table, &label, code);
5031+
5032+ sb_reset (&label);
5033+ for (j = 0; name[j]; j++)
5034+ sb_add_char (&label, name[j] - 'A' + 'a');
5035+ hash_add_to_int_table (&keyword_hash_table, &label, code);
5036+
5037+ sb_kill (&label);
5038+}
5039+
5040+/* Build the keyword hash table - put each keyword in the table twice,
5041+ once upper and once lower case. */
5042+
5043+static void
5044+process_init ()
5045+{
5046+ int i;
5047+
5048+ for (i = 0; kinfo[i].name; i++)
5049+ add_keyword (kinfo[i].name, kinfo[i].code);
5050+
5051+ if (mri)
5052+ {
5053+ for (i = 0; mrikinfo[i].name; i++)
5054+ add_keyword (mrikinfo[i].name, mrikinfo[i].code);
5055+ }
5056+}
5057+
5058+static void
5059+do_define (string)
5060+ const char *string;
5061+{
5062+ sb label;
5063+ int res = 1;
5064+ hash_entry *ptr;
5065+ sb_new (&label);
5066+
5067+ while (*string)
5068+ {
5069+ if (*string == '=')
5070+ {
5071+ sb value;
5072+ sb_new (&value);
5073+ string++;
5074+ while (*string)
5075+ {
5076+ sb_add_char (&value, *string);
5077+ string++;
5078+ }
5079+ exp_get_abs (_("Invalid expression on command line.\n"),
5080+ 0, &value, &res);
5081+ sb_kill (&value);
5082+ break;
5083+ }
5084+ sb_add_char (&label, *string);
5085+
5086+ string++;
5087+ }
5088+
5089+ ptr = hash_create (&vars, &label);
5090+ free_old_entry (ptr);
5091+ ptr->type = hash_integer;
5092+ ptr->value.i = res;
5093+ sb_kill (&label);
5094+}
5095+
5096+char *program_name;
5097+
5098+/* The list of long options. */
5099+static struct option long_options[] =
5100+{
5101+ { "alternate", no_argument, 0, 'a' },
5102+ { "include", required_argument, 0, 'I' },
5103+ { "commentchar", required_argument, 0, 'c' },
5104+ { "copysource", no_argument, 0, 's' },
5105+ { "debug", no_argument, 0, 'd' },
5106+ { "help", no_argument, 0, 'h' },
5107+ { "mri", no_argument, 0, 'M' },
5108+ { "output", required_argument, 0, 'o' },
5109+ { "print", no_argument, 0, 'p' },
5110+ { "unreasonable", no_argument, 0, 'u' },
5111+ { "version", no_argument, 0, 'v' },
5112+ { "define", required_argument, 0, 'd' },
5113+ { NULL, no_argument, 0, 0 }
5114+};
5115+
5116+/* Show a usage message and exit. */
5117+static void
5118+show_usage (file, status)
5119+ FILE *file;
5120+ int status;
5121+{
5122+ fprintf (file, _("\
5123+Usage: %s \n\
5124+ [-a] [--alternate] enter alternate macro mode\n\
5125+ [-c char] [--commentchar char] change the comment character from !\n\
5126+ [-d] [--debug] print some debugging info\n\
5127+ [-h] [--help] print this message\n\
5128+ [-M] [--mri] enter MRI compatibility mode\n\
5129+ [-o out] [--output out] set the output file\n\
5130+ [-p] [--print] print line numbers\n"), program_name);
5131+ fprintf (file, _("\
5132+ [-s] [--copysource] copy source through as comments \n\
5133+ [-u] [--unreasonable] allow unreasonable nesting\n\
5134+ [-v] [--version] print the program version\n\
5135+ [-Dname=value] create preprocessor variable called name, with value\n\
5136+ [-Ipath] add to include path list\n\
5137+ [in-file]\n"));
5138+ if (status == 0)
5139+ printf (_("Report bugs to %s\n"), REPORT_BUGS_TO);
5140+ exit (status);
5141+}
5142+
5143+/* Display a help message and exit. */
5144+
5145+static void
5146+show_help ()
5147+{
5148+ printf (_("%s: Gnu Assembler Macro Preprocessor\n"), program_name);
5149+ show_usage (stdout, 0);
5150+}
5151+
5152+int main PARAMS ((int, char **));
5153+
5154+int
5155+main (argc, argv)
5156+ int argc;
5157+ char **argv;
5158+{
5159+ int opt;
5160+ char *out_name = 0;
5161+ sp = include_stack;
5162+
5163+ ifstack[0].on = 1;
5164+ ifi = 0;
5165+
5166+#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
5167+ setlocale (LC_MESSAGES, "");
5168+#endif
5169+#if defined (HAVE_SETLOCALE)
5170+ setlocale (LC_CTYPE, "");
5171+#endif
5172+ bindtextdomain (PACKAGE, LOCALEDIR);
5173+ textdomain (PACKAGE);
5174+
5175+ program_name = argv[0];
5176+ xmalloc_set_program_name (program_name);
5177+
5178+ hash_new_table (101, &keyword_hash_table);
5179+ hash_new_table (101, &assign_hash_table);
5180+ hash_new_table (101, &vars);
5181+
5182+ sb_new (&label);
5183+
5184+ while ((opt = getopt_long (argc, argv, "I:sdhavc:upo:D:M", long_options,
5185+ (int *) NULL))
5186+ != EOF)
5187+ {
5188+ switch (opt)
5189+ {
5190+ case 'o':
5191+ out_name = optarg;
5192+ break;
5193+ case 'u':
5194+ unreasonable = 1;
5195+ break;
5196+ case 'I':
5197+ {
5198+ include_path *p = (include_path *) xmalloc (sizeof (include_path));
5199+ p->next = NULL;
5200+ sb_new (&p->path);
5201+ sb_add_string (&p->path, optarg);
5202+ if (paths_tail)
5203+ paths_tail->next = p;
5204+ else
5205+ paths_head = p;
5206+ paths_tail = p;
5207+ }
5208+ break;
5209+ case 'p':
5210+ print_line_number = 1;
5211+ break;
5212+ case 'c':
5213+ comment_char = optarg[0];
5214+ break;
5215+ case 'a':
5216+ alternate = 1;
5217+ break;
5218+ case 's':
5219+ copysource = 1;
5220+ break;
5221+ case 'd':
5222+ stats = 1;
5223+ break;
5224+ case 'D':
5225+ do_define (optarg);
5226+ break;
5227+ case 'M':
5228+ mri = 1;
5229+ comment_char = ';';
5230+ break;
5231+ case 'h':
5232+ show_help ();
5233+ /* NOTREACHED */
5234+ case 'v':
5235+ /* This output is intended to follow the GNU standards document. */
5236+ printf (_("GNU assembler pre-processor %s\n"), program_version);
5237+ printf (_("Copyright 1996 Free Software Foundation, Inc.\n"));
5238+ printf (_("\
5239+This program is free software; you may redistribute it under the terms of\n\
5240+the GNU General Public License. This program has absolutely no warranty.\n"));
5241+ exit (0);
5242+ /* NOTREACHED */
5243+ case 0:
5244+ break;
5245+ default:
5246+ show_usage (stderr, 1);
5247+ /* NOTREACHED */
5248+ }
5249+ }
5250+
5251+ process_init ();
5252+
5253+ macro_init (alternate, mri, 0, exp_get_abs);
5254+
5255+ if (out_name)
5256+ {
5257+ outfile = fopen (out_name, "w");
5258+ if (!outfile)
5259+ {
5260+ fprintf (stderr, _("%s: Can't open output file `%s'.\n"),
5261+ program_name, out_name);
5262+ exit (1);
5263+ }
5264+ }
5265+ else
5266+ {
5267+ outfile = stdout;
5268+ }
5269+
5270+ chartype_init ();
5271+ if (!outfile)
5272+ outfile = stdout;
5273+
5274+ /* Process all the input files. */
5275+
5276+ while (optind < argc)
5277+ {
5278+ if (new_file (argv[optind]))
5279+ {
5280+ process_file ();
5281+ }
5282+ else
5283+ {
5284+ fprintf (stderr, _("%s: Can't open input file `%s'.\n"),
5285+ program_name, argv[optind]);
5286+ exit (1);
5287+ }
5288+ optind++;
5289+ }
5290+
5291+ quit ();
5292+ return 0;
5293+}
5294+
5295+/* This function is used because an abort in some of the other files
5296+ may be compiled into as_abort because they include as.h. */
5297+
5298+void
5299+as_abort (file, line, fn)
5300+ const char *file, *fn;
5301+ int line;
5302+{
5303+ fprintf (stderr, _("Internal error, aborting at %s line %d"), file, line);
5304+ if (fn)
5305+ fprintf (stderr, " in %s", fn);
5306+ fprintf (stderr, _("\nPlease report this bug.\n"));
5307+ exit (1);
5308+}
1684d5ca
JB
5309+
5310+/* duplicated from as internals */
5311+
5312+static void
5313+identify (char *file)
5314+{
5315+ static int identified;
5316+
5317+ if (identified)
5318+ return;
5319+ identified++;
5320+
5321+ if (file)
5322+ fprintf (stderr, "%s: ", file);
5323+ fprintf (stderr, _("Assembler messages:\n"));
5324+}
5325+
5326+/* The number of warnings issued. */
5327+static int warning_count;
5328+
5329+/* The common portion of as_warn and as_warn_where. */
5330+
5331+static void
5332+as_warn_internal (char *file, unsigned int line, char *buffer)
5333+{
5334+ ++warning_count;
5335+
5336+ identify (file);
5337+ if (file)
5338+ fprintf (stderr, "%s:%u: ", file, line);
5339+ fprintf (stderr, _("Warning: "));
5340+ fputs (buffer, stderr);
5341+ (void) putc ('\n', stderr);
5342+}
5343+
5344+/* Send to stderr a string as a warning, and locate warning
5345+ in input file(s).
5346+ Please only use this for when we have some recovery action.
5347+ Please explain in string (which may have '\n's) what recovery was
5348+ done. */
5349+
5350+void
5351+as_warn (const char *format, ...)
5352+{
5353+ va_list args;
5354+ char buffer[2000];
5355+
5356+ if (1 /*!flag_no_warnings*/)
5357+ {
5358+ va_start (args, format);
5359+ vsprintf (buffer, format, args);
5360+ va_end (args);
5361+ as_warn_internal ((char *) NULL, 0, buffer);
5362+ }
5363+}
5364+
892a047e
JB
5365+/* Like as_bad but the file name and line number are passed in.
5366+ Unfortunately, we have to repeat the function in order to handle
5367+ the varargs correctly and portably. */
5368+
5369+void
5370+as_warn_where (char *file, unsigned int line, const char *format, ...)
5371+{
5372+ va_list args;
5373+ char buffer[2000];
5374+
5375+ if (1 /*!flag_no_warnings*/)
5376+ {
5377+ va_start (args, format);
5378+ vsprintf (buffer, format, args);
5379+ va_end (args);
5380+ as_warn_internal (file, line, buffer);
5381+ }
5382+}
5383+
1684d5ca
JB
5384+/* Nonzero if we've hit a 'bad error', and should not write an obj file,
5385+ and exit with a nonzero error code. */
5386+
5387+static int error_count;
5388+
5389+/* The common portion of as_bad and as_bad_where. */
5390+
5391+static void
5392+as_bad_internal (char *file, unsigned int line, char *buffer)
5393+{
5394+ ++error_count;
5395+
5396+ identify (file);
5397+ if (file)
5398+ fprintf (stderr, "%s:%u: ", file, line);
5399+ fprintf (stderr, _("Error: "));
5400+ fputs (buffer, stderr);
5401+ (void) putc ('\n', stderr);
5402+}
5403+
892a047e
JB
5404+/* Send to stderr a string as a warning, and locate warning in input
5405+ file(s). Please us when there is no recovery, but we want to
5406+ continue processing but not produce an object file.
5407+ Please explain in string (which may have '\n's) what recovery was
5408+ done. */
5409+
5410+void
5411+as_bad (const char *format, ...)
5412+{
5413+ va_list args;
5414+ char buffer[2000];
5415+
5416+ va_start (args, format);
5417+ vsprintf (buffer, format, args);
5418+ va_end (args);
5419+
5420+ as_bad_internal ((char *) NULL, 0, buffer);
5421+}
5422+
5423+/* Like as_bad but the file name and line number are passed in.
5424+ Unfortunately, we have to repeat the function in order to handle
5425+ the varargs correctly and portably. */
5426+
1684d5ca
JB
5427+void
5428+as_bad_where (char *file, unsigned int line, const char *format, ...)
5429+{
5430+ va_list args;
5431+ char buffer[2000];
5432+
5433+ va_start (args, format);
5434+ vsprintf (buffer, format, args);
5435+ va_end (args);
5436+
5437+ as_bad_internal (file, line, buffer);
5438+}
5439+
34c762af
JB
5440+/* Indicate assertion failure.
5441+ Arguments: Filename, line number, optional function name. */
5442+
5443+void
5444+as_assert (const char *file, int line, const char *fn)
5445+{
5446+ fprintf (stderr, _("Internal error!\n"));
5447+ if (fn)
5448+ fprintf (stderr, _("Assertion failure in %s at %s line %d.\n"),
5449+ fn, file, line);
5450+ else
5451+ fprintf (stderr, _("Assertion failure at %s line %d.\n"), file, line);
5452+ fprintf (stderr, _("Please report this bug.\n"));
5453+ xexit (EXIT_FAILURE);
5454+}
5455+
1684d5ca
JB
5456+#ifndef LEX_AT
5457+/* The m88k unfortunately uses @ as a label beginner. */
5458+#define LEX_AT 0
5459+#endif
5460+
5461+#ifndef LEX_BR
5462+/* The RS/6000 assembler uses {,},[,] as parts of symbol names. */
5463+#define LEX_BR 0
5464+#endif
5465+
5466+#ifndef LEX_PCT
5467+/* The Delta 68k assembler permits % inside label names. */
5468+#define LEX_PCT 0
5469+#endif
5470+
5471+#ifndef LEX_QM
5472+/* The PowerPC Windows NT assemblers permits ? inside label names. */
5473+#define LEX_QM 0
5474+#endif
5475+
5476+#ifndef LEX_HASH
5477+/* The IA-64 assembler uses # as a suffix designating a symbol. We include
5478+ it in the symbol and strip it out in tc_canonicalize_symbol_name. */
5479+#define LEX_HASH 0
5480+#endif
5481+
5482+#ifndef LEX_DOLLAR
5483+/* The a29k assembler does not permits labels to start with $. */
5484+#define LEX_DOLLAR 3
5485+#endif
5486+
5487+#ifndef LEX_TILDE
5488+/* The Delta 68k assembler permits ~ at start of label names. */
5489+#define LEX_TILDE 0
5490+#endif
5491+
5492+/* Used by is_... macros. our ctype[]. */
5493+char lex_type[256] = {
5494+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* @ABCDEFGHIJKLMNO */
5495+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* PQRSTUVWXYZ[\]^_ */
5496+ 0, 0, 0, LEX_HASH, LEX_DOLLAR, LEX_PCT, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, /* _!"#$%&'()*+,-./ */
5497+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, LEX_QM, /* 0123456789:;<=>? */
5498+ LEX_AT, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* @ABCDEFGHIJKLMNO */
5499+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, LEX_BR, 0, LEX_BR, 0, 3, /* PQRSTUVWXYZ[\]^_ */
5500+ 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* `abcdefghijklmno */
5501+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, LEX_BR, 0, LEX_BR, LEX_TILDE, 0, /* pqrstuvwxyz{|}~. */
5502+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
5503+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
5504+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
5505+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
5506+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
5507+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
5508+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
5509+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
5510+};
7d553eaf
JB
5511+
5512+/* just a stub to satisfy unused function in sb.o */
5513+int do_scrub_chars (int (*get) (char*, int), char *tostart, int tolen) {}
e85a30b2
AM
5514--- binutils-2.16.91.0.2.org/gas/macro.c 2005-05-10 22:46:44.000000000 +0000
5515+++ binutils-2.16.91.0.2/gas/macro.c 2005-07-21 18:31:04.000000000 +0000
1be9367e 5516@@ -41,8 +41,8 @@
4f1b0aad
JB
5517 static int get_apost_token (int, sb *, sb *, int);
5518 static int sub_actual (int, sb *, sb *, struct hash_control *, int, sb *, int);
2859501d 5519 static const char *macro_expand_body
1684d5ca 5520- (sb *, sb *, formal_entry *, struct hash_control *, const macro_entry *);
4f1b0aad 5521-static const char *macro_expand (int, sb *, macro_entry *, sb *);
1684d5ca 5522+ (sb *, sb *, formal_entry *, struct hash_control *, const macro_entry *, int);
4f1b0aad 5523+static const char *macro_expand (int, sb *, macro_entry *, sb *, int);
1684d5ca 5524 static void free_macro(macro_entry *);
2859501d
JB
5525
5526 #define ISWHITE(x) ((x) == ' ' || (x) == '\t')
1be9367e 5527@@ -754,7 +754,7 @@
2859501d
JB
5528
5529 static const char *
4f1b0aad 5530 macro_expand_body (sb *in, sb *out, formal_entry *formals,
1684d5ca
JB
5531- struct hash_control *formal_hash, const macro_entry *macro)
5532+ struct hash_control *formal_hash, const macro_entry *macro, int comment_char)
2859501d
JB
5533 {
5534 sb t;
1684d5ca 5535 int src = 0, inquote = 0, macro_line = 0;
1be9367e 5536@@ -786,7 +786,14 @@
2859501d
JB
5537 else if (in->ptr[src] == '\\')
5538 {
5539 src++;
1684d5ca 5540- if (src < in->len && in->ptr[src] == '(')
2859501d
JB
5541+ if (in->ptr[src] == comment_char && comment_char != '\0')
5542+ {
5543+ /* This is a comment, just drop the rest of the line. */
5544+ while (src < in->len
5545+ && in->ptr[src] != '\n')
5546+ src++;
5547+ }
1684d5ca 5548+ else if (src < in->len && in->ptr[src] == '(')
2859501d
JB
5549 {
5550 /* Sub in till the next ')' literally. */
5551 src++;
1be9367e 5552@@ -867,7 +874,7 @@
1684d5ca
JB
5553 else
5554 {
2859501d
JB
5555 src = sb_skip_white (src + 5, in);
5556- while (in->ptr[src] != '\n')
5557+ while (in->ptr[src] != '\n' && in->ptr[src] != comment_char)
5558 {
1684d5ca 5559 const char *name;
892a047e 5560 formal_entry *f = new_formal ();
1be9367e 5561@@ -903,6 +910,17 @@
2859501d
JB
5562 }
5563 }
5564 }
5565+ else if (comment_char != '\0'
5566+ && in->ptr[src] == comment_char
5567+ && src + 1 < in->len
5568+ && in->ptr[src + 1] == comment_char
5569+ && !inquote)
5570+ {
5571+ /* Two comment chars in a row cause the rest of the line to
5572+ be dropped. */
5573+ while (src < in->len && in->ptr[src] != '\n')
5574+ src++;
5575+ }
5576 else if (in->ptr[src] == '"'
5577 || (macro_mri && in->ptr[src] == '\''))
5578 {
1be9367e 5579@@ -984,7 +1002,7 @@
2859501d
JB
5580 body. */
5581
5582 static const char *
4f1b0aad
JB
5583-macro_expand (int idx, sb *in, macro_entry *m, sb *out)
5584+macro_expand (int idx, sb *in, macro_entry *m, sb *out, int comment_char)
2859501d
JB
5585 {
5586 sb t;
5587 formal_entry *ptr;
1be9367e 5588@@ -1029,7 +1047,7 @@
2859501d
JB
5589
5590 /* Peel off the actuals and store them away in the hash tables' actuals. */
5591 idx = sb_skip_white (idx, in);
5592- while (idx < in->len)
5593+ while (idx < in->len && in->ptr[idx] != comment_char)
5594 {
5595 int scan;
5596
1be9367e 5597@@ -1156,7 +1174,7 @@
892a047e
JB
5598 sb_add_string (&ptr->actual, buffer);
5599 }
2859501d 5600
892a047e
JB
5601- err = macro_expand_body (&m->sub, out, m->formals, m->formal_hash, m);
5602+ err = macro_expand_body (&m->sub, out, m->formals, m->formal_hash, m, comment_char);
5603 }
2859501d 5604
1684d5ca 5605 /* Discard any unnamed formal arguments. */
1be9367e 5606@@ -1189,7 +1207,7 @@
2859501d
JB
5607 *EXPAND. Return 1 if a macro is found, 0 otherwise. */
5608
5609 int
4f1b0aad
JB
5610-check_macro (const char *line, sb *expand,
5611+check_macro (const char *line, sb *expand, int comment_char,
5612 const char **error, macro_entry **info)
2859501d 5613 {
4f1b0aad 5614 const char *s;
1be9367e 5615@@ -1224,7 +1242,7 @@
2859501d
JB
5616 sb_add_char (&line_sb, *s++);
5617
5618 sb_new (expand);
5619- *error = macro_expand (0, &line_sb, macro, expand);
5620+ *error = macro_expand (0, &line_sb, macro, expand, comment_char);
5621
5622 sb_kill (&line_sb);
5623
1be9367e 5624@@ -1285,7 +1303,7 @@
2859501d
JB
5625 success, or an error message otherwise. */
5626
5627 const char *
4f1b0aad
JB
5628-expand_irp (int irpc, int idx, sb *in, sb *out, int (*get_line) (sb *))
5629+expand_irp (int irpc, int idx, sb *in, sb *out, int (*get_line) (sb *), int comment_char)
2859501d 5630 {
2859501d 5631 sb sub;
1684d5ca 5632 formal_entry f;
1be9367e 5633@@ -1318,10 +1336,10 @@
2859501d
JB
5634 sb_reset (out);
5635
5636 idx = sb_skip_comma (idx, in);
5637- if (idx >= in->len)
5638+ if (idx >= in->len || in->ptr[idx] == comment_char)
5639 {
5640 /* Expand once with a null string. */
5641- err = macro_expand_body (&sub, out, &f, h, 0);
1684d5ca 5642+ err = macro_expand_body (&sub, out, &f, h, 0, comment_char);
2859501d 5643 }
1684d5ca 5644 else
2859501d 5645 {
1be9367e
PS
5646@@ -1333,7 +1351,7 @@
5647 ++idx;
5648 }
5649
2859501d
JB
5650- while (idx < in->len)
5651+ while (idx < in->len && in->ptr[idx] != comment_char)
5652 {
5653 if (!irpc)
892a047e 5654 idx = get_any_string (idx, in, &f.actual);
1be9367e
PS
5655@@ -1347,7 +1365,7 @@
5656 in_quotes = ! in_quotes;
5657
2859501d
JB
5658 nxt = sb_skip_white (idx + 1, in);
5659- if (nxt >= in->len)
5660+ if (nxt >= in->len || in->ptr[nxt] == comment_char)
5661 {
5662 idx = nxt;
5663 break;
1be9367e 5664@@ -1358,7 +1376,7 @@
2859501d
JB
5665 ++idx;
5666 }
1be9367e 5667
2859501d 5668- err = macro_expand_body (&sub, out, &f, h, 0);
1684d5ca 5669+ err = macro_expand_body (&sub, out, &f, h, 0, comment_char);
2859501d 5670 if (err != NULL)
1684d5ca 5671 break;
2859501d 5672 if (!irpc)
e85a30b2
AM
5673--- binutils-2.16.91.0.2.org/gas/macro.h 2005-05-10 22:46:44.000000000 +0000
5674+++ binutils-2.16.91.0.2/gas/macro.h 2005-07-21 18:31:04.000000000 +0000
5675@@ -90,8 +90,8 @@
4f1b0aad 5676 extern void macro_mri_mode (int);
2859501d 5677 extern const char *define_macro
1684d5ca 5678 (int, sb *, sb *, int (*) (sb *), char *, unsigned int, const char **);
4f1b0aad
JB
5679-extern int check_macro (const char *, sb *, const char **, macro_entry **);
5680+extern int check_macro (const char *, sb *, int, const char **, macro_entry **);
5681 extern void delete_macro (const char *);
5682-extern const char *expand_irp (int, int, sb *, sb *, int (*) (sb *));
5683+extern const char *expand_irp (int, int, sb *, sb *, int (*) (sb *), int);
2859501d
JB
5684
5685 #endif
e85a30b2
AM
5686--- binutils-2.16.91.0.2.org/gas/read.c 2005-06-22 20:53:34.000000000 +0000
5687+++ binutils-2.16.91.0.2/gas/read.c 2005-07-21 18:31:04.000000000 +0000
5688@@ -555,7 +555,7 @@
1684d5ca
JB
5689 const char *err;
5690 macro_entry *macro;
2859501d 5691
1684d5ca
JB
5692- if (check_macro (line, &out, &err, &macro))
5693+ if (check_macro (line, &out, '\0', &err, &macro))
5694 {
5695 if (err != NULL)
5696 as_bad ("%s", err);
e85a30b2 5697@@ -1958,7 +1958,7 @@
2859501d
JB
5698
5699 sb_new (&out);
5700
5701- err = expand_irp (irpc, 0, &s, &out, get_line_sb);
5702+ err = expand_irp (irpc, 0, &s, &out, get_line_sb, '\0');
5703 if (err != NULL)
5704 as_bad_where (file, line, "%s", err);
5705
This page took 7.04821 seconds and 4 git commands to generate.