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