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