[packages/binutils] - removed gasp remains, moved to binutils-gasp.spec
qboosh
qboosh at pld-linux.org
Tue Sep 27 21:08:56 CEST 2022
commit 222a2fedcaea1f2c583dc4c1610506a2d2411b78
Author: Jakub Bogusz <qboosh at pld-linux.org>
Date: Tue Sep 27 21:09:01 2022 +0200
- removed gasp remains, moved to binutils-gasp.spec
binutils-gasp.patch | 5728 ---------------------------------------------------
binutils.spec | 36 +-
2 files changed, 1 insertion(+), 5763 deletions(-)
---
diff --git a/binutils.spec b/binutils.spec
index 4f18269..bb8fe05 100644
--- a/binutils.spec
+++ b/binutils.spec
@@ -8,7 +8,6 @@
%bcond_without gold # don't build gold (no C++ dependencies)
%bcond_without default_bfd # default ld.bfd instead of gold
%bcond_without debuginfod # debuginfo lokups with debuginfod
-%bcond_with gasp # gasp
%bcond_without gprofng # gprofng
%bcond_without jansson # Package Metadata embedding support
%bcond_without msgpack # msgpack support
@@ -17,9 +16,6 @@
%ifnarch %{ix86} %{x8664} x32 aarch64 %{arm}
%undefine with_gold
%endif
-%ifarch %{arm}
-%undefine with_gasp
-%endif
%ifnarch %{ix86} %{x8664} aarch64
%undefine with_gprofng 1
%endif
@@ -43,7 +39,6 @@ Source0: https://ftp.gnu.org/gnu/binutils/%{name}-%{version}.tar.lz
# Source0-md5: 061a1460a09cc71e51886c008be55d44
Source1: http://www.mif.pg.gda.pl/homepages/ankry/man-PLD/%{name}-non-english-man-pages.tar.bz2
# Source1-md5: a717d9707ec77d82acb6ec9078c472d6
-Patch0: %{name}-gasp.patch
Patch1: %{name}-info.patch
Patch2: %{name}-libtool-relink.patch
Patch3: %{name}-pt_pax_flags.patch
@@ -159,24 +154,8 @@ Static GNU binutils libraries (libbfd, libopcodes).
%description static -l pl.UTF-8
Biblioteki statyczne GNU binutils (libbfd, libopcodes).
-%package gasp
-Summary: GASP - old preprocessor for assembly programs
-Summary(pl.UTF-8): GASP - stary preprocesor dla programów w asemblerze
-Group: Development/Tools
-Requires: %{name} = %{epoch}:%{version}-%{release}
-
-%description gasp
-GASP - old preprocessor for assembly programs. It's officially
-obsoleted, but it's still needed to build some packages.
-
-%description gasp -l pl.UTF-8
-GASP - stary preprocesor dla programów w asemblerze. Jest oficjalnie
-uznany za przestarzały, ale jest nadal potrzebny do zbudowania
-niektórych pakietów.
-
%prep
%setup -q
-%{?with_gasp:%patch0 -p1}
%patch1 -p1
%patch2 -p1
%{?with_pax:%patch3 -p1}
@@ -196,7 +175,7 @@ niektórych pakietów.
%{__aclocal}
%{__autoconf}
-# non-standard regeneration (needed because of gasp patch)
+# non-standard regeneration
# AM_BINUTILS_WARNINGS in bfd/warning.m4, ZW_GNU_GETTEXT_SISTER_DIR in config/gettext-sister.m4
for dir in gas bfd; do
cd $dir || exit 1
@@ -328,12 +307,6 @@ rm -rf $RPM_BUILD_ROOT
%postun devel -p /sbin/postshell
-/usr/sbin/fix-info-dir -c %{_infodir}
-%post gasp -p /sbin/postshell
--/usr/sbin/fix-info-dir -c %{_infodir}
-
-%postun gasp -p /sbin/postshell
--/usr/sbin/fix-info-dir -c %{_infodir}
-
%files -f %{name}.lang
%defattr(644,root,root,755)
%doc README
@@ -462,10 +435,3 @@ rm -rf $RPM_BUILD_ROOT
%{_libdir}/libctf.a
%{_libdir}/libctf-nobfd.a
%{_libdir}/libopcodes.a
-
-%if %{with gasp}
-%files gasp
-%defattr(644,root,root,755)
-%attr(755,root,root) %{_bindir}/gasp
-%{_infodir}/gasp.info*
-%endif
diff --git a/binutils-gasp.patch b/binutils-gasp.patch
deleted file mode 100644
index 47c24fd..0000000
--- a/binutils-gasp.patch
+++ /dev/null
@@ -1,5728 +0,0 @@
---- binutils-2.17.50.0.13/gas/Makefile.am.orig 2007-03-16 16:48:29.000000000 +0100
-+++ binutils-2.17.50.0.13/gas/Makefile.am 2007-03-16 20:26:20.200480821 +0100
-@@ -199,7 +199,7 @@
- symbols.c \
- write.c
-
--CFILES = $(GAS_CFILES) itbl-ops.c cgen.c
-+CFILES = $(GAS_CFILES) gasp.c itbl-ops.c cgen.c
-
- HFILES = \
- as.h \
-@@ -455,7 +455,8 @@
-
- # Note: GASP is now deprecated and has been removed. It is still
- # available in the CVS archive or older binutils releases if it is needed.
--noinst_PROGRAMS = as-new
-+# ...and it is needed for few packages in distribution.
-+noinst_PROGRAMS = as-new gasp-new
- noinst_SCRIPTS = $(GDBINIT)
- EXTRA_SCRIPTS = .gdbinit
-
-@@ -517,6 +518,10 @@
- $(OBJ_FORMAT_CFILES) $(OBJ_FORMAT_HFILES) \
- $(CONFIG_ATOF_CFILES) $(MULTI_CFILES)
-
-+gasp_new_SOURCES = gasp.c macro.c sb.c hash.c
-+gasp_new_LDADD = ../bfd/libbfd.la ../libiberty/libiberty.a $(LIBINTL)
-+gasp_new_DEPENDENCIES = ../bfd/libbfd.la ../libiberty/libiberty.a $(LIBINTL_DEP)
-+
- EXPECT = expect
- RUNTEST = runtest
- RUNTESTFLAGS=
-@@ -682,6 +682,9 @@
-
- itbl-lex-wrapper. at OBJEXT@: itbl-lex.c itbl-parse.h
-
-+gasp.o:gasp.c $(INCDIR)/getopt.h $(INCDIR)/safe-ctype.h \
-+ as.h sb.h macro.h $(INCDIR)/xregex.h $(INCDIR)/xregex2.h
-+
- itbl-parse.c: $(srcdir)/itbl-parse.y
- $(SHELL) $(YLWRAP) $(srcdir)/itbl-parse.y y.tab.c $@ y.tab.h itbl-parse.h -- $(YACCCOMPILE) -d
-
---- binutils-2.38/gas/doc/local.mk.orig 2022-01-22 13:14:08.000000000 +0100
-+++ binutils-2.38/gas/doc/local.mk 2022-02-13 11:08:05.134403535 +0100
-@@ -30,7 +30,7 @@
-
- man_MANS = %D%/as.1
-
--info_TEXINFOS = %D%/as.texi
-+info_TEXINFOS = %D%/as.texi %D%/gasp.texi
- %C%_as_TEXINFOS = %D%/asconfig.texi $(CPU_DOCS)
-
- AM_MAKEINFOFLAGS = -I "$(srcdir)/%D%" -I %D% -I "$(srcdir)/../libiberty" \
---- binutils-2.16.91.0.2.org/gas/doc/gasp.texi 1970-01-01 00:00:00.000000000 +0000
-+++ binutils-2.16.91.0.2/gas/doc/gasp.texi 2005-07-21 18:31:04.000000000 +0000
-@@ -0,0 +1,1456 @@
-+\input texinfo @c -*- Texinfo -*-
-+ at setfilename gasp.info
-+ at c
-+ at c This file documents the assembly preprocessor "GASP"
-+ at c
-+ at c Copyright 1994, 1995, 2000, 2002 Free Software Foundation, Inc.
-+ at c
-+ at c Permission is granted to copy, distribute and/or modify this document
-+ at c under the terms of the GNU Free Documentation License, Version 1.1
-+ at c or any later version published by the Free Software Foundation;
-+ at c with no Invariant Sections, with no Front-Cover Texts, and with no
-+ at c Back-Cover Texts. A copy of the license is included in the
-+ at c section entitled "GNU Free Documentation License".
-+
-+ at ifinfo
-+ at format
-+START-INFO-DIR-ENTRY
-+* gasp: (gasp). The GNU Assembler Preprocessor
-+END-INFO-DIR-ENTRY
-+ at end format
-+ at end ifinfo
-+
-+ at syncodeindex ky cp
-+ at syncodeindex fn cp
-+
-+ at finalout
-+ at setchapternewpage odd
-+ at settitle GASP
-+ at titlepage
-+ at c FIXME boring title
-+ at title GASP, an assembly preprocessor
-+ at subtitle for GASP version 1
-+ at sp 1
-+ at subtitle March 1994
-+ at author Roland Pesch
-+ at page
-+
-+ at tex
-+{\parskip=0pt \hfill Cygnus Support\par
-+}
-+ at end tex
-+
-+ at vskip 0pt plus 1filll
-+Copyright @copyright{} 1994, 1995, 2000, 2002 Free Software Foundation, Inc.
-+
-+ Permission is granted to copy, distribute and/or modify this document
-+ under the terms of the GNU Free Documentation License, Version 1.1
-+ or any later version published by the Free Software Foundation;
-+ with no Invariant Sections, with no Front-Cover Texts, and with no
-+ Back-Cover Texts. A copy of the license is included in the
-+ section entitled "GNU Free Documentation License".
-+
-+ at end titlepage
-+
-+ at ifinfo
-+Copyright @copyright{} 1994, 1995, 2000, 2002 Free Software Foundation, Inc.
-+
-+ at ignore
-+Permission is granted to process this file through TeX and print the
-+results, provided the printed document carries a copying permission
-+notice identical to this one except for the removal of this paragraph
-+(this paragraph not being relevant to the printed manual).
-+ at end ignore
-+
-+ Permission is granted to copy, distribute and/or modify this document
-+ under the terms of the GNU Free Documentation License, Version 1.1
-+ or any later version published by the Free Software Foundation;
-+ with no Invariant Sections, with no Front-Cover Texts, and with no
-+ Back-Cover Texts. A copy of the license is included in the
-+ section entitled "GNU Free Documentation License".
-+
-+
-+ at node Top
-+ at top GASP
-+
-+GASP is a preprocessor for assembly programs.
-+
-+This file describes version 1 of GASP.
-+
-+Steve Chamberlain wrote GASP; Roland Pesch wrote this manual.
-+
-+ at menu
-+* Overview:: What is GASP?
-+* Invoking GASP:: Command line options.
-+* Commands:: Preprocessor commands.
-+* GNU Free Documentation License:: GNU Free Documentation License
-+* Index:: Index.
-+ at end menu
-+ at end ifinfo
-+
-+ at node Overview
-+ at chapter What is GASP?
-+
-+The primary purpose of the @sc{gnu} assembler is to assemble the output of
-+other programs---notably compilers. When you have to hand-code
-+specialized routines in assembly, that means the @sc{gnu} assembler is
-+an unfriendly processor: it has no directives for macros, conditionals,
-+or many other conveniences that you might expect.
-+
-+In some cases you can simply use the C preprocessor, or a generalized
-+preprocessor like @sc{m4}; but this can be awkward, since none of these
-+things are designed with assembly in mind.
-+
-+ at sc{gasp} fills this need. It is expressly designed to provide the
-+facilities you need with hand-coded assembly code. Implementing it as a
-+preprocessor, rather than part of the assembler, allows the maximum
-+flexibility: you can use it with hand-coded assembly, without paying a
-+penalty of added complexity in the assembler you use for compiler
-+output.
-+
-+ at emph{Note} The use of @sc{gasp} has now been deprecated. Anything
-+that it could do can now be done by the macro facilities built into
-+ at sc{gas} itself. At some point in the future the @sc{gasp} sources will
-+be removed entirely from the binutils distribution.
-+
-+Here is a small example to give the flavor of @sc{gasp}. This input to
-+ at sc{gasp}
-+
-+ at cartouche
-+ at example
-+ .MACRO saveregs from=8 to=14
-+count .ASSIGNA \from
-+ ! save r\from..r\to
-+ .AWHILE \&count LE \to
-+ mov r\&count,@@-sp
-+count .ASSIGNA \&count + 1
-+ .AENDW
-+ .ENDM
-+
-+ saveregs from=12
-+
-+bar: mov #H'dead+10,r0
-+foo .SDATAC "hello"<10>
-+ .END
-+ at end example
-+ at end cartouche
-+
-+ at noindent
-+generates this assembly program:
-+
-+ at cartouche
-+ at example
-+ ! save r12..r14
-+ mov r12,@@-sp
-+ mov r13,@@-sp
-+ mov r14,@@-sp
-+
-+bar: mov #57005+10,r0
-+foo: .byte 6,104,101,108,108,111,10
-+ at end example
-+ at end cartouche
-+
-+ at node Invoking GASP
-+ at chapter Command Line Options
-+
-+ at c FIXME! Or is there a simpler way, calling from GAS option?
-+The simplest way to use @sc{gasp} is to run it as a filter and assemble
-+its output. In Unix and its ilk, you can do this, for example:
-+
-+ at c FIXME! GASP filename suffix convention?
-+ at example
-+$ gasp prog.asm | as -o prog.o
-+ at end example
-+
-+Naturally, there are also a few command-line options to allow you to
-+request variations on this basic theme. Here is the full set of
-+possibilities for the @sc{gasp} command line.
-+
-+ at example
-+gasp [ -a | --alternate ]
-+ [ -c @var{char} | --commentchar @var{char} ]
-+ [ -d | --debug ] [ -h | --help ] [ -M | --mri ]
-+ [ -o @var{outfile} | --output @var{outfile} ]
-+ [ -p | --print ] [ -s | --copysource ]
-+ [ -u | --unreasonable ] [ -v | --version ]
-+ @var{infile} @dots{}
-+ at end example
-+
-+ at ftable @code
-+ at item @var{infile} @dots{}
-+ at c FIXME! Why not stdin as default infile?
-+The input file names. You must specify at least one input file; if you
-+specify more, @sc{gasp} preprocesses them all, concatenating the output
-+in the order you list the @var{infile} arguments.
-+
-+Mark the end of each input file with the preprocessor command
-+ at code{.END}. @xref{Other Commands,, Miscellaneous commands}.
-+
-+ at item -a
-+ at itemx --alternate
-+Use alternative macro syntax. @xref{Alternate,, Alternate macro
-+syntax}, for a discussion of how this syntax differs from the default
-+ at sc{gasp} syntax.
-+
-+ at cindex comment character, changing
-+ at cindex semicolon, as comment
-+ at cindex exclamation mark, as comment
-+ at cindex shriek, as comment
-+ at cindex bang, as comment
-+ at cindex @code{!} default comment char
-+ at cindex @code{;} as comment char
-+ at item -c '@var{char}'
-+ at itemx --commentchar '@var{char}'
-+Use @var{char} as the comment character. The default comment character
-+is @samp{!}. For example, to use a semicolon as the comment character,
-+specify @w{@samp{-c ';'}} on the @sc{gasp} command line. Since
-+assembler command characters often have special significance to command
-+shells, it is a good idea to quote or escape @var{char} when you specify
-+a comment character.
-+
-+For the sake of simplicity, all examples in this manual use the default
-+comment character @samp{!}.
-+
-+ at item -d
-+ at itemx --debug
-+Show debugging statistics. In this version of @sc{gasp}, this option
-+produces statistics about the string buffers that @sc{gasp} allocates
-+internally. For each defined buffersize @var{s}, @sc{gasp} shows the
-+number of strings @var{n} that it allocated, with a line like this:
-+
-+ at example
-+strings size @var{s} : @var{n}
-+ at end example
-+
-+ at noindent
-+ at sc{gasp} displays these statistics on the standard error stream, when
-+done preprocessing.
-+
-+ at item -h
-+ at itemx --help
-+Display a summary of the @sc{gasp} command line options.
-+
-+ at item -M
-+ at itemx --mri
-+Use MRI compatibility mode. Using this option causes @sc{gasp} to
-+accept the syntax and pseudo-ops used by the Microtec Research
-+ at code{ASM68K} assembler.
-+
-+ at item -o @var{outfile}
-+ at itemx --output @var{outfile}
-+Write the output in a file called @var{outfile}. If you do not use the
-+ at samp{-o} option, @sc{gasp} writes its output on the standard output
-+stream.
-+
-+ at item -p
-+ at itemx --print
-+Print line numbers. @sc{gasp} obeys this option @emph{only} if you also
-+specify @samp{-s} to copy source lines to its output. With @samp{-s
-+-p}, @sc{gasp} displays the line number of each source line copied
-+(immediately after the comment character at the beginning of the line).
-+
-+ at item -s
-+ at itemx --copysource
-+Copy the source lines to the output file. Use this option
-+to see the effect of each preprocessor line on the @sc{gasp} output.
-+ at sc{gasp} places a comment character (@samp{!} by default) at
-+the beginning of each source line it copies, so that you can use this
-+option and still assemble the result.
-+
-+ at item -u
-+ at itemx --unreasonable
-+Bypass ``unreasonable expansion'' limit. Since you can define @sc{gasp}
-+macros inside other macro definitions, the preprocessor normally
-+includes a sanity check. If your program requires more than 1,000
-+nested expansions, @sc{gasp} normally exits with an error message. Use
-+this option to turn off this check, allowing unlimited nested
-+expansions.
-+
-+ at item -v
-+ at itemx --version
-+Display the @sc{gasp} version number.
-+ at end ftable
-+
-+ at node Commands
-+ at chapter Preprocessor Commands
-+
-+ at sc{gasp} commands have a straightforward syntax that fits in well with
-+assembly conventions. In general, a command extends for a line, and may
-+have up to three fields: an optional label, the command itself, and
-+optional arguments to the command. You can write commands in upper or
-+lower case, though this manual shows them in upper case. @xref{Syntax
-+Details,, Details of the GASP syntax}, for more information.
-+
-+ at menu
-+* Conditionals::
-+* Loops::
-+* Variables::
-+* Macros::
-+* Data::
-+* Listings::
-+* Other Commands::
-+* Syntax Details::
-+* Alternate::
-+ at end menu
-+
-+ at node Conditionals
-+ at section Conditional assembly
-+
-+The conditional-assembly directives allow you to include or exclude
-+portions of an assembly depending on how a pair of expressions, or a
-+pair of strings, compare.
-+
-+The overall structure of conditionals is familiar from many other
-+contexts. @code{.AIF} marks the start of a conditional, and precedes
-+assembly for the case when the condition is true. An optional
-+ at code{.AELSE} precedes assembly for the converse case, and an
-+ at code{.AENDI} marks the end of the condition.
-+
-+ at c FIXME! Why doesn't -u turn off this check?
-+You may nest conditionals up to a depth of 100; @sc{gasp} rejects
-+nesting beyond that, because it may indicate a bug in your macro
-+structure.
-+
-+ at c FIXME! Why isn't there something like cpp's -D option? Conditionals
-+ at c would be much more useful if there were.
-+Conditionals are primarily useful inside macro definitions, where you
-+often need different effects depending on argument values.
-+ at xref{Macros,, Defining your own directives}, for details about defining
-+macros.
-+
-+ at ftable @code
-+ at item .AIF @var{expra} @var{cmp} @var{exprb}
-+ at itemx .AIF "@var{stra}" @var{cmp} "@var{strb}"
-+
-+The governing condition goes on the same line as the @code{.AIF}
-+preprocessor command. You may compare either two strings, or two
-+expressions.
-+
-+When you compare strings, only two conditional @var{cmp} comparison
-+operators are available: @samp{EQ} (true if @var{stra} and @var{strb}
-+are identical), and @samp{NE} (the opposite).
-+
-+When you compare two expressions, @emph{both expressions must be
-+absolute} (@pxref{Expressions,, Arithmetic expressions in GASP}). You
-+can use these @var{cmp} comparison operators with expressions:
-+
-+ at ftable @code
-+ at item EQ
-+Are @var{expra} and @var{exprb} equal? (For strings, are @var{stra} and
-+ at var{strb} identical?)
-+
-+ at item NE
-+Are @var{expra} and @var{exprb} different? (For strings, are @var{stra}
-+and @var{strb} different?
-+
-+ at item LT
-+Is @var{expra} less than @var{exprb}? (Not allowed for strings.)
-+
-+ at item LE
-+Is @var{expra} less than or equal to @var{exprb}? (Not allowed for strings.)
-+
-+ at item GT
-+Is @var{expra} greater than @var{exprb}? (Not allowed for strings.)
-+
-+ at item GE
-+Is @var{expra} greater than or equal to @var{exprb}? (Not allowed for
-+strings.)
-+ at end ftable
-+
-+ at item .AELSE
-+Marks the start of assembly code to be included if the condition fails.
-+Optional, and only allowed within a conditional (between @code{.AIF} and
-+ at code{.AENDI}).
-+
-+ at item .AENDI
-+Marks the end of a conditional assembly.
-+ at end ftable
-+
-+ at node Loops
-+ at section Repetitive sections of assembly
-+
-+Two preprocessor directives allow you to repeatedly issue copies of the
-+same block of assembly code.
-+
-+ at ftable @code
-+ at item .AREPEAT @var{aexp}
-+ at itemx .AENDR
-+If you simply need to repeat the same block of assembly over and over a
-+fixed number of times, sandwich one instance of the repeated block
-+between @code{.AREPEAT} and @code{.AENDR}. Specify the number of
-+copies as @var{aexp} (which must be an absolute expression). For
-+example, this repeats two assembly statements three times in succession:
-+
-+ at cartouche
-+ at example
-+ .AREPEAT 3
-+ rotcl r2
-+ div1 r0,r1
-+ .AENDR
-+ at end example
-+ at end cartouche
-+
-+ at item .AWHILE @var{expra} @var{cmp} @var{exprb}
-+ at itemx .AENDW
-+ at itemx .AWHILE @var{stra} @var{cmp} @var{strb}
-+ at itemx .AENDW
-+To repeat a block of assembly depending on a conditional test, rather
-+than repeating it for a specific number of times, use @code{.AWHILE}.
-+ at code{.AENDW} marks the end of the repeated block. The conditional
-+comparison works exactly the same way as for @code{.AIF}, with the same
-+comparison operators (@pxref{Conditionals,, Conditional assembly}).
-+
-+Since the terms of the comparison must be absolute expression,
-+ at code{.AWHILE} is primarily useful within macros. @xref{Macros,,
-+Defining your own directives}.
-+ at end ftable
-+
-+ at cindex loops, breaking out of
-+ at cindex breaking out of loops
-+You can use the @code{.EXITM} preprocessor directive to break out of
-+loops early (as well as to break out of macros). @xref{Macros,,
-+Defining your own directives}.
-+
-+ at node Variables
-+ at section Preprocessor variables
-+
-+You can use variables in @sc{gasp} to represent strings, registers, or
-+the results of expressions.
-+
-+You must distinguish two kinds of variables:
-+ at enumerate
-+ at item
-+Variables defined with @code{.EQU} or @code{.ASSIGN}. To evaluate this
-+kind of variable in your assembly output, simply mention its name. For
-+example, these two lines define and use a variable @samp{eg}:
-+
-+ at cartouche
-+ at example
-+eg .EQU FLIP-64
-+ @dots{}
-+ mov.l eg,r0
-+ at end example
-+ at end cartouche
-+
-+ at emph{Do not use} this kind of variable in conditional expressions or
-+while loops; @sc{gasp} only evaluates these variables when writing
-+assembly output.
-+
-+ at item
-+Variables for use during preprocessing. You can define these
-+with @code{.ASSIGNC} or @code{.ASSIGNA}. To evaluate this
-+kind of variable, write @samp{\&} before the variable name; for example,
-+
-+ at cartouche
-+ at example
-+opcit .ASSIGNA 47
-+ @dots{}
-+ .AWHILE \&opcit GT 0
-+ @dots{}
-+ .AENDW
-+ at end example
-+ at end cartouche
-+
-+ at sc{gasp} treats macro arguments almost the same way, but to evaluate
-+them you use the prefix @samp{\} rather than @samp{\&}.
-+ at xref{Macros,, Defining your own directives}.
-+ at end enumerate
-+
-+ at ftable @code
-+ at item @var{pvar} .EQU @var{expr}
-+ at c FIXME! Anything to beware of re GAS directive of same name?
-+Assign preprocessor variable @var{pvar} the value of the expression
-+ at var{expr}. There are no restrictions on redefinition; use @samp{.EQU}
-+with the same @var{pvar} as often as you find it convenient.
-+
-+ at item @var{pvar} .ASSIGN @var{expr}
-+Almost the same as @code{.EQU}, save that you may not redefine
-+ at var{pvar} using @code{.ASSIGN} once it has a value.
-+ at c FIXME!! Supposed to work this way, apparently, but on 9feb94 works
-+ at c just like .EQU
-+
-+ at item @var{pvar} .ASSIGNA @var{aexpr}
-+Define a variable with a numeric value, for use during preprocessing.
-+ at var{aexpr} must be an absolute expression. You can redefine variables
-+with @code{.ASSIGNA} at any time.
-+
-+ at item @var{pvar} .ASSIGNC "@var{str}"
-+Define a variable with a string value, for use during preprocessing.
-+You can redefine variables with @code{.ASSIGNC} at any time.
-+
-+ at item @var{pvar} .REG (@var{register})
-+Use @code{.REG} to define a variable that represents a register. In
-+particular, @var{register} is @emph{not evaluated} as an expression.
-+You may use @code{.REG} at will to redefine register variables.
-+ at end ftable
-+
-+All these directives accept the variable name in the ``label'' position,
-+that is at the left margin. You may specify a colon after the variable
-+name if you wish; the first example above could have started @samp{eg:}
-+with the same effect.
-+
-+ at c pagebreak makes for better aesthetics---ensures macro and expansion together
-+ at page
-+ at node Macros
-+ at section Defining your own directives
-+
-+The commands @code{.MACRO} and @code{.ENDM} allow you to define macros
-+that generate assembly output. You can use these macros with a syntax
-+similar to built-in @sc{gasp} or assembler directives. For example,
-+this definition specifies a macro @code{SUM} that adds together a range of
-+consecutive registers:
-+
-+ at cartouche
-+ at example
-+ .MACRO SUM FROM=0, TO=9
-+ ! \FROM \TO
-+ mov r\FROM,r10
-+COUNT .ASSIGNA \FROM+1
-+ .AWHILE \&COUNT LE \TO
-+ add r\&COUNT,r10
-+COUNT .ASSIGNA \&COUNT+1
-+ .AENDW
-+ .ENDM
-+ at end example
-+ at end cartouche
-+
-+ at noindent
-+With that definition, @samp{SUM 0,5} generates this assembly output:
-+
-+ at cartouche
-+ at example
-+ ! 0 5
-+ mov r0,r10
-+ add r1,r10
-+ add r2,r10
-+ add r3,r10
-+ add r4,r10
-+ add r5,r10
-+ at end example
-+ at end cartouche
-+
-+ at ftable @code
-+ at item .MACRO @var{macname}
-+ at itemx .MACRO @var{macname} @var{macargs} @dots{}
-+Begin the definition of a macro called @var{macname}. If your macro
-+definition requires arguments, specify their names after the macro name,
-+separated by commas or spaces. You can supply a default value for any
-+macro argument by following the name with @samp{=@var{deflt}}. For
-+example, these are all valid @code{.MACRO} statements:
-+
-+ at table @code
-+ at item .MACRO COMM
-+Begin the definition of a macro called @code{COMM}, which takes no
-+arguments.
-+
-+ at item .MACRO PLUS1 P, P1
-+ at itemx .MACRO PLUS1 P P1
-+Either statement begins the definition of a macro called @code{PLUS1},
-+which takes two arguments; within the macro definition, write
-+ at samp{\P} or @samp{\P1} to evaluate the arguments.
-+
-+ at item .MACRO RESERVE_STR P1=0 P2
-+Begin the definition of a macro called @code{RESERVE_STR}, with two
-+arguments. The first argument has a default value, but not the second.
-+After the definition is complete, you can call the macro either as
-+ at samp{RESERVE_STR @var{a}, at var{b}} (with @samp{\P1} evaluating to
-+ at var{a} and @samp{\P2} evaluating to @var{b}), or as @samp{RESERVE_STR
-+, at var{b}} (with @samp{\P1} evaluating as the default, in this case
-+ at samp{0}, and @samp{\P2} evaluating to @var{b}).
-+ at end table
-+
-+When you call a macro, you can specify the argument values either by
-+position, or by keyword. For example, @samp{SUM 9,17} is equivalent to
-+ at samp{SUM TO=17, FROM=9}. Macro arguments are preprocessor variables
-+similar to the variables you define with @samp{.ASSIGNA} or
-+ at samp{.ASSIGNC}; in particular, you can use them in conditionals or for
-+loop control. (The only difference is the prefix you write to evaluate
-+the variable: for a macro argument, write @samp{\@var{argname}}, but for
-+a preprocessor variable, write @samp{\&@var{varname}}.)
-+
-+ at item @var{name} .MACRO
-+ at itemx @var{name} .MACRO ( @var{macargs} @dots{} )
-+ at c FIXME check: I think no error _and_ no args recognized if I use form
-+ at c NAME .MACRO ARG ARG
-+An alternative form of introducing a macro definition: specify the macro
-+name in the label position, and the arguments (if any) between
-+parentheses after the name. Defaulting rules and usage work the same
-+way as for the other macro definition syntax.
-+
-+ at item .ENDM
-+Mark the end of a macro definition.
-+
-+ at item .EXITM
-+Exit early from the current macro definition, @code{.AREPEAT} loop, or
-+ at code{.AWHILE} loop.
-+
-+ at cindex number of macros executed
-+ at cindex macros, count executed
-+ at item \@@
-+ at sc{gasp} maintains a counter of how many macros it has
-+executed in this pseudo-variable; you can copy that number to your
-+output with @samp{\@@}, but @emph{only within a macro definition}.
-+
-+ at item LOCAL @var{name} [ , @dots{} ]
-+ at emph{Warning: @code{LOCAL} is only available if you select ``alternate
-+macro syntax'' with @samp{-a} or @samp{--alternate}.} @xref{Alternate,,
-+Alternate macro syntax}.
-+
-+Generate a string replacement for each of the @var{name} arguments, and
-+replace any instances of @var{name} in each macro expansion. The
-+replacement string is unique in the assembly, and different for each
-+separate macro expansion. @code{LOCAL} allows you to write macros that
-+define symbols, without fear of conflict between separate macro expansions.
-+ at end ftable
-+
-+ at node Data
-+ at section Data output
-+
-+In assembly code, you often need to specify working areas of memory;
-+depending on the application, you may want to initialize such memory or
-+not. @sc{gasp} provides preprocessor directives to help you avoid
-+repetitive coding for both purposes.
-+
-+You can use labels as usual to mark the data areas.
-+
-+ at menu
-+* Initialized::
-+* Uninitialized::
-+ at end menu
-+
-+ at node Initialized
-+ at subsection Initialized data
-+
-+These are the @sc{gasp} directives for initialized data, and the standard
-+ at sc{gnu} assembler directives they expand to:
-+
-+ at ftable @code
-+ at item .DATA @var{expr}, @var{expr}, @dots{}
-+ at itemx .DATA.B @var{expr}, @var{expr}, @dots{}
-+ at itemx .DATA.W @var{expr}, @var{expr}, @dots{}
-+ at itemx .DATA.L @var{expr}, @var{expr}, @dots{}
-+Evaluate arithmetic expressions @var{expr}, and emit the corresponding
-+ at code{as} directive (labelled with @var{lab}). The unqualified
-+ at code{.DATA} emits @samp{.long}; @code{.DATA.B} emits @samp{.byte};
-+ at code{.DATA.W} emits @samp{.short}; and @code{.DATA.L} emits
-+ at samp{.long}.
-+
-+For example, @samp{foo .DATA 1,2,3} emits @samp{foo: .long 1,2,3}.
-+
-+ at item .DATAB @var{repeat}, @var{expr}
-+ at itemx .DATAB.B @var{repeat}, @var{expr}
-+ at itemx .DATAB.W @var{repeat}, @var{expr}
-+ at itemx .DATAB.L @var{repeat}, @var{expr}
-+ at c FIXME! Looks like gasp accepts and ignores args after 2nd.
-+Make @code{as} emit @var{repeat} copies of the value of the expression
-+ at var{expr} (using the @code{as} directive @code{.fill}).
-+ at samp{.DATAB.B} repeats one-byte values; @samp{.DATAB.W} repeats
-+two-byte values; and @samp{.DATAB.L} repeats four-byte values.
-+ at samp{.DATAB} without a suffix repeats four-byte values, just like
-+ at samp{.DATAB.L}.
-+
-+ at c FIXME! Allowing zero might be useful for edge conditions in macros.
-+ at var{repeat} must be an absolute expression with a positive value.
-+
-+ at item .SDATA "@var{str}" @dots{}
-+String data. Emits a concatenation of bytes, precisely as you specify
-+them (in particular, @emph{nothing is added to mark the end} of the
-+string). @xref{Constants,, String and numeric constants}, for details
-+about how to write strings. @code{.SDATA} concatenates multiple
-+arguments, making it easy to switch between string representations. You
-+can use commas to separate the individual arguments for clarity, if you
-+choose.
-+
-+ at item .SDATAB @var{repeat}, "@var{str}" @dots{}
-+Repeated string data. The first argument specifies how many copies of
-+the string to emit; the remaining arguments specify the string, in the
-+same way as the arguments to @code{.SDATA}.
-+
-+ at item .SDATAZ "@var{str}" @dots{}
-+Zero-terminated string data. Just like @code{.SDATA}, except that
-+ at code{.SDATAZ} writes a zero byte at the end of the string.
-+
-+ at item .SDATAC "@var{str}" @dots{}
-+Count-prefixed string data. Just like @code{.SDATA}, except that
-+ at sc{gasp} precedes the string with a leading one-byte count. For
-+example, @samp{.SDATAC "HI"} generates @samp{.byte 2,72,73}. Since the
-+count field is only one byte, you can only use @code{.SDATAC} for
-+strings less than 256 bytes in length.
-+ at end ftable
-+
-+ at node Uninitialized
-+ at subsection Uninitialized data
-+
-+ at c FIXME! .space different on some platforms, notably HPPA. Config?
-+Use the @code{.RES}, @code{.SRES}, @code{.SRESC}, and @code{.SRESZ}
-+directives to reserve memory and leave it uninitialized. @sc{gasp}
-+resolves these directives to appropriate calls of the @sc{gnu}
-+ at code{as} @code{.space} directive.
-+
-+ at ftable @code
-+ at item .RES @var{count}
-+ at itemx .RES.B @var{count}
-+ at itemx .RES.W @var{count}
-+ at itemx .RES.L @var{count}
-+Reserve room for @var{count} uninitialized elements of data. The
-+suffix specifies the size of each element: @code{.RES.B} reserves
-+ at var{count} bytes, @code{.RES.W} reserves @var{count} pairs of bytes,
-+and @code{.RES.L} reserves @var{count} quartets. @code{.RES} without a
-+suffix is equivalent to @code{.RES.L}.
-+
-+ at item .SRES @var{count}
-+ at itemx .SRES.B @var{count}
-+ at itemx .SRES.W @var{count}
-+ at itemx .SRES.L @var{count}
-+ at c FIXME! This is boring. Shouldn't it at least have a different
-+ at c default size? (e.g. the "S" suggests "string", for which .B
-+ at c would be more appropriate)
-+ at code{.SRES} is a synonym for @samp{.RES}.
-+
-+ at item .SRESC @var{count}
-+ at itemx .SRESC.B @var{count}
-+ at itemx .SRESC.W @var{count}
-+ at itemx .SRESC.L @var{count}
-+Like @code{.SRES}, but reserves space for @code{@var{count}+1} elements.
-+
-+ at item .SRESZ @var{count}
-+ at itemx .SRESZ.B @var{count}
-+ at itemx .SRESZ.W @var{count}
-+ at itemx .SRESZ.L @var{count}
-+Like @code{.SRES}, but reserves space for @code{@var{count}+1} elements.
-+ at end ftable
-+
-+ at node Listings
-+ at section Assembly listing control
-+
-+The @sc{gasp} listing-control directives correspond to
-+related @sc{gnu} @code{as} directives.
-+
-+ at ftable @code
-+ at item .PRINT LIST
-+ at itemx .PRINT NOLIST
-+Print control. This directive emits the @sc{gnu} @code{as} directive
-+ at code{.list} or @code{.nolist}, according to its argument. @xref{List,,
-+ at code{.list}, as.info, Using as}, for details on how these directives
-+interact.
-+
-+ at item .FORM LIN=@var{ln}
-+ at itemx .FORM COL=@var{cols}
-+ at itemx .FORM LIN=@var{ln} COL=@var{cols}
-+Specify the page size for assembly listings: @var{ln} represents the
-+number of lines, and @var{cols} the number of columns. You may specify
-+either page dimension independently, or both together. If you do not
-+specify the number of lines, @sc{gasp} assumes 60 lines; if you do not
-+specify the number of columns, @sc{gasp} assumes 132 columns.
-+(Any values you may have specified in previous instances of @code{.FORM}
-+do @emph{not} carry over as defaults.) Emits the @code{.psize}
-+assembler directive.
-+
-+ at item .HEADING @var{string}
-+Specify @var{string} as the title of your assembly listings. Emits
-+ at samp{.title "@var{string}"}.
-+
-+ at item .PAGE
-+Force a new page in assembly listings. Emits @samp{.eject}.
-+ at end ftable
-+
-+ at node Other Commands
-+ at section Miscellaneous commands
-+
-+ at ftable @code
-+ at item .ALTERNATE
-+Use the alternate macro syntax henceforth in the assembly.
-+ at xref{Alternate,, Alternate macro syntax}.
-+
-+ at item .ORG
-+ at c FIXME! This is very strange, since _GAS_ understands .org
-+This command is recognized, but not yet implemented. @sc{gasp}
-+generates an error message for programs that use @code{.ORG}.
-+
-+ at item .RADIX @var{s}
-+ at c FIXME no test cases in testsuite/gasp
-+ at sc{gasp} understands numbers in any of base two, eight, ten, or
-+sixteen. You can encode the base explicitly in any numeric constant
-+(@pxref{Constants,, String and numeric constants}). If you write
-+numbers without an explicit indication of the base, the most recent
-+ at samp{.RADIX @var{s}} command determines how they are interpreted.
-+ at var{s} is a single letter, one of the following:
-+
-+ at table @code
-+ at item .RADIX B
-+Base 2.
-+
-+ at item .RADIX Q
-+Base 8.
-+
-+ at item .RADIX D
-+Base 10. This is the original default radix.
-+
-+ at item .RADIX H
-+Base 16.
-+ at end table
-+
-+You may specify the argument @var{s} in lower case (any of @samp{bqdh})
-+with the same effects.
-+
-+ at item .EXPORT @var{name}
-+ at itemx .GLOBAL @var{name}
-+ at c FIXME! No test cases in testsuite/gasp
-+Declare @var{name} global (emits @samp{.global @var{name}}). The two
-+directives are synonymous.
-+
-+ at item .PROGRAM
-+No effect: @sc{gasp} accepts this directive, and silently ignores it.
-+
-+ at item .END
-+Mark end of each preprocessor file. @sc{gasp} issues a warning if it
-+reaches end of file without seeing this command.
-+
-+ at item .INCLUDE "@var{str}"
-+Preprocess the file named by @var{str}, as if its contents appeared
-+where the @code{.INCLUDE} directive does. @sc{gasp} imposes a maximum
-+limit of 30 stacked include files, as a sanity check.
-+ at c FIXME! Why is include depth not affected by -u?
-+
-+ at item .ALIGN @var{size}
-+ at c FIXME! Why is this not utterly pointless?
-+Evaluate the absolute expression @var{size}, and emit the assembly
-+instruction @samp{.align @var{size}} using the result.
-+ at end ftable
-+
-+ at node Syntax Details
-+ at section Details of the GASP syntax
-+
-+Since @sc{gasp} is meant to work with assembly code, its statement
-+syntax has no surprises for the assembly programmer.
-+
-+ at cindex whitespace
-+ at emph{Whitespace} (blanks or tabs; @emph{not} newline) is partially
-+significant, in that it delimits up to three fields in a line. The
-+amount of whitespace does not matter; you may line up fields in separate
-+lines if you wish, but @sc{gasp} does not require that.
-+
-+ at cindex fields of @sc{gasp} source line
-+ at cindex label field
-+The @emph{first field}, an optional @dfn{label}, must be flush left in a
-+line (with no leading whitespace) if it appears at all. You may use a
-+colon after the label if you wish; @sc{gasp} neither requires the colon
-+nor objects to it (but will not include it as part of the label name).
-+
-+ at cindex directive field
-+The @emph{second field}, which must appear after some whitespace,
-+contains a @sc{gasp} or assembly @dfn{directive}.
-+
-+ at cindex argument fields
-+Any @emph{further fields} on a line are @dfn{arguments} to the
-+directive; you can separate them from one another using either commas or
-+whitespace.
-+
-+ at menu
-+* Markers::
-+* Constants::
-+* Symbols::
-+* Expressions::
-+* String Builtins::
-+ at end menu
-+
-+ at node Markers
-+ at subsection Special syntactic markers
-+
-+ at sc{gasp} recognizes a few special markers: to delimit comments, to
-+continue a statement on the next line, to separate symbols from other
-+characters, and to copy text to the output literally. (One other
-+special marker, @samp{\@@}, works only within macro definitions;
-+ at pxref{Macros,, Defining your own directives}.)
-+
-+ at cindex comments
-+The trailing part of any @sc{gasp} source line may be a @dfn{comment}.
-+A comment begins with the first unquoted comment character (@samp{!} by
-+default), or an escaped or doubled comment character (@samp{\!} or
-+ at samp{!!} by default), and extends to the end of a line. You can
-+specify what comment character to use with the @samp{-c} option
-+(@pxref{Invoking GASP,, Command Line Options}). The two kinds of
-+comment markers lead to slightly different treatment:
-+
-+ at table @code
-+ at item !
-+A single, un-escaped comment character generates an assembly comment in
-+the @sc{gasp} output. @sc{gasp} evaluates any preprocessor variables
-+(macro arguments, or variables defined with @code{.ASSIGNA} or
-+ at code{.ASSIGNC}) present. For example, a macro that begins like this
-+
-+ at example
-+ .MACRO SUM FROM=0, TO=9
-+ ! \FROM \TO
-+ at end example
-+
-+ at noindent
-+issues as the first line of output a comment that records the
-+values you used to call the macro.
-+
-+ at c comments, preprocessor-only
-+ at c preprocessor-only comments
-+ at c GASP-only comments
-+ at item \!
-+ at itemx !!
-+Either an escaped comment character, or a double comment character,
-+marks a @sc{gasp} source comment. @sc{gasp} does not copy such comments
-+to the assembly output.
-+ at end table
-+
-+ at cindex continuation character
-+ at kindex +
-+To @emph{continue a statement} on the next line of the file, begin the
-+second line with the character @samp{+}.
-+
-+ at cindex literal copy to output
-+ at cindex copying literally to output
-+ at cindex preprocessing, avoiding
-+ at cindex avoiding preprocessing
-+Occasionally you may want to prevent @sc{gasp} from preprocessing some
-+particular bit of text. To @emph{copy literally} from the @sc{gasp}
-+source to its output, place @samp{\(} before the string to copy, and
-+ at samp{)} at the end. For example, write @samp{\(\!)} if you need the
-+characters @samp{\!} in your assembly output.
-+
-+ at cindex symbol separator
-+ at cindex text, separating from symbols
-+ at cindex symbols, separating from text
-+To @emph{separate a preprocessor variable} from text to appear
-+immediately after its value, write a single quote (@code{'}). For
-+example, @samp{.SDATA "\P'1"} writes a string built by concatenating the
-+value of @code{P} and the digit @samp{1}. (You cannot achieve this by
-+writing just @samp{\P1}, since @samp{P1} is itself a valid name for a
-+preprocessor variable.)
-+
-+ at node Constants
-+ at subsection String and numeric constants
-+
-+There are two ways of writing @dfn{string constants} in @sc{gasp}: as
-+literal text, and by numeric byte value. Specify a string literal
-+between double quotes (@code{"@var{str}"}). Specify an individual
-+numeric byte value as an absolute expression between angle brackets
-+(@code{<@var{expr}>}. Directives that output strings allow you to
-+specify any number of either kind of value, in whatever order is
-+convenient, and concatenate the result. (Alternate syntax mode
-+introduces a number of alternative string notations; @pxref{Alternate,,
-+Alternate macro syntax}.)
-+
-+ at c Details of numeric notation, e.g. base prefixes
-+You can write @dfn{numeric constants} either in a specific base, or in
-+whatever base is currently selected (either 10, or selected by the most
-+recent @code{.RADIX}).
-+
-+To write a number in a @emph{specific base}, use the pattern
-+ at code{@var{s}'@var{ddd}}: a base specifier character @var{s}, followed
-+by a single quote followed by digits @var{ddd}. The base specifier
-+character matches those you can specify with @code{.RADIX}: @samp{B} for
-+base 2, @samp{Q} for base 8, @samp{D} for base 10, and @samp{H} for base
-+16. (You can write this character in lower case if you prefer.)
-+
-+You can write floating point constants using the same syntax recognised
-+by GAS @ref{Flonums,,Flonums,as,The GNU Assembler.}. A constraint is
-+that these constants will be interpreted as decimal values irrespective
-+of the currently selected base.
-+
-+ at c FIXME! What are rules for recognizing number in deflt base? Whatever
-+ at c is left over after parsing other things??
-+
-+ at node Symbols
-+ at subsection Symbols
-+
-+ at sc{gasp} recognizes symbol names that start with any alphabetic character,
-+ at samp{_}, or @samp{$}, and continue with any of the same characters or
-+with digits. Label names follow the same rules.
-+
-+ at node Expressions
-+ at subsection Arithmetic expressions in GASP
-+
-+ at cindex absolute expressions
-+ at cindex relocatable expressions
-+There are two kinds of expressions, depending on their result:
-+ at dfn{absolute} expressions, which resolve to a constant (that is, they
-+do not involve any values unknown to @sc{gasp}), and @dfn{relocatable}
-+expressions, which must reduce to the form
-+
-+ at example
-+ at var{addsym}+ at var{const}- at var{subsym}
-+ at end example
-+
-+ at noindent
-+where @var{addsym} and @var{subsym} are assembly symbols of unknown
-+value, and @var{const} is a constant.
-+
-+Arithmetic for @sc{gasp} expressions follows very similar rules to C.
-+You can use parentheses to change precedence; otherwise, arithmetic
-+primitives have decreasing precedence in the order of the following
-+list.
-+
-+ at enumerate
-+ at item
-+Single-argument @code{+} (identity), @code{-} (arithmetic opposite), or
-+ at code{~} (bitwise negation). @emph{The argument must be an absolute
-+expression.}
-+
-+ at item
-+ at code{*} (multiplication) and @code{/} (division). @emph{Both arguments
-+must be absolute expressions.}
-+
-+ at item
-+ at code{+} (addition) and @code{-} (subtraction). @emph{At least one argument
-+must be absolute.}
-+ at c FIXME! Actually, subtraction doesn't check for this.
-+
-+ at item
-+ at code{&} (bitwise and). @emph{Both arguments must be absolute.}
-+
-+ at item
-+ at c FIXME! I agree ~ is a better notation than ^ for xor, but is the
-+ at c improvement worth differing from C?
-+ at code{|} (bitwise or) and @code{~} (bitwise exclusive or; @code{^} in
-+C). @emph{Both arguments must be absolute.}
-+ at end enumerate
-+
-+ at node String Builtins
-+ at subsection String primitives
-+
-+You can use these primitives to manipulate strings (in the argument
-+field of @sc{gasp} statements):
-+
-+ at ftable @code
-+ at item .LEN("@var{str}")
-+Calculate the length of string @code{"@var{str}"}, as an absolute
-+expression. For example, @samp{.RES.B .LEN("sample")} reserves six
-+bytes of memory.
-+
-+ at item .INSTR("@var{string}", "@var{seg}", @var{ix})
-+Search for the first occurrence of @var{seg} after position @var{ix} of
-+ at var{string}. For example, @samp{.INSTR("ABCDEFG", "CDE", 0)} evaluates
-+to the absolute result @code{2}.
-+
-+The result is @code{-1} if @var{seg} does not occur in @var{string}
-+after position @var{ix}.
-+
-+ at item .SUBSTR("@var{string}", at var{start}, at var{len})
-+The substring of @var{string} beginning at byte number @var{start} and
-+extending for @var{len} bytes.
-+ at end ftable
-+
-+ at node Alternate
-+ at section Alternate macro syntax
-+
-+If you specify @samp{-a} or @samp{--alternate} on the @sc{gasp} command
-+line, the preprocessor uses somewhat different syntax. This syntax is
-+reminiscent of the syntax of Phar Lap macro assembler, but it
-+is @emph{not} meant to be a full emulation of Phar Lap or similar
-+assemblers. In particular, @sc{gasp} does not support directives such
-+as @code{DB} and @code{IRP}, even in alternate syntax mode.
-+
-+In particular, @samp{-a} (or @samp{--alternate}) elicits these
-+differences:
-+
-+ at table @emph
-+ at item Preprocessor directives
-+You can use @sc{gasp} preprocessor directives without a leading @samp{.}
-+dot. For example, you can write @samp{SDATA} with the same effect as
-+ at samp{.SDATA}.
-+
-+ at item LOCAL
-+One additional directive, @code{LOCAL}, is available. @xref{Macros,,
-+Defining your own directives}, for an explanation of how to use
-+ at code{LOCAL}.
-+
-+ at need 2000
-+ at item String delimiters
-+You can write strings delimited in these other ways besides
-+ at code{"@var{string}"}:
-+
-+ at table @code
-+ at item '@var{string}'
-+You can delimit strings with single-quote charaters.
-+
-+ at item <@var{string}>
-+You can delimit strings with matching angle brackets.
-+ at end table
-+
-+ at item single-character string escape
-+To include any single character literally in a string (even if the
-+character would otherwise have some special meaning), you can prefix the
-+character with @samp{!} (an exclamation mark). For example, you can
-+write @samp{<4.3 !> 5.4!!>} to get the literal text @samp{4.3 > 5.4!}.
-+
-+ at item Expression results as strings
-+You can write @samp{%@var{expr}} to evaluate the expression @var{expr}
-+and use the result as a string.
-+ at end table
-+
-+ at node GNU Free Documentation License
-+ at chapter GNU Free Documentation License
-+
-+ GNU Free Documentation License
-+
-+ Version 1.1, March 2000
-+
-+ Copyright (C) 2000 Free Software Foundation, Inc.
-+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+
-+ Everyone is permitted to copy and distribute verbatim copies
-+ of this license document, but changing it is not allowed.
-+
-+
-+0. PREAMBLE
-+
-+The purpose of this License is to make a manual, textbook, or other
-+written document "free" in the sense of freedom: to assure everyone
-+the effective freedom to copy and redistribute it, with or without
-+modifying it, either commercially or noncommercially. Secondarily,
-+this License preserves for the author and publisher a way to get
-+credit for their work, while not being considered responsible for
-+modifications made by others.
-+
-+This License is a kind of "copyleft", which means that derivative
-+works of the document must themselves be free in the same sense. It
-+complements the GNU General Public License, which is a copyleft
-+license designed for free software.
-+
-+We have designed this License in order to use it for manuals for free
-+software, because free software needs free documentation: a free
-+program should come with manuals providing the same freedoms that the
-+software does. But this License is not limited to software manuals;
-+it can be used for any textual work, regardless of subject matter or
-+whether it is published as a printed book. We recommend this License
-+principally for works whose purpose is instruction or reference.
-+
-+
-+1. APPLICABILITY AND DEFINITIONS
-+
-+This License applies to any manual or other work that contains a
-+notice placed by the copyright holder saying it can be distributed
-+under the terms of this License. The "Document", below, refers to any
-+such manual or work. Any member of the public is a licensee, and is
-+addressed as "you".
-+
-+A "Modified Version" of the Document means any work containing the
-+Document or a portion of it, either copied verbatim, or with
-+modifications and/or translated into another language.
-+
-+A "Secondary Section" is a named appendix or a front-matter section of
-+the Document that deals exclusively with the relationship of the
-+publishers or authors of the Document to the Document's overall subject
-+(or to related matters) and contains nothing that could fall directly
-+within that overall subject. (For example, if the Document is in part a
-+textbook of mathematics, a Secondary Section may not explain any
-+mathematics.) The relationship could be a matter of historical
-+connection with the subject or with related matters, or of legal,
-+commercial, philosophical, ethical or political position regarding
-+them.
-+
-+The "Invariant Sections" are certain Secondary Sections whose titles
-+are designated, as being those of Invariant Sections, in the notice
-+that says that the Document is released under this License.
-+
-+The "Cover Texts" are certain short passages of text that are listed,
-+as Front-Cover Texts or Back-Cover Texts, in the notice that says that
-+the Document is released under this License.
-+
-+A "Transparent" copy of the Document means a machine-readable copy,
-+represented in a format whose specification is available to the
-+general public, whose contents can be viewed and edited directly and
-+straightforwardly with generic text editors or (for images composed of
-+pixels) generic paint programs or (for drawings) some widely available
-+drawing editor, and that is suitable for input to text formatters or
-+for automatic translation to a variety of formats suitable for input
-+to text formatters. A copy made in an otherwise Transparent file
-+format whose markup has been designed to thwart or discourage
-+subsequent modification by readers is not Transparent. A copy that is
-+not "Transparent" is called "Opaque".
-+
-+Examples of suitable formats for Transparent copies include plain
-+ASCII without markup, Texinfo input format, LaTeX input format, SGML
-+or XML using a publicly available DTD, and standard-conforming simple
-+HTML designed for human modification. Opaque formats include
-+PostScript, PDF, proprietary formats that can be read and edited only
-+by proprietary word processors, SGML or XML for which the DTD and/or
-+processing tools are not generally available, and the
-+machine-generated HTML produced by some word processors for output
-+purposes only.
-+
-+The "Title Page" means, for a printed book, the title page itself,
-+plus such following pages as are needed to hold, legibly, the material
-+this License requires to appear in the title page. For works in
-+formats which do not have any title page as such, "Title Page" means
-+the text near the most prominent appearance of the work's title,
-+preceding the beginning of the body of the text.
-+
-+
-+2. VERBATIM COPYING
-+
-+You may copy and distribute the Document in any medium, either
-+commercially or noncommercially, provided that this License, the
-+copyright notices, and the license notice saying this License applies
-+to the Document are reproduced in all copies, and that you add no other
-+conditions whatsoever to those of this License. You may not use
-+technical measures to obstruct or control the reading or further
-+copying of the copies you make or distribute. However, you may accept
-+compensation in exchange for copies. If you distribute a large enough
-+number of copies you must also follow the conditions in section 3.
-+
-+You may also lend copies, under the same conditions stated above, and
-+you may publicly display copies.
-+
-+
-+3. COPYING IN QUANTITY
-+
-+If you publish printed copies of the Document numbering more than 100,
-+and the Document's license notice requires Cover Texts, you must enclose
-+the copies in covers that carry, clearly and legibly, all these Cover
-+Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on
-+the back cover. Both covers must also clearly and legibly identify
-+you as the publisher of these copies. The front cover must present
-+the full title with all words of the title equally prominent and
-+visible. You may add other material on the covers in addition.
-+Copying with changes limited to the covers, as long as they preserve
-+the title of the Document and satisfy these conditions, can be treated
-+as verbatim copying in other respects.
-+
-+If the required texts for either cover are too voluminous to fit
-+legibly, you should put the first ones listed (as many as fit
-+reasonably) on the actual cover, and continue the rest onto adjacent
-+pages.
-+
-+If you publish or distribute Opaque copies of the Document numbering
-+more than 100, you must either include a machine-readable Transparent
-+copy along with each Opaque copy, or state in or with each Opaque copy
-+a publicly-accessible computer-network location containing a complete
-+Transparent copy of the Document, free of added material, which the
-+general network-using public has access to download anonymously at no
-+charge using public-standard network protocols. If you use the latter
-+option, you must take reasonably prudent steps, when you begin
-+distribution of Opaque copies in quantity, to ensure that this
-+Transparent copy will remain thus accessible at the stated location
-+until at least one year after the last time you distribute an Opaque
-+copy (directly or through your agents or retailers) of that edition to
-+the public.
-+
-+It is requested, but not required, that you contact the authors of the
-+Document well before redistributing any large number of copies, to give
-+them a chance to provide you with an updated version of the Document.
-+
-+
-+4. MODIFICATIONS
-+
-+You may copy and distribute a Modified Version of the Document under
-+the conditions of sections 2 and 3 above, provided that you release
-+the Modified Version under precisely this License, with the Modified
-+Version filling the role of the Document, thus licensing distribution
-+and modification of the Modified Version to whoever possesses a copy
-+of it. In addition, you must do these things in the Modified Version:
-+
-+A. Use in the Title Page (and on the covers, if any) a title distinct
-+ from that of the Document, and from those of previous versions
-+ (which should, if there were any, be listed in the History section
-+ of the Document). You may use the same title as a previous version
-+ if the original publisher of that version gives permission.
-+B. List on the Title Page, as authors, one or more persons or entities
-+ responsible for authorship of the modifications in the Modified
-+ Version, together with at least five of the principal authors of the
-+ Document (all of its principal authors, if it has less than five).
-+C. State on the Title page the name of the publisher of the
-+ Modified Version, as the publisher.
-+D. Preserve all the copyright notices of the Document.
-+E. Add an appropriate copyright notice for your modifications
-+ adjacent to the other copyright notices.
-+F. Include, immediately after the copyright notices, a license notice
-+ giving the public permission to use the Modified Version under the
-+ terms of this License, in the form shown in the Addendum below.
-+G. Preserve in that license notice the full lists of Invariant Sections
-+ and required Cover Texts given in the Document's license notice.
-+H. Include an unaltered copy of this License.
-+I. Preserve the section entitled "History", and its title, and add to
-+ it an item stating at least the title, year, new authors, and
-+ publisher of the Modified Version as given on the Title Page. If
-+ there is no section entitled "History" in the Document, create one
-+ stating the title, year, authors, and publisher of the Document as
-+ given on its Title Page, then add an item describing the Modified
-+ Version as stated in the previous sentence.
-+J. Preserve the network location, if any, given in the Document for
-+ public access to a Transparent copy of the Document, and likewise
-+ the network locations given in the Document for previous versions
-+ it was based on. These may be placed in the "History" section.
-+ You may omit a network location for a work that was published at
-+ least four years before the Document itself, or if the original
-+ publisher of the version it refers to gives permission.
-+K. In any section entitled "Acknowledgements" or "Dedications",
-+ preserve the section's title, and preserve in the section all the
-+ substance and tone of each of the contributor acknowledgements
-+ and/or dedications given therein.
-+L. Preserve all the Invariant Sections of the Document,
-+ unaltered in their text and in their titles. Section numbers
-+ or the equivalent are not considered part of the section titles.
-+M. Delete any section entitled "Endorsements". Such a section
-+ may not be included in the Modified Version.
-+N. Do not retitle any existing section as "Endorsements"
-+ or to conflict in title with any Invariant Section.
-+
-+If the Modified Version includes new front-matter sections or
-+appendices that qualify as Secondary Sections and contain no material
-+copied from the Document, you may at your option designate some or all
-+of these sections as invariant. To do this, add their titles to the
-+list of Invariant Sections in the Modified Version's license notice.
-+These titles must be distinct from any other section titles.
-+
-+You may add a section entitled "Endorsements", provided it contains
-+nothing but endorsements of your Modified Version by various
-+parties--for example, statements of peer review or that the text has
-+been approved by an organization as the authoritative definition of a
-+standard.
-+
-+You may add a passage of up to five words as a Front-Cover Text, and a
-+passage of up to 25 words as a Back-Cover Text, to the end of the list
-+of Cover Texts in the Modified Version. Only one passage of
-+Front-Cover Text and one of Back-Cover Text may be added by (or
-+through arrangements made by) any one entity. If the Document already
-+includes a cover text for the same cover, previously added by you or
-+by arrangement made by the same entity you are acting on behalf of,
-+you may not add another; but you may replace the old one, on explicit
-+permission from the previous publisher that added the old one.
-+
-+The author(s) and publisher(s) of the Document do not by this License
-+give permission to use their names for publicity for or to assert or
-+imply endorsement of any Modified Version.
-+
-+
-+5. COMBINING DOCUMENTS
-+
-+You may combine the Document with other documents released under this
-+License, under the terms defined in section 4 above for modified
-+versions, provided that you include in the combination all of the
-+Invariant Sections of all of the original documents, unmodified, and
-+list them all as Invariant Sections of your combined work in its
-+license notice.
-+
-+The combined work need only contain one copy of this License, and
-+multiple identical Invariant Sections may be replaced with a single
-+copy. If there are multiple Invariant Sections with the same name but
-+different contents, make the title of each such section unique by
-+adding at the end of it, in parentheses, the name of the original
-+author or publisher of that section if known, or else a unique number.
-+Make the same adjustment to the section titles in the list of
-+Invariant Sections in the license notice of the combined work.
-+
-+In the combination, you must combine any sections entitled "History"
-+in the various original documents, forming one section entitled
-+"History"; likewise combine any sections entitled "Acknowledgements",
-+and any sections entitled "Dedications". You must delete all sections
-+entitled "Endorsements."
-+
-+
-+6. COLLECTIONS OF DOCUMENTS
-+
-+You may make a collection consisting of the Document and other documents
-+released under this License, and replace the individual copies of this
-+License in the various documents with a single copy that is included in
-+the collection, provided that you follow the rules of this License for
-+verbatim copying of each of the documents in all other respects.
-+
-+You may extract a single document from such a collection, and distribute
-+it individually under this License, provided you insert a copy of this
-+License into the extracted document, and follow this License in all
-+other respects regarding verbatim copying of that document.
-+
-+
-+7. AGGREGATION WITH INDEPENDENT WORKS
-+
-+A compilation of the Document or its derivatives with other separate
-+and independent documents or works, in or on a volume of a storage or
-+distribution medium, does not as a whole count as a Modified Version
-+of the Document, provided no compilation copyright is claimed for the
-+compilation. Such a compilation is called an "aggregate", and this
-+License does not apply to the other self-contained works thus compiled
-+with the Document, on account of their being thus compiled, if they
-+are not themselves derivative works of the Document.
-+
-+If the Cover Text requirement of section 3 is applicable to these
-+copies of the Document, then if the Document is less than one quarter
-+of the entire aggregate, the Document's Cover Texts may be placed on
-+covers that surround only the Document within the aggregate.
-+Otherwise they must appear on covers around the whole aggregate.
-+
-+
-+8. TRANSLATION
-+
-+Translation is considered a kind of modification, so you may
-+distribute translations of the Document under the terms of section 4.
-+Replacing Invariant Sections with translations requires special
-+permission from their copyright holders, but you may include
-+translations of some or all Invariant Sections in addition to the
-+original versions of these Invariant Sections. You may include a
-+translation of this License provided that you also include the
-+original English version of this License. In case of a disagreement
-+between the translation and the original English version of this
-+License, the original English version will prevail.
-+
-+
-+9. TERMINATION
-+
-+You may not copy, modify, sublicense, or distribute the Document except
-+as expressly provided for under this License. Any other attempt to
-+copy, modify, sublicense or distribute the Document is void, and will
-+automatically terminate your rights under this License. However,
-+parties who have received copies, or rights, from you under this
-+License will not have their licenses terminated so long as such
-+parties remain in full compliance.
-+
-+
-+10. FUTURE REVISIONS OF THIS LICENSE
-+
-+The Free Software Foundation may publish new, revised versions
-+of the GNU Free Documentation License from time to time. Such new
-+versions will be similar in spirit to the present version, but may
-+differ in detail to address new problems or concerns. See
-+http://www.gnu.org/copyleft/.
-+
-+Each version of the License is given a distinguishing version number.
-+If the Document specifies that a particular numbered version of this
-+License "or any later version" applies to it, you have the option of
-+following the terms and conditions either of that specified version or
-+of any later version that has been published (not as a draft) by the
-+Free Software Foundation. If the Document does not specify a version
-+number of this License, you may choose any version ever published (not
-+as a draft) by the Free Software Foundation.
-+
-+
-+ADDENDUM: How to use this License for your documents
-+
-+To use this License in a document you have written, include a copy of
-+the License in the document and put the following copyright and
-+license notices just after the title page:
-+
-+ at smallexample
-+ Copyright (c) YEAR YOUR NAME.
-+ Permission is granted to copy, distribute and/or modify this document
-+ under the terms of the GNU Free Documentation License, Version 1.1
-+ or any later version published by the Free Software Foundation;
-+ with the Invariant Sections being LIST THEIR TITLES, with the
-+ Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST.
-+ A copy of the license is included in the section entitled "GNU
-+ Free Documentation License".
-+ at end smallexample
-+
-+If you have no Invariant Sections, write "with no Invariant Sections"
-+instead of saying which ones are invariant. If you have no
-+Front-Cover Texts, write "no Front-Cover Texts" instead of
-+"Front-Cover Texts being LIST"; likewise for Back-Cover Texts.
-+
-+If your document contains nontrivial examples of program code, we
-+recommend releasing these examples in parallel under your choice of
-+free software license, such as the GNU General Public License,
-+to permit their use in free software.
-+
-+ at node Index
-+ at unnumbered Index
-+
-+ at printindex cp
-+
-+ at contents
-+ at bye
---- binutils-2.24.51.0.4/gas/gasp.c.orig 1970-01-01 01:00:00.000000000 +0100
-+++ binutils-2.24.51.0.4/gas/gasp.c 2014-10-12 11:32:34.014384388 +0200
-@@ -0,0 +1,4016 @@
-+/* gasp.c - Gnu assembler preprocessor main program.
-+ Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
-+ Free Software Foundation, Inc.
-+
-+ Written by Steve and Judy Chamberlain of Cygnus Support,
-+ sac at cygnus.com
-+
-+ This file is part of GASP, the GNU Assembler Preprocessor.
-+
-+ GASP is free software; you can redistribute it and/or modify
-+ it under the terms of the GNU General Public License as published by
-+ the Free Software Foundation; either version 2, or (at your option)
-+ any later version.
-+
-+ GASP is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ GNU General Public License for more details.
-+
-+ You should have received a copy of the GNU General Public License
-+ along with GASP; see the file COPYING. If not, write to the Free
-+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-+ 02111-1307, USA. */
-+
-+/*
-+This program translates the input macros and stuff into a form
-+suitable for gas to consume.
-+
-+ gasp [-sdhau] [-c char] [-o <outfile>] <infile>*
-+
-+ -s copy source to output
-+ -c <char> comments are started with <char> instead of !
-+ -u allow unreasonable stuff
-+ -p print line numbers
-+ -d print debugging stats
-+ -s semi colons start comments
-+ -a use alternate syntax
-+ Pseudo ops can start with or without a .
-+ Labels have to be in first column.
-+ -I specify include dir
-+ Macro arg parameters subsituted by name, don't need the &.
-+ String can start with ' too.
-+ Strings can be surrounded by <..>
-+ A %<exp> in a string evaluates the expression
-+ Literal char in a string with !
-+*/
-+
-+#include "config.h"
-+#include "bfdver.h"
-+
-+#include <assert.h>
-+#include <stdio.h>
-+#include <string.h>
-+#include "getopt.h"
-+
-+#ifdef HAVE_STDLIB_H
-+#include <stdlib.h>
-+#endif
-+
-+#ifdef NEED_MALLOC_DECLARATION
-+extern char *malloc ();
-+#endif
-+
-+#include "as.h"
-+#include "ansidecl.h"
-+#include "libiberty.h"
-+#include "safe-ctype.h"
-+#include "sb.h"
-+#include "macro.h"
-+#include "asintl.h"
-+#include "xregex.h"
-+
-+const char *program_version = "1.2";
-+
-+/* This is normally declared in as.h, but we don't include that. We
-+ need the function because other files linked with gasp.c might call
-+ it. */
-+extern void as_abort (const char *, int, const char *);
-+
-+/* The default obstack chunk size. If we set this to zero, the
-+ obstack code will use whatever will fit in a 4096 byte block. This
-+ is used by the hash table code used by macro.c. */
-+int chunksize = 0;
-+
-+#define MAX_INCLUDES 30 /* Maximum include depth. */
-+#define MAX_REASONABLE 1000 /* Maximum number of expansions. */
-+
-+int unreasonable; /* -u on command line. */
-+int stats; /* -d on command line. */
-+int print_line_number; /* -p flag on command line. */
-+int copysource; /* -c flag on command line. */
-+int warnings; /* Number of WARNINGs generated so far. */
-+int errors; /* Number of ERRORs generated so far. */
-+int fatals; /* Number of fatal ERRORs generated so far (either 0 or 1). */
-+int alternate = 0; /* -a on command line. */
-+int mri = 0; /* -M on command line. */
-+char comment_char = '!';
-+int radix = 10; /* Default radix. */
-+
-+int had_end; /* Seen .END. */
-+
-+/* The output stream. */
-+FILE *outfile;
-+
-+/* The attributes of each character are stored as a bit pattern
-+ chartype, which gives us quick tests. */
-+
-+#define FIRSTBIT 1
-+#define NEXTBIT 2
-+#define SEPBIT 4
-+#define WHITEBIT 8
-+#define COMMENTBIT 16
-+#define BASEBIT 32
-+#define ISCOMMENTCHAR(x) (chartype[(unsigned char)(x)] & COMMENTBIT)
-+#define ISFIRSTCHAR(x) (chartype[(unsigned char)(x)] & FIRSTBIT)
-+#define ISNEXTCHAR(x) (chartype[(unsigned char)(x)] & NEXTBIT)
-+#define ISSEP(x) (chartype[(unsigned char)(x)] & SEPBIT)
-+#define ISWHITE(x) (chartype[(unsigned char)(x)] & WHITEBIT)
-+#define ISBASE(x) (chartype[(unsigned char)(x)] & BASEBIT)
-+static char chartype[256];
-+
-+/* Conditional assembly uses the `ifstack'. Each aif pushes another
-+ entry onto the stack, and sets the on flag if it should. The aelse
-+ sets hadelse, and toggles on. An aend pops a level. We limit to
-+ 100 levels of nesting, not because we're facists pigs with read
-+ only minds, but because more than 100 levels of nesting is probably
-+ a bug in the user's macro structure. */
-+
-+#define IFNESTING 100
-+struct {
-+ int on; /* Is the level being output. */
-+ int hadelse; /* Has an aelse been seen. */
-+} ifstack[IFNESTING];
-+
-+int ifi;
-+
-+/* The final and intermediate results of expression evaluation are kept in
-+ exp_t's. Note that a symbol is not an sb, but a pointer into the input
-+ line. It must be coped somewhere safe before the next line is read in. */
-+
-+typedef struct {
-+ char *name;
-+ int len;
-+} symbol;
-+
-+typedef struct {
-+ int value; /* Constant part. */
-+ symbol add_symbol; /* Name part. */
-+ symbol sub_symbol; /* Name part. */
-+} exp_t;
-+
-+/* Hashing is done in a pretty standard way. A hash_table has a
-+ pointer to a vector of pointers to hash_entrys, and the size of the
-+ vector. A hash_entry contains a union of all the info we like to
-+ store in hash table. If there is a hash collision, hash_entries
-+ with the same hash are kept in a chain. */
-+
-+/* What the data in a hash_entry means. */
-+typedef enum {
-+ hash_integer, /* Name->integer mapping. */
-+ hash_string, /* Name->string mapping. */
-+ hash_macro, /* Name is a macro. */
-+ hash_formal /* Name is a formal argument. */
-+} hash_type;
-+
-+typedef struct hs {
-+ sb key; /* Symbol name. */
-+ hash_type type; /* Symbol meaning. */
-+ union {
-+ sb s;
-+ int i;
-+ struct macro_struct *m;
-+ struct formal_struct *f;
-+ } value;
-+ struct hs *next; /* Next hash_entry with same hash key. */
-+} hash_entry;
-+
-+typedef struct {
-+ hash_entry **table;
-+ int size;
-+} hash_table;
-+
-+/* How we nest files and expand macros etc.
-+
-+ We keep a stack of of include_stack structs. Each include file
-+ pushes a new level onto the stack. We keep an sb with a pushback
-+ too. unget chars are pushed onto the pushback sb, getchars first
-+ checks the pushback sb before reading from the input stream.
-+
-+ Small things are expanded by adding the text of the item onto the
-+ pushback sb. Larger items are grown by pushing a new level and
-+ allocating the entire pushback buf for the item. Each time
-+ something like a macro is expanded, the stack index is changed. We
-+ can then perform an exitm by popping all entries off the stack with
-+ the same stack index. If we're being reasonable, we can detect
-+ recusive expansion by checking the index is reasonably small. */
-+
-+typedef enum {
-+ include_file, include_repeat, include_while, include_macro
-+} include_type;
-+
-+struct include_stack {
-+ sb pushback; /* Current pushback stream. */
-+ int pushback_index; /* Next char to read from stream. */
-+ FILE *handle; /* Open file. */
-+ sb name; /* Name of file. */
-+ int linecount; /* Number of lines read so far. */
-+ include_type type;
-+ int index; /* Index of this layer. */
-+} include_stack[MAX_INCLUDES];
-+
-+struct include_stack *sp;
-+#define isp (sp - include_stack)
-+
-+/* Include file list. */
-+
-+typedef struct include_path {
-+ struct include_path *next;
-+ sb path;
-+} include_path;
-+
-+include_path *paths_head;
-+include_path *paths_tail;
-+
-+static void quit (void);
-+static void hash_new_table (int, hash_table *);
-+static int hash (sb *);
-+static hash_entry *hash_create (hash_table *, sb *);
-+static void hash_add_to_string_table (hash_table *, sb *, sb *, int);
-+static void hash_add_to_int_table (hash_table *, sb *, int);
-+static hash_entry *hash_lookup (hash_table *, sb *);
-+static void checkconst (int, exp_t *);
-+static int is_flonum (size_t, sb *);
-+static int chew_flonum (size_t, sb *, sb *);
-+static int sb_strtol (size_t, sb *, int, int *);
-+static int level_0 (size_t, sb *, exp_t *);
-+static int level_1 (size_t, sb *, exp_t *);
-+static int level_2 (size_t, sb *, exp_t *);
-+static int level_3 (size_t, sb *, exp_t *);
-+static int level_4 (size_t, sb *, exp_t *);
-+static int level_5 (size_t, sb *, exp_t *);
-+static int exp_parse (size_t, sb *, exp_t *);
-+static void exp_string (exp_t *, sb *);
-+static size_t exp_get_abs (const char *, size_t, sb *, offsetT *);
-+#if 0
-+static void strip_comments (sb *);
-+#endif
-+static void unget (int);
-+static void include_buf (sb *, sb *, include_type, int);
-+static void include_print_where_line (FILE *);
-+static void include_print_line (FILE *);
-+static size_t get_line (sb *);
-+static int grab_label (sb *, sb *);
-+static void change_base (size_t, sb *, sb *);
-+static void do_end (sb *);
-+static void do_assign (int, size_t, sb *);
-+static void do_radix (sb *);
-+static int get_opsize (size_t, sb *, int *);
-+static int eol (size_t, sb *);
-+static void do_data (size_t, sb *, int);
-+static void do_datab (size_t, sb *);
-+static void gasp_do_align (size_t, sb *);
-+static void do_res (size_t, sb *, int);
-+static void do_export (sb *);
-+static void do_print (size_t, sb *);
-+static void do_heading (size_t, sb *);
-+static void do_page (void);
-+static void do_form (size_t, sb *);
-+static int get_any_string (size_t, sb *, sb *, int, int);
-+static int skip_openp (size_t, sb *);
-+static int skip_closep (size_t, sb *);
-+static int dolen (size_t, sb *, sb *);
-+static int doinstr (size_t, sb *, sb *);
-+static int dosubstr (size_t, sb *, sb *);
-+static void process_assigns (size_t, sb *, sb *);
-+static int get_and_process (size_t, sb *, sb *);
-+static void process_file (void);
-+static void free_old_entry (hash_entry *);
-+static void do_assigna (size_t, sb *);
-+static void do_assignc (size_t, sb *);
-+static void do_reg (size_t, sb *);
-+static int condass_lookup_name (sb *, size_t, sb *, int);
-+static int whatcond (size_t, sb *, int *);
-+static int istrue (size_t, sb *);
-+static void do_aif (size_t, sb *);
-+static void do_aelse (void);
-+static void do_aendi (void);
-+static int condass_on (void);
-+static void do_if (size_t, sb *, int);
-+static int get_mri_string (size_t, sb *, sb *, int);
-+static void do_ifc (size_t, sb *, int);
-+static void do_aendr (void);
-+static void do_awhile (size_t, sb *);
-+static void do_aendw (void);
-+static void do_exitm (void);
-+static void do_arepeat (size_t, sb *);
-+static void do_endm (void);
-+static void do_irp (size_t, sb *, int);
-+static void do_local (size_t, sb *);
-+static void do_macro (size_t, sb *);
-+static int macro_op (size_t, sb *);
-+static int getstring (size_t, sb *, sb *);
-+static void do_sdata (size_t, sb *, int);
-+static void do_sdatab (size_t, sb *);
-+static int new_file (const char *);
-+static void do_include (size_t, sb *);
-+static void include_pop (void);
-+static int get (void);
-+static int linecount (void);
-+static int include_next_index (void);
-+static void chartype_init (void);
-+static int process_pseudo_op (size_t, sb *, sb *);
-+static void add_keyword (const char *, int);
-+static void process_init (void);
-+static void do_define (const char *);
-+static void show_usage (FILE *, int);
-+static void show_help (void);
-+
-+/* --- functions recently removed from sb.c --- */
-+
-+/* put a null at the end of the sb at in and return the start of the
-+ * string, so that it can be used as an arg to printf %s. */
-+
-+static char *
-+sb_name (sb *in)
-+{
-+ /* stick a null on the end of the string */
-+ sb_add_char (in, 0);
-+ return in->ptr;
-+}
-+
-+/* print the sb at ptr to the output file */
-+
-+static void
-+sb_print (FILE *outfileP, sb *ptr)
-+{
-+ size_t i;
-+ int nc = 0;
-+
-+ for (i = 0; i < ptr->len; i++)
-+ {
-+ if (nc)
-+ {
-+ fprintf (outfileP, ",");
-+ }
-+ fprintf (outfileP, "%d", ptr->ptr[i]);
-+ nc = 1;
-+ }
-+}
-+
-+/* print the sb at ptr to the output file */
-+
-+static void
-+sb_print_at (FILE *outfileP, size_t idx, sb *ptr)
-+{
-+ size_t i;
-+ for (i = idx; i < ptr->len; i++)
-+ putc (ptr->ptr[i], outfileP);
-+}
-+
-+#define FATAL(x) \
-+ do \
-+ { \
-+ include_print_where_line (stderr); \
-+ fprintf x; \
-+ fatals++; \
-+ quit (); \
-+ } \
-+ while (0)
-+
-+#define ERROR(x) \
-+ do \
-+ { \
-+ include_print_where_line (stderr); \
-+ fprintf x; \
-+ errors++; \
-+ } \
-+ while (0)
-+
-+#define WARNING(x) \
-+ do \
-+ { \
-+ include_print_where_line (stderr); \
-+ fprintf x; \
-+ warnings++; \
-+ } \
-+ while (0)
-+
-+/* Exit the program and return the right ERROR code. */
-+
-+static void
-+quit ()
-+{
-+ int exitcode;
-+ if (fatals + errors)
-+ exitcode = 1;
-+ else
-+ exitcode = 0;
-+
-+ exit (exitcode);
-+}
-+
-+/* Hash table maintenance. */
-+
-+/* Build a new hash table with size buckets
-+ and fill in the info at ptr. */
-+
-+static void
-+hash_new_table (size, ptr)
-+ int size;
-+ hash_table *ptr;
-+{
-+ int i;
-+ ptr->size = size;
-+ ptr->table = (hash_entry **) xmalloc (size * (sizeof (hash_entry *)));
-+ /* Fill with null-pointer, not zero-bit-pattern. */
-+ for (i = 0; i < size; i++)
-+ ptr->table[i] = 0;
-+}
-+
-+/* Calculate and return the hash value of the sb at key. */
-+
-+static int
-+hash (key)
-+ sb *key;
-+{
-+ int k = 0x1234;
-+ size_t i;
-+ char *p = key->ptr;
-+ for (i = 0; i < key->len; i++)
-+ {
-+ k ^= (k << 2) ^ *p;
-+ p++;
-+ }
-+ return k & 0xf0fff;
-+}
-+
-+/* Look up key in hash_table tab. If present, then return it,
-+ otherwise build a new one and fill it with hash_integer. */
-+
-+static hash_entry *
-+hash_create (tab, key)
-+ hash_table *tab;
-+ sb *key;
-+{
-+ int k = hash (key) % tab->size;
-+ hash_entry *p;
-+ hash_entry **table = tab->table;
-+
-+ p = table[k];
-+
-+ while (1)
-+ {
-+ if (!p)
-+ {
-+ hash_entry *n = (hash_entry *) xmalloc (sizeof (hash_entry));
-+ n->next = table[k];
-+ sb_new (&n->key);
-+ sb_add_sb (&n->key, key);
-+ table[k] = n;
-+ n->type = hash_integer;
-+ return n;
-+ }
-+ if (strncmp (table[k]->key.ptr, key->ptr, key->len) == 0)
-+ {
-+ return p;
-+ }
-+ p = p->next;
-+ }
-+}
-+
-+/* Add sb name with key into hash_table tab.
-+ If replacing old value and again, then ERROR. */
-+
-+static void
-+hash_add_to_string_table (tab, key, name, again)
-+ hash_table *tab;
-+ sb *key;
-+ sb *name;
-+ int again;
-+{
-+ hash_entry *ptr = hash_create (tab, key);
-+ if (ptr->type == hash_integer)
-+ {
-+ sb_new (&ptr->value.s);
-+ }
-+ if (ptr->value.s.len)
-+ {
-+ if (!again)
-+ ERROR ((stderr, _("redefinition not allowed\n")));
-+ }
-+
-+ ptr->type = hash_string;
-+ sb_reset (&ptr->value.s);
-+
-+ sb_add_sb (&ptr->value.s, name);
-+}
-+
-+/* Add integer name to hash_table tab with sb key. */
-+
-+static void
-+hash_add_to_int_table (tab, key, name)
-+ hash_table *tab;
-+ sb *key;
-+ int name;
-+{
-+ hash_entry *ptr = hash_create (tab, key);
-+ ptr->value.i = name;
-+}
-+
-+/* Look up sb key in hash_table tab.
-+ If found, return hash_entry result, else 0. */
-+
-+static hash_entry *
-+hash_lookup (tab, key)
-+ hash_table *tab;
-+ sb *key;
-+{
-+ int k = hash (key) % tab->size;
-+ hash_entry **table = tab->table;
-+ hash_entry *p = table[k];
-+ while (p)
-+ {
-+ if (p->key.len == key->len
-+ && strncmp (p->key.ptr, key->ptr, key->len) == 0)
-+ return p;
-+ p = p->next;
-+ }
-+ return 0;
-+}
-+
-+/* expressions
-+
-+ are handled in a really simple recursive decent way. each bit of
-+ the machine takes an index into an sb and a pointer to an exp_t,
-+ modifies the *exp_t and returns the index of the first character
-+ past the part of the expression parsed.
-+
-+ expression precedence:
-+ ( )
-+ unary + - ~
-+ * /
-+ + -
-+ &
-+ | ~
-+*/
-+
-+/* Make sure that the exp_t at term is constant.
-+ If not the give the op ERROR. */
-+
-+static void
-+checkconst (op, term)
-+ int op;
-+ exp_t *term;
-+{
-+ if (term->add_symbol.len
-+ || term->sub_symbol.len)
-+ {
-+ ERROR ((stderr, _("the %c operator cannot take non-absolute arguments.\n"), op));
-+ }
-+}
-+
-+/* Chew the flonum from the string starting at idx. Adjust idx to
-+ point to the next character after the flonum. */
-+
-+static int
-+chew_flonum (idx, string, out)
-+ size_t idx;
-+ sb *string;
-+ sb *out;
-+{
-+ sb buf;
-+ regex_t reg;
-+ regmatch_t match;
-+
-+ /* Duplicate and null terminate `string'. */
-+ sb_new (&buf);
-+ sb_add_sb (&buf, string);
-+ sb_add_char (&buf, '\0');
-+
-+ if (regcomp (®, "([0-9]*\\.[0-9]+([eE][+-]?[0-9]+)?)", REG_EXTENDED) != 0)
-+ return idx;
-+ if (regexec (®, &buf.ptr[idx], 1, &match, 0) != 0)
-+ return idx;
-+
-+ /* Copy the match to the output. */
-+ assert (match.rm_eo >= match.rm_so);
-+ sb_add_buffer (out, &buf.ptr[idx], match.rm_eo - match.rm_so);
-+
-+ sb_kill (&buf);
-+ regfree (®);
-+ idx += match.rm_eo;
-+ return idx;
-+}
-+
-+static int
-+is_flonum (idx, string)
-+ size_t idx;
-+ sb *string;
-+{
-+ sb buf;
-+ regex_t reg;
-+ int rc;
-+
-+ /* Duplicate and null terminate `string'. */
-+ sb_new (&buf);
-+ sb_add_sb (&buf, string);
-+ sb_add_char (&buf, '\0');
-+
-+ if (regcomp (®, "^[0-9]*\\.[0-9]+([eE][+-]?[0-9]+)?", REG_EXTENDED) != 0)
-+ return 0;
-+
-+ rc = regexec (®, &buf.ptr[idx], 0, NULL, 0);
-+ sb_kill (&buf);
-+ regfree (®);
-+ return (rc == 0);
-+}
-+
-+/* Turn the number in string at idx into a number of base, fill in
-+ ptr, and return the index of the first character not in the number. */
-+
-+static int
-+sb_strtol (idx, string, base, ptr)
-+ size_t idx;
-+ sb *string;
-+ int base;
-+ int *ptr;
-+{
-+ int value = 0;
-+ idx = sb_skip_white (idx, string);
-+
-+ while (idx < string->len)
-+ {
-+ int ch = string->ptr[idx];
-+ int dig = 0;
-+ if (ISDIGIT (ch))
-+ dig = ch - '0';
-+ else if (ch >= 'a' && ch <= 'f')
-+ dig = ch - 'a' + 10;
-+ else if (ch >= 'A' && ch <= 'F')
-+ dig = ch - 'A' + 10;
-+ else
-+ break;
-+
-+ if (dig >= base)
-+ break;
-+
-+ value = value * base + dig;
-+ idx++;
-+ }
-+ *ptr = value;
-+ return idx;
-+}
-+
-+static int
-+level_0 (idx, string, lhs)
-+ size_t idx;
-+ sb *string;
-+ exp_t *lhs;
-+{
-+ lhs->add_symbol.len = 0;
-+ lhs->add_symbol.name = 0;
-+
-+ lhs->sub_symbol.len = 0;
-+ lhs->sub_symbol.name = 0;
-+
-+ idx = sb_skip_white (idx, string);
-+
-+ lhs->value = 0;
-+
-+ if (ISDIGIT (string->ptr[idx]))
-+ {
-+ idx = sb_strtol (idx, string, 10, &lhs->value);
-+ }
-+ else if (ISFIRSTCHAR (string->ptr[idx]))
-+ {
-+ int len = 0;
-+ lhs->add_symbol.name = string->ptr + idx;
-+ while (idx < string->len && ISNEXTCHAR (string->ptr[idx]))
-+ {
-+ idx++;
-+ len++;
-+ }
-+ lhs->add_symbol.len = len;
-+ }
-+ else if (string->ptr[idx] == '"')
-+ {
-+ sb acc;
-+ sb_new (&acc);
-+ ERROR ((stderr, _("string where expression expected.\n")));
-+ idx = getstring (idx, string, &acc);
-+ sb_kill (&acc);
-+ }
-+ else
-+ {
-+ ERROR ((stderr, _("can't find primary in expression.\n")));
-+ idx++;
-+ }
-+ return sb_skip_white (idx, string);
-+}
-+
-+static int
-+level_1 (idx, string, lhs)
-+ size_t idx;
-+ sb *string;
-+ exp_t *lhs;
-+{
-+ idx = sb_skip_white (idx, string);
-+
-+ switch (string->ptr[idx])
-+ {
-+ case '+':
-+ idx = level_1 (idx + 1, string, lhs);
-+ break;
-+ case '~':
-+ idx = level_1 (idx + 1, string, lhs);
-+ checkconst ('~', lhs);
-+ lhs->value = ~lhs->value;
-+ break;
-+ case '-':
-+ {
-+ symbol t;
-+ idx = level_1 (idx + 1, string, lhs);
-+ lhs->value = -lhs->value;
-+ t = lhs->add_symbol;
-+ lhs->add_symbol = lhs->sub_symbol;
-+ lhs->sub_symbol = t;
-+ break;
-+ }
-+ case '(':
-+ idx++;
-+ idx = level_5 (sb_skip_white (idx, string), string, lhs);
-+ if (string->ptr[idx] != ')')
-+ ERROR ((stderr, _("misplaced closing parens.\n")));
-+ else
-+ idx++;
-+ break;
-+ default:
-+ idx = level_0 (idx, string, lhs);
-+ break;
-+ }
-+ return sb_skip_white (idx, string);
-+}
-+
-+static int
-+level_2 (idx, string, lhs)
-+ size_t idx;
-+ sb *string;
-+ exp_t *lhs;
-+{
-+ exp_t rhs;
-+
-+ idx = level_1 (idx, string, lhs);
-+
-+ while (idx < string->len && (string->ptr[idx] == '*'
-+ || string->ptr[idx] == '/'))
-+ {
-+ char op = string->ptr[idx++];
-+ idx = level_1 (idx, string, &rhs);
-+ switch (op)
-+ {
-+ case '*':
-+ checkconst ('*', lhs);
-+ checkconst ('*', &rhs);
-+ lhs->value *= rhs.value;
-+ break;
-+ case '/':
-+ checkconst ('/', lhs);
-+ checkconst ('/', &rhs);
-+ if (rhs.value == 0)
-+ ERROR ((stderr, _("attempt to divide by zero.\n")));
-+ else
-+ lhs->value /= rhs.value;
-+ break;
-+ }
-+ }
-+ return sb_skip_white (idx, string);
-+}
-+
-+static int
-+level_3 (idx, string, lhs)
-+ size_t idx;
-+ sb *string;
-+ exp_t *lhs;
-+{
-+ exp_t rhs;
-+
-+ idx = level_2 (idx, string, lhs);
-+
-+ while (idx < string->len
-+ && (string->ptr[idx] == '+'
-+ || string->ptr[idx] == '-'))
-+ {
-+ char op = string->ptr[idx++];
-+ idx = level_2 (idx, string, &rhs);
-+ switch (op)
-+ {
-+ case '+':
-+ lhs->value += rhs.value;
-+ if (lhs->add_symbol.name && rhs.add_symbol.name)
-+ {
-+ ERROR ((stderr, _("can't add two relocatable expressions\n")));
-+ }
-+ /* Change nn+symbol to symbol + nn. */
-+ if (rhs.add_symbol.name)
-+ {
-+ lhs->add_symbol = rhs.add_symbol;
-+ }
-+ break;
-+ case '-':
-+ lhs->value -= rhs.value;
-+ lhs->sub_symbol = rhs.add_symbol;
-+ break;
-+ }
-+ }
-+ return sb_skip_white (idx, string);
-+}
-+
-+static int
-+level_4 (idx, string, lhs)
-+ size_t idx;
-+ sb *string;
-+ exp_t *lhs;
-+{
-+ exp_t rhs;
-+
-+ idx = level_3 (idx, string, lhs);
-+
-+ while (idx < string->len &&
-+ string->ptr[idx] == '&')
-+ {
-+ char op = string->ptr[idx++];
-+ idx = level_3 (idx, string, &rhs);
-+ switch (op)
-+ {
-+ case '&':
-+ checkconst ('&', lhs);
-+ checkconst ('&', &rhs);
-+ lhs->value &= rhs.value;
-+ break;
-+ }
-+ }
-+ return sb_skip_white (idx, string);
-+}
-+
-+static int
-+level_5 (idx, string, lhs)
-+ size_t idx;
-+ sb *string;
-+ exp_t *lhs;
-+{
-+ exp_t rhs;
-+
-+ idx = level_4 (idx, string, lhs);
-+
-+ while (idx < string->len
-+ && (string->ptr[idx] == '|' || string->ptr[idx] == '~'))
-+ {
-+ char op = string->ptr[idx++];
-+ idx = level_4 (idx, string, &rhs);
-+ switch (op)
-+ {
-+ case '|':
-+ checkconst ('|', lhs);
-+ checkconst ('|', &rhs);
-+ lhs->value |= rhs.value;
-+ break;
-+ case '~':
-+ checkconst ('~', lhs);
-+ checkconst ('~', &rhs);
-+ lhs->value ^= rhs.value;
-+ break;
-+ }
-+ }
-+ return sb_skip_white (idx, string);
-+}
-+
-+/* Parse the expression at offset idx into string, fill up res with
-+ the result. Return the index of the first char past the
-+ expression. */
-+
-+static int
-+exp_parse (idx, string, res)
-+ size_t idx;
-+ sb *string;
-+ exp_t *res;
-+{
-+ return level_5 (sb_skip_white (idx, string), string, res);
-+}
-+
-+/* Turn the expression at exp into text and glue it onto the end of
-+ string. */
-+
-+static void
-+exp_string (exp, string)
-+ exp_t *exp;
-+ sb *string;
-+{
-+ int np = 0;
-+ int ad = 0;
-+ sb_reset (string);
-+
-+ if (exp->add_symbol.len)
-+ {
-+ sb_add_buffer (string, exp->add_symbol.name, exp->add_symbol.len);
-+ np = 1;
-+ ad = 1;
-+ }
-+ if (exp->value)
-+ {
-+ char buf[20];
-+ if (np)
-+ sb_add_char (string, '+');
-+ sprintf (buf, "%d", exp->value);
-+ sb_add_string (string, buf);
-+ np = 1;
-+ ad = 1;
-+ }
-+ if (exp->sub_symbol.len)
-+ {
-+ sb_add_char (string, '-');
-+ sb_add_buffer (string, exp->add_symbol.name, exp->add_symbol.len);
-+ np = 0;
-+ ad = 1;
-+ }
-+
-+ if (!ad)
-+ sb_add_char (string, '0');
-+}
-+
-+/* Parse the expression at offset idx into sb in. Return the value in
-+ val. If the expression is not constant, give ERROR emsg. Return
-+ the index of the first character past the end of the expression. */
-+
-+static size_t
-+exp_get_abs (emsg, idx, in, val)
-+ const char *emsg;
-+ size_t idx;
-+ sb *in;
-+ offsetT *val;
-+{
-+ exp_t res;
-+ idx = exp_parse (idx, in, &res);
-+ if (res.add_symbol.len || res.sub_symbol.len)
-+ ERROR ((stderr, "%s", emsg));
-+ *val = res.value;
-+ return idx;
-+}
-+
-+/* Current label parsed from line. */
-+sb label;
-+
-+/* Hash table for all assigned variables. */
-+hash_table assign_hash_table;
-+
-+/* Hash table for keyword. */
-+hash_table keyword_hash_table;
-+
-+/* Hash table for eq variables. */
-+hash_table vars;
-+
-+#define in_comment ';'
-+
-+#if 0
-+static void
-+strip_comments (out)
-+ sb *out;
-+{
-+ char *s = out->ptr;
-+ int i = 0;
-+ for (i = 0; i < out->len; i++)
-+ {
-+ if (ISCOMMENTCHAR (s[i]))
-+ {
-+ out->len = i;
-+ return;
-+ }
-+ }
-+}
-+#endif
-+
-+/* Push back character ch so that it can be read again. */
-+
-+static void
-+unget (ch)
-+ int ch;
-+{
-+ if (ch == '\n')
-+ {
-+ sp->linecount--;
-+ }
-+ if (sp->pushback_index)
-+ sp->pushback_index--;
-+ else
-+ sb_add_char (&sp->pushback, ch);
-+}
-+
-+/* Push the sb ptr onto the include stack, with the given name, type
-+ and index. */
-+
-+static void
-+include_buf (name, ptr, type, indx)
-+ sb *name;
-+ sb *ptr;
-+ include_type type;
-+ int indx;
-+{
-+ sp++;
-+ if (sp - include_stack >= MAX_INCLUDES)
-+ FATAL ((stderr, _("unreasonable nesting.\n")));
-+ sb_new (&sp->name);
-+ sb_add_sb (&sp->name, name);
-+ sp->handle = 0;
-+ sp->linecount = 1;
-+ sp->pushback_index = 0;
-+ sp->type = type;
-+ sp->index = indx;
-+ sb_new (&sp->pushback);
-+ sb_add_sb (&sp->pushback, ptr);
-+}
-+
-+/* Used in ERROR messages, print info on where the include stack is
-+ onto file. */
-+
-+static void
-+include_print_where_line (file)
-+ FILE *file;
-+{
-+ struct include_stack *p = include_stack + 1;
-+
-+ while (p <= sp)
-+ {
-+ fprintf (file, "%s:%d ", sb_name (&p->name), p->linecount - 1);
-+ p++;
-+ }
-+}
-+
-+/* Used in listings, print the line number onto file. */
-+
-+static void
-+include_print_line (file)
-+ FILE *file;
-+{
-+ int n;
-+ struct include_stack *p = include_stack + 1;
-+
-+ n = fprintf (file, "%4d", p->linecount);
-+ p++;
-+ while (p <= sp)
-+ {
-+ n += fprintf (file, ".%d", p->linecount);
-+ p++;
-+ }
-+ while (n < 8 * 3)
-+ {
-+ fprintf (file, " ");
-+ n++;
-+ }
-+}
-+
-+/* Read a line from the top of the include stack into sb in. */
-+
-+static size_t
-+get_line (in)
-+ sb *in;
-+{
-+ int online = 0;
-+ int more = 1, ch = 0;
-+
-+ if (copysource)
-+ {
-+ putc (comment_char, outfile);
-+ if (print_line_number)
-+ include_print_line (outfile);
-+ }
-+
-+ while (1)
-+ {
-+ ch = get ();
-+
-+ while (ch == '\r')
-+ ch = get ();
-+
-+ if (ch == EOF)
-+ {
-+ if (online)
-+ {
-+ WARNING ((stderr, _("End of file not at start of line.\n")));
-+ if (copysource)
-+ putc ('\n', outfile);
-+ ch = '\n';
-+ }
-+ else
-+ more = 0;
-+ break;
-+ }
-+
-+ if (copysource)
-+ {
-+ putc (ch, outfile);
-+ }
-+
-+ if (ch == '\n')
-+ {
-+ ch = get ();
-+ online = 0;
-+ if (ch == '+')
-+ {
-+ /* Continued line. */
-+ if (copysource)
-+ {
-+ putc (comment_char, outfile);
-+ putc ('+', outfile);
-+ }
-+ ch = get ();
-+ }
-+ else
-+ {
-+ if (ch != EOF)
-+ unget (ch);
-+ ch = '\n'; break;
-+ }
-+ }
-+ else
-+ {
-+ sb_add_char (in, ch);
-+ }
-+ online++;
-+ }
-+
-+ return more ? ch : 0;
-+}
-+
-+/* Find a label from sb in and put it in out. */
-+
-+static int
-+grab_label (in, out)
-+ sb *in;
-+ sb *out;
-+{
-+ size_t i = 0;
-+ sb_reset (out);
-+ if (ISFIRSTCHAR (in->ptr[i]) || in->ptr[i] == '\\')
-+ {
-+ sb_add_char (out, in->ptr[i]);
-+ i++;
-+ while ((ISNEXTCHAR (in->ptr[i])
-+ || in->ptr[i] == '\\'
-+ || in->ptr[i] == '&')
-+ && i < in->len)
-+ {
-+ sb_add_char (out, in->ptr[i]);
-+ i++;
-+ }
-+ }
-+ return i;
-+}
-+
-+/* Find all strange base stuff and turn into decimal. Also
-+ find all the other numbers and convert them from the default radix. */
-+
-+static void
-+change_base (idx, in, out)
-+ size_t idx;
-+ sb *in;
-+ sb *out;
-+{
-+ char buffer[20];
-+
-+ while (idx < in->len)
-+ {
-+ if (in->ptr[idx] == '\\'
-+ && idx + 1 < in->len
-+ && in->ptr[idx + 1] == '(')
-+ {
-+ idx += 2;
-+ while (idx < in->len
-+ && in->ptr[idx] != ')')
-+ {
-+ sb_add_char (out, in->ptr[idx]);
-+ idx++;
-+ }
-+ if (idx < in->len)
-+ idx++;
-+ }
-+ else if (idx < in->len - 1 && in->ptr[idx + 1] == '\'' && ! mri)
-+ {
-+ int base;
-+ int value;
-+ switch (in->ptr[idx])
-+ {
-+ case 'b':
-+ case 'B':
-+ base = 2;
-+ break;
-+ case 'q':
-+ case 'Q':
-+ base = 8;
-+ break;
-+ case 'h':
-+ case 'H':
-+ base = 16;
-+ break;
-+ case 'd':
-+ case 'D':
-+ base = 10;
-+ break;
-+ default:
-+ ERROR ((stderr, _("Illegal base character %c.\n"), in->ptr[idx]));
-+ base = 10;
-+ break;
-+ }
-+
-+ idx = sb_strtol (idx + 2, in, base, &value);
-+ sprintf (buffer, "%d", value);
-+ sb_add_string (out, buffer);
-+ }
-+ else if (ISFIRSTCHAR (in->ptr[idx]))
-+ {
-+ /* Copy entire names through quickly. */
-+ sb_add_char (out, in->ptr[idx]);
-+ idx++;
-+ while (idx < in->len && ISNEXTCHAR (in->ptr[idx]))
-+ {
-+ sb_add_char (out, in->ptr[idx]);
-+ idx++;
-+ }
-+ }
-+ else if (is_flonum (idx, in))
-+ {
-+ idx = chew_flonum (idx, in, out);
-+ }
-+ else if (ISDIGIT (in->ptr[idx]))
-+ {
-+ int value;
-+ /* All numbers must start with a digit, let's chew it and
-+ spit out decimal. */
-+ idx = sb_strtol (idx, in, radix, &value);
-+ sprintf (buffer, "%d", value);
-+ sb_add_string (out, buffer);
-+
-+ /* Skip all undigsested letters. */
-+ while (idx < in->len && ISNEXTCHAR (in->ptr[idx]))
-+ {
-+ sb_add_char (out, in->ptr[idx]);
-+ idx++;
-+ }
-+ }
-+ else if (in->ptr[idx] == '"' || in->ptr[idx] == '\'')
-+ {
-+ char tchar = in->ptr[idx];
-+ /* Copy entire names through quickly. */
-+ sb_add_char (out, in->ptr[idx]);
-+ idx++;
-+ while (idx < in->len && in->ptr[idx] != tchar)
-+ {
-+ sb_add_char (out, in->ptr[idx]);
-+ idx++;
-+ }
-+ }
-+ else
-+ {
-+ /* Nothing special, just pass it through. */
-+ sb_add_char (out, in->ptr[idx]);
-+ idx++;
-+ }
-+ }
-+
-+}
-+
-+/* .end */
-+
-+static void
-+do_end (in)
-+ sb *in;
-+{
-+ had_end = 1;
-+ if (mri)
-+ fprintf (outfile, "%s\n", sb_name (in));
-+}
-+
-+/* .assign */
-+
-+static void
-+do_assign (again, idx, in)
-+ int again;
-+ size_t idx;
-+ sb *in;
-+{
-+ /* Stick label in symbol table with following value. */
-+ exp_t e;
-+ sb acc;
-+
-+ sb_new (&acc);
-+ idx = exp_parse (idx, in, &e);
-+ exp_string (&e, &acc);
-+ hash_add_to_string_table (&assign_hash_table, &label, &acc, again);
-+ sb_kill (&acc);
-+}
-+
-+/* .radix [b|q|d|h] */
-+
-+static void
-+do_radix (ptr)
-+ sb *ptr;
-+{
-+ size_t idx = sb_skip_white (0, ptr);
-+ switch (ptr->ptr[idx])
-+ {
-+ case 'B':
-+ case 'b':
-+ radix = 2;
-+ break;
-+ case 'q':
-+ case 'Q':
-+ radix = 8;
-+ break;
-+ case 'd':
-+ case 'D':
-+ radix = 10;
-+ break;
-+ case 'h':
-+ case 'H':
-+ radix = 16;
-+ break;
-+ default:
-+ ERROR ((stderr, _("radix is %c must be one of b, q, d or h"), radix));
-+ }
-+}
-+
-+/* Parse off a .b, .w or .l. */
-+
-+static int
-+get_opsize (idx, in, size)
-+ size_t idx;
-+ sb *in;
-+ int *size;
-+{
-+ *size = 4;
-+ if (in->ptr[idx] == '.')
-+ {
-+ idx++;
-+ }
-+ switch (in->ptr[idx])
-+ {
-+ case 'b':
-+ case 'B':
-+ *size = 1;
-+ break;
-+ case 'w':
-+ case 'W':
-+ *size = 2;
-+ break;
-+ case 'l':
-+ case 'L':
-+ *size = 4;
-+ break;
-+ case ' ':
-+ case '\t':
-+ break;
-+ default:
-+ ERROR ((stderr, _("size must be one of b, w or l, is %c.\n"), in->ptr[idx]));
-+ break;
-+ }
-+ idx++;
-+
-+ return idx;
-+}
-+
-+static int
-+eol (idx, line)
-+ size_t idx;
-+ sb *line;
-+{
-+ idx = sb_skip_white (idx, line);
-+ if (idx < line->len
-+ && ISCOMMENTCHAR(line->ptr[idx]))
-+ return 1;
-+ if (idx >= line->len)
-+ return 1;
-+ return 0;
-+}
-+
-+/* .data [.b|.w|.l] <data>*
-+ or d[bwl] <data>* */
-+
-+static void
-+do_data (idx, in, size)
-+ size_t idx;
-+ sb *in;
-+ int size;
-+{
-+ int opsize = 4;
-+ const char *opname = ".yikes!";
-+ sb acc;
-+ sb_new (&acc);
-+
-+ if (!size)
-+ {
-+ idx = get_opsize (idx, in, &opsize);
-+ }
-+ else
-+ {
-+ opsize = size;
-+ }
-+ switch (opsize)
-+ {
-+ case 4:
-+ opname = ".long";
-+ break;
-+ case 2:
-+ opname = ".short";
-+ break;
-+ case 1:
-+ opname = ".byte";
-+ break;
-+ }
-+
-+ fprintf (outfile, "%s\t", opname);
-+
-+ idx = sb_skip_white (idx, in);
-+
-+ if (alternate
-+ && idx < in->len
-+ && in->ptr[idx] == '"')
-+ {
-+ size_t i;
-+ idx = getstring (idx, in, &acc);
-+ for (i = 0; i < acc.len; i++)
-+ {
-+ if (i)
-+ fprintf (outfile, ",");
-+ fprintf (outfile, "%d", acc.ptr[i]);
-+ }
-+ }
-+ else
-+ {
-+ while (!eol (idx, in))
-+ {
-+ exp_t e;
-+ idx = exp_parse (idx, in, &e);
-+ exp_string (&e, &acc);
-+ sb_add_char (&acc, 0);
-+ fprintf (outfile, "%s", acc.ptr);
-+ if (idx < in->len && in->ptr[idx] == ',')
-+ {
-+ fprintf (outfile, ",");
-+ idx++;
-+ }
-+ }
-+ }
-+ sb_kill (&acc);
-+ sb_print_at (outfile, idx, in);
-+ fprintf (outfile, "\n");
-+}
-+
-+/* .datab [.b|.w|.l] <repeat>,<fill> */
-+
-+static void
-+do_datab (idx, in)
-+ size_t idx;
-+ sb *in;
-+{
-+ int opsize;
-+ offsetT repeat;
-+ offsetT fill;
-+
-+ idx = get_opsize (idx, in, &opsize);
-+
-+ idx = exp_get_abs (_("datab repeat must be constant.\n"), idx, in, &repeat);
-+ idx = sb_skip_comma (idx, in);
-+ idx = exp_get_abs (_("datab data must be absolute.\n"), idx, in, &fill);
-+
-+ fprintf (outfile, ".fill\t%ld,%d,%ld\n", (long)repeat, opsize, (long)fill);
-+}
-+
-+/* .align <size> */
-+
-+static void
-+gasp_do_align (idx, in)
-+ size_t idx;
-+ sb *in;
-+{
-+ int have_fill; offsetT al, fill;
-+
-+ idx = exp_get_abs (_("align needs absolute expression.\n"), idx, in, &al);
-+ idx = sb_skip_white (idx, in);
-+ have_fill = 0;
-+ fill = 0;
-+ if (! eol (idx, in))
-+ {
-+ idx = sb_skip_comma (idx, in);
-+ idx = exp_get_abs (_(".align needs absolute fill value.\n"), idx, in,
-+ &fill);
-+ have_fill = 1;
-+ }
-+
-+ fprintf (outfile, ".align %ld", (long)al);
-+ if (have_fill)
-+ fprintf (outfile, ",%ld", (long)fill);
-+ fprintf (outfile, "\n");
-+}
-+
-+/* .res[.b|.w|.l] <size> */
-+
-+static void
-+do_res (idx, in, type)
-+ size_t idx;
-+ sb *in;
-+ int type;
-+{
-+ int size = 4;
-+ offsetT count = 0;
-+
-+ idx = get_opsize (idx, in, &size);
-+ while (!eol (idx, in))
-+ {
-+ idx = sb_skip_white (idx, in);
-+ if (in->ptr[idx] == ',')
-+ idx++;
-+ idx = exp_get_abs (_("res needs absolute expression for fill count.\n"), idx, in, &count);
-+
-+ if (type == 'c' || type == 'z')
-+ count++;
-+
-+ fprintf (outfile, ".space %ld\n", (long)(count * size));
-+ }
-+}
-+
-+/* .export */
-+
-+static void
-+do_export (in)
-+ sb *in;
-+{
-+ fprintf (outfile, ".global %s\n", sb_name (in));
-+}
-+
-+/* .print [list] [nolist] */
-+
-+static void
-+do_print (idx, in)
-+ size_t idx;
-+ sb *in;
-+{
-+ idx = sb_skip_white (idx, in);
-+ while (idx < in->len)
-+ {
-+ if (strncasecmp (in->ptr + idx, "LIST", 4) == 0)
-+ {
-+ fprintf (outfile, ".list\n");
-+ idx += 4;
-+ }
-+ else if (strncasecmp (in->ptr + idx, "NOLIST", 6) == 0)
-+ {
-+ fprintf (outfile, ".nolist\n");
-+ idx += 6;
-+ }
-+ idx++;
-+ }
-+}
-+
-+/* .head */
-+
-+static void
-+do_heading (idx, in)
-+ size_t idx;
-+ sb *in;
-+{
-+ sb head;
-+ sb_new (&head);
-+ idx = getstring (idx, in, &head);
-+ fprintf (outfile, ".title \"%s\"\n", sb_name (&head));
-+ sb_kill (&head);
-+}
-+
-+/* .page */
-+
-+static void
-+do_page ()
-+{
-+ fprintf (outfile, ".eject\n");
-+}
-+
-+/* .form [lin=<value>] [col=<value>] */
-+
-+static void
-+do_form (idx, in)
-+ size_t idx;
-+ sb *in;
-+{
-+ offsetT lines = 60;
-+ offsetT columns = 132;
-+ idx = sb_skip_white (idx, in);
-+
-+ while (idx < in->len)
-+ {
-+
-+ if (strncasecmp (in->ptr + idx, "LIN=", 4) == 0)
-+ {
-+ idx += 4;
-+ idx = exp_get_abs (_("form LIN= needs absolute expresssion.\n"), idx, in, &lines);
-+ }
-+
-+ if (strncasecmp (in->ptr + idx, _("COL="), 4) == 0)
-+ {
-+ idx += 4;
-+ idx = exp_get_abs (_("form COL= needs absolute expresssion.\n"), idx, in, &columns);
-+ }
-+
-+ idx++;
-+ }
-+ fprintf (outfile, ".psize %ld,%ld\n", (long)lines, (long)columns);
-+
-+}
-+
-+/* Fetch string from the input stream,
-+ rules:
-+ 'Bxyx<whitespace> -> return 'Bxyza
-+ %<char> -> return string of decimal value of x
-+ "<string>" -> return string
-+ xyx<whitespace> -> return xyz
-+*/
-+
-+static int
-+get_any_string (idx, in, out, expand, pretend_quoted)
-+ size_t idx;
-+ sb *in;
-+ sb *out;
-+ int expand;
-+ int pretend_quoted;
-+{
-+ sb_reset (out);
-+ idx = sb_skip_white (idx, in);
-+
-+ if (idx < in->len)
-+ {
-+ if (in->len > 2 && in->ptr[idx + 1] == '\'' && ISBASE (in->ptr[idx]))
-+ {
-+ while (!ISSEP (in->ptr[idx]))
-+ sb_add_char (out, in->ptr[idx++]);
-+ }
-+ else if (in->ptr[idx] == '%'
-+ && alternate
-+ && expand)
-+ {
-+ offsetT val;
-+ char buf[20];
-+ /* Turns the next expression into a string. */
-+ /* xgettext: no-c-format */
-+ idx = exp_get_abs (_("% operator needs absolute expression"),
-+ idx + 1,
-+ in,
-+ &val);
-+ sprintf (buf, "%ld", (long)val);
-+ sb_add_string (out, buf);
-+ }
-+ else if (in->ptr[idx] == '"'
-+ || in->ptr[idx] == '<'
-+ || (alternate && in->ptr[idx] == '\''))
-+ {
-+ if (alternate && expand)
-+ {
-+ /* Keep the quotes. */
-+ sb_add_char (out, '\"');
-+
-+ idx = getstring (idx, in, out);
-+ sb_add_char (out, '\"');
-+
-+ }
-+ else
-+ {
-+ idx = getstring (idx, in, out);
-+ }
-+ }
-+ else
-+ {
-+ while (idx < in->len
-+ && (in->ptr[idx] == '"'
-+ || in->ptr[idx] == '\''
-+ || pretend_quoted
-+ || !ISSEP (in->ptr[idx])))
-+ {
-+ if (in->ptr[idx] == '"'
-+ || in->ptr[idx] == '\'')
-+ {
-+ char tchar = in->ptr[idx];
-+ sb_add_char (out, in->ptr[idx++]);
-+ while (idx < in->len
-+ && in->ptr[idx] != tchar)
-+ sb_add_char (out, in->ptr[idx++]);
-+ if (idx == in->len)
-+ return idx;
-+ }
-+ sb_add_char (out, in->ptr[idx++]);
-+ }
-+ }
-+ }
-+
-+ return idx;
-+}
-+
-+/* Skip along sb in starting at idx, suck off whitespace a ( and more
-+ whitespace. Return the idx of the next char. */
-+
-+static int
-+skip_openp (idx, in)
-+ size_t idx;
-+ sb *in;
-+{
-+ idx = sb_skip_white (idx, in);
-+ if (in->ptr[idx] != '(')
-+ ERROR ((stderr, _("misplaced ( .\n")));
-+ idx = sb_skip_white (idx + 1, in);
-+ return idx;
-+}
-+
-+/* Skip along sb in starting at idx, suck off whitespace a ) and more
-+ whitespace. Return the idx of the next char. */
-+
-+static int
-+skip_closep (idx, in)
-+ size_t idx;
-+ sb *in;
-+{
-+ idx = sb_skip_white (idx, in);
-+ if (in->ptr[idx] != ')')
-+ ERROR ((stderr, _("misplaced ).\n")));
-+ idx = sb_skip_white (idx + 1, in);
-+ return idx;
-+}
-+
-+/* .len */
-+
-+static int
-+dolen (idx, in, out)
-+ size_t idx;
-+ sb *in;
-+ sb *out;
-+{
-+
-+ sb stringout;
-+ char buffer[10];
-+
-+ sb_new (&stringout);
-+ idx = skip_openp (idx, in);
-+ idx = get_and_process (idx, in, &stringout);
-+ idx = skip_closep (idx, in);
-+ sprintf (buffer, "%d", stringout.len);
-+ sb_add_string (out, buffer);
-+
-+ sb_kill (&stringout);
-+ return idx;
-+}
-+
-+/* .instr */
-+
-+static int
-+doinstr (idx, in, out)
-+ size_t idx;
-+ sb *in;
-+ sb *out;
-+{
-+ sb string;
-+ sb search;
-+ size_t i;
-+ offsetT start;
-+ int res;
-+ char buffer[10];
-+
-+ sb_new (&string);
-+ sb_new (&search);
-+ idx = skip_openp (idx, in);
-+ idx = get_and_process (idx, in, &string);
-+ idx = sb_skip_comma (idx, in);
-+ idx = get_and_process (idx, in, &search);
-+ idx = sb_skip_comma (idx, in);
-+ if (ISDIGIT (in->ptr[idx]))
-+ {
-+ idx = exp_get_abs (_(".instr needs absolute expresson.\n"), idx, in, &start);
-+ }
-+ else
-+ {
-+ start = 0;
-+ }
-+ idx = skip_closep (idx, in);
-+ res = -1;
-+ for (i = start; i < string.len; i++)
-+ {
-+ if (strncmp (string.ptr + i, search.ptr, search.len) == 0)
-+ {
-+ res = i;
-+ break;
-+ }
-+ }
-+ sprintf (buffer, "%d", res);
-+ sb_add_string (out, buffer);
-+ sb_kill (&string);
-+ sb_kill (&search);
-+ return idx;
-+}
-+
-+static int
-+dosubstr (idx, in, out)
-+ size_t idx;
-+ sb *in;
-+ sb *out;
-+{
-+ sb string;
-+ offsetT pos;
-+ offsetT len;
-+ sb_new (&string);
-+
-+ idx = skip_openp (idx, in);
-+ idx = get_and_process (idx, in, &string);
-+ idx = sb_skip_comma (idx, in);
-+ idx = exp_get_abs (_("need absolute position.\n"), idx, in, &pos);
-+ idx = sb_skip_comma (idx, in);
-+ idx = exp_get_abs (_("need absolute length.\n"), idx, in, &len);
-+ idx = skip_closep (idx, in);
-+
-+ if (len < 0 || pos < 0 ||
-+ pos > string.len
-+ || pos + len > string.len)
-+ {
-+ sb_add_string (out, " ");
-+ }
-+ else
-+ {
-+ sb_add_char (out, '"');
-+ while (len > 0)
-+ {
-+ sb_add_char (out, string.ptr[pos++]);
-+ len--;
-+ }
-+ sb_add_char (out, '"');
-+ }
-+ sb_kill (&string);
-+ return idx;
-+}
-+
-+/* Scan line, change tokens in the hash table to their replacements. */
-+
-+static void
-+process_assigns (idx, in, buf)
-+ size_t idx;
-+ sb *in;
-+ sb *buf;
-+{
-+ while (idx < in->len)
-+ {
-+ hash_entry *ptr;
-+ if (in->ptr[idx] == '\\'
-+ && idx + 1 < in->len
-+ && in->ptr[idx + 1] == '(')
-+ {
-+ do
-+ {
-+ sb_add_char (buf, in->ptr[idx]);
-+ idx++;
-+ }
-+ while (idx < in->len && in->ptr[idx - 1] != ')');
-+ }
-+ else if (in->ptr[idx] == '\\'
-+ && idx + 1 < in->len
-+ && in->ptr[idx + 1] == '&')
-+ {
-+ idx = condass_lookup_name (in, idx + 2, buf, 1);
-+ }
-+ else if (in->ptr[idx] == '\\'
-+ && idx + 1 < in->len
-+ && in->ptr[idx + 1] == '$')
-+ {
-+ idx = condass_lookup_name (in, idx + 2, buf, 0);
-+ }
-+ else if (idx + 3 < in->len
-+ && in->ptr[idx] == '.'
-+ && TOUPPER (in->ptr[idx + 1]) == 'L'
-+ && TOUPPER (in->ptr[idx + 2]) == 'E'
-+ && TOUPPER (in->ptr[idx + 3]) == 'N')
-+ idx = dolen (idx + 4, in, buf);
-+ else if (idx + 6 < in->len
-+ && in->ptr[idx] == '.'
-+ && TOUPPER (in->ptr[idx + 1]) == 'I'
-+ && TOUPPER (in->ptr[idx + 2]) == 'N'
-+ && TOUPPER (in->ptr[idx + 3]) == 'S'
-+ && TOUPPER (in->ptr[idx + 4]) == 'T'
-+ && TOUPPER (in->ptr[idx + 5]) == 'R')
-+ idx = doinstr (idx + 6, in, buf);
-+ else if (idx + 7 < in->len
-+ && in->ptr[idx] == '.'
-+ && TOUPPER (in->ptr[idx + 1]) == 'S'
-+ && TOUPPER (in->ptr[idx + 2]) == 'U'
-+ && TOUPPER (in->ptr[idx + 3]) == 'B'
-+ && TOUPPER (in->ptr[idx + 4]) == 'S'
-+ && TOUPPER (in->ptr[idx + 5]) == 'T'
-+ && TOUPPER (in->ptr[idx + 6]) == 'R')
-+ idx = dosubstr (idx + 7, in, buf);
-+ else if (ISFIRSTCHAR (in->ptr[idx]))
-+ {
-+ /* May be a simple name subsitution, see if we have a word. */
-+ sb acc;
-+ size_t cur = idx + 1;
-+ while (cur < in->len
-+ && (ISNEXTCHAR (in->ptr[cur])))
-+ cur++;
-+
-+ sb_new (&acc);
-+ sb_add_buffer (&acc, in->ptr + idx, cur - idx);
-+ ptr = hash_lookup (&assign_hash_table, &acc);
-+ if (ptr)
-+ {
-+ /* Found a definition for it. */
-+ sb_add_sb (buf, &ptr->value.s);
-+ }
-+ else
-+ {
-+ /* No definition, just copy the word. */
-+ sb_add_sb (buf, &acc);
-+ }
-+ sb_kill (&acc);
-+ idx = cur;
-+ }
-+ else
-+ {
-+ sb_add_char (buf, in->ptr[idx++]);
-+ }
-+ }
-+}
-+
-+static int
-+get_and_process (idx, in, out)
-+ size_t idx;
-+ sb *in;
-+ sb *out;
-+{
-+ sb t;
-+ sb_new (&t);
-+ idx = get_any_string (idx, in, &t, 1, 0);
-+ process_assigns (0, &t, out);
-+ sb_kill (&t);
-+ return idx;
-+}
-+
-+static void
-+process_file ()
-+{
-+ sb line;
-+ sb t1, t2;
-+ sb acc;
-+ sb label_in;
-+ int more;
-+
-+ sb_new (&line);
-+ sb_new (&t1);
-+ sb_new (&t2);
-+ sb_new (&acc);
-+ sb_new (&label_in);
-+ sb_reset (&line);
-+ more = get_line (&line);
-+ while (more)
-+ {
-+ /* Find any label and pseudo op that we're intested in. */
-+ size_t l;
-+ if (line.len == 0)
-+ {
-+ if (condass_on ())
-+ fprintf (outfile, "\n");
-+ }
-+ else if (mri
-+ && (line.ptr[0] == '*'
-+ || line.ptr[0] == '!'))
-+ {
-+ /* MRI line comment. */
-+ fprintf (outfile, "%s", sb_name (&line));
-+ }
-+ else
-+ {
-+ l = grab_label (&line, &label_in);
-+ sb_reset (&label);
-+
-+ if (line.ptr[l] == ':')
-+ l++;
-+ while (ISWHITE (line.ptr[l]) && l < line.len)
-+ l++;
-+
-+ if (label_in.len)
-+ {
-+ int do_assigns;
-+
-+ /* Munge the label, unless this is EQU or ASSIGN. */
-+ do_assigns = 1;
-+ if (l < line.len
-+ && (line.ptr[l] == '.' || alternate || mri))
-+ {
-+ size_t lx = l;
-+
-+ if (line.ptr[lx] == '.')
-+ ++lx;
-+ if (lx + 3 <= line.len
-+ && strncasecmp ("EQU", line.ptr + lx, 3) == 0
-+ && (lx + 3 == line.len
-+ || ! ISFIRSTCHAR (line.ptr[lx + 3])))
-+ do_assigns = 0;
-+ else if (lx + 6 <= line.len
-+ && strncasecmp ("ASSIGN", line.ptr + lx, 6) == 0
-+ && (lx + 6 == line.len
-+ || ! ISFIRSTCHAR (line.ptr[lx + 6])))
-+ do_assigns = 0;
-+ }
-+
-+ if (do_assigns)
-+ process_assigns (0, &label_in, &label);
-+ else
-+ sb_add_sb (&label, &label_in);
-+ }
-+
-+ if (l < line.len)
-+ {
-+ if (process_pseudo_op (l, &line, &acc))
-+ {
-+
-+ }
-+ else if (condass_on ())
-+ {
-+ if (macro_op (l, &line))
-+ {
-+
-+ }
-+ else
-+ {
-+ {
-+ if (label.len)
-+ {
-+ fprintf (outfile, "%s:\t", sb_name (&label));
-+ }
-+ else
-+ fprintf (outfile, "\t");
-+ sb_reset (&t1);
-+ process_assigns (l, &line, &t1);
-+ sb_reset (&t2);
-+ change_base (0, &t1, &t2);
-+ fprintf (outfile, "%s\n", sb_name (&t2));
-+ }
-+ }
-+ }
-+ }
-+ else
-+ {
-+ /* Only a label on this line. */
-+ if (label.len && condass_on ())
-+ {
-+ fprintf (outfile, "%s:\n", sb_name (&label));
-+ }
-+ }
-+ }
-+
-+ if (had_end)
-+ break;
-+ sb_reset (&line);
-+ more = get_line (&line);
-+ }
-+
-+ if (!had_end && !mri)
-+ WARNING ((stderr, _("END missing from end of file.\n")));
-+}
-+
-+static void
-+free_old_entry (ptr)
-+ hash_entry *ptr;
-+{
-+ if (ptr)
-+ {
-+ if (ptr->type == hash_string)
-+ sb_kill (&ptr->value.s);
-+ }
-+}
-+
-+/* name: .ASSIGNA <value> */
-+
-+static void
-+do_assigna (idx, in)
-+ size_t idx;
-+ sb *in;
-+{
-+ sb tmp;
-+ offsetT val;
-+ sb_new (&tmp);
-+
-+ process_assigns (idx, in, &tmp);
-+ idx = exp_get_abs (_(".ASSIGNA needs constant expression argument.\n"), 0, &tmp, &val);
-+
-+ if (!label.len)
-+ {
-+ ERROR ((stderr, _(".ASSIGNA without label.\n")));
-+ }
-+ else
-+ {
-+ hash_entry *ptr = hash_create (&vars, &label);
-+ free_old_entry (ptr);
-+ ptr->type = hash_integer;
-+ ptr->value.i = val;
-+ }
-+ sb_kill (&tmp);
-+}
-+
-+/* name: .ASSIGNC <string> */
-+
-+static void
-+do_assignc (idx, in)
-+ size_t idx;
-+ sb *in;
-+{
-+ sb acc;
-+ sb_new (&acc);
-+ idx = getstring (idx, in, &acc);
-+
-+ if (!label.len)
-+ {
-+ ERROR ((stderr, _(".ASSIGNS without label.\n")));
-+ }
-+ else
-+ {
-+ hash_entry *ptr = hash_create (&vars, &label);
-+ free_old_entry (ptr);
-+ ptr->type = hash_string;
-+ sb_new (&ptr->value.s);
-+ sb_add_sb (&ptr->value.s, &acc);
-+ }
-+ sb_kill (&acc);
-+}
-+
-+/* name: .REG (reg) */
-+
-+static void
-+do_reg (idx, in)
-+ size_t idx;
-+ sb *in;
-+{
-+ /* Remove reg stuff from inside parens. */
-+ sb what;
-+ if (!mri)
-+ idx = skip_openp (idx, in);
-+ else
-+ idx = sb_skip_white (idx, in);
-+ sb_new (&what);
-+ while (idx < in->len
-+ && (mri
-+ ? ! eol (idx, in)
-+ : in->ptr[idx] != ')'))
-+ {
-+ sb_add_char (&what, in->ptr[idx]);
-+ idx++;
-+ }
-+ hash_add_to_string_table (&assign_hash_table, &label, &what, 1);
-+ sb_kill (&what);
-+}
-+
-+static int
-+condass_lookup_name (inbuf, idx, out, warn)
-+ sb *inbuf;
-+ size_t idx;
-+ sb *out;
-+ int warn;
-+{
-+ hash_entry *ptr;
-+ sb condass_acc;
-+ sb_new (&condass_acc);
-+
-+ while (idx < inbuf->len
-+ && ISNEXTCHAR (inbuf->ptr[idx]))
-+ {
-+ sb_add_char (&condass_acc, inbuf->ptr[idx++]);
-+ }
-+
-+ if (inbuf->ptr[idx] == '\'')
-+ idx++;
-+ ptr = hash_lookup (&vars, &condass_acc);
-+
-+ if (!ptr)
-+ {
-+ if (warn)
-+ {
-+ WARNING ((stderr, _("Can't find preprocessor variable %s.\n"), sb_name (&condass_acc)));
-+ }
-+ else
-+ {
-+ sb_add_string (out, "0");
-+ }
-+ }
-+ else
-+ {
-+ if (ptr->type == hash_integer)
-+ {
-+ char buffer[30];
-+ sprintf (buffer, "%d", ptr->value.i);
-+ sb_add_string (out, buffer);
-+ }
-+ else
-+ {
-+ sb_add_sb (out, &ptr->value.s);
-+ }
-+ }
-+ sb_kill (&condass_acc);
-+ return idx;
-+}
-+
-+#define EQ 1
-+#define NE 2
-+#define GE 3
-+#define LT 4
-+#define LE 5
-+#define GT 6
-+#define NEVER 7
-+
-+static int
-+whatcond (idx, in, val)
-+ size_t idx;
-+ sb *in;
-+ int *val;
-+{
-+ int cond;
-+
-+ idx = sb_skip_white (idx, in);
-+ cond = NEVER;
-+ if (idx + 1 < in->len)
-+ {
-+ char *p;
-+ char a, b;
-+
-+ p = in->ptr + idx;
-+ a = TOUPPER (p[0]);
-+ b = TOUPPER (p[1]);
-+ if (a == 'E' && b == 'Q')
-+ cond = EQ;
-+ else if (a == 'N' && b == 'E')
-+ cond = NE;
-+ else if (a == 'L' && b == 'T')
-+ cond = LT;
-+ else if (a == 'L' && b == 'E')
-+ cond = LE;
-+ else if (a == 'G' && b == 'T')
-+ cond = GT;
-+ else if (a == 'G' && b == 'E')
-+ cond = GE;
-+ }
-+ if (cond == NEVER)
-+ {
-+ ERROR ((stderr, _("Comparison operator must be one of EQ, NE, LT, LE, GT or GE.\n")));
-+ cond = NEVER;
-+ }
-+ idx = sb_skip_white (idx + 2, in);
-+ *val = cond;
-+ return idx;
-+}
-+
-+static int
-+istrue (idx, in)
-+ size_t idx;
-+ sb *in;
-+{
-+ int res;
-+ sb acc_a;
-+ sb cond;
-+ sb acc_b;
-+ sb_new (&acc_a);
-+ sb_new (&cond);
-+ sb_new (&acc_b);
-+ idx = sb_skip_white (idx, in);
-+
-+ if (in->ptr[idx] == '"')
-+ {
-+ int cond2;
-+ int same;
-+ /* This is a string comparision. */
-+ idx = getstring (idx, in, &acc_a);
-+ idx = whatcond (idx, in, &cond2);
-+ idx = getstring (idx, in, &acc_b);
-+ same = acc_a.len == acc_b.len
-+ && (strncmp (acc_a.ptr, acc_b.ptr, acc_a.len) == 0);
-+
-+ if (cond2 != EQ && cond2 != NE)
-+ {
-+ ERROR ((stderr, _("Comparison operator for strings must be EQ or NE\n")));
-+ res = 0;
-+ }
-+ else
-+ res = (cond2 != EQ) ^ same;
-+ }
-+ else
-+ /* This is a numeric expression. */
-+ {
-+ offsetT vala;
-+ offsetT valb;
-+ int cond2;
-+ idx = exp_get_abs (_("Conditional operator must have absolute operands.\n"), idx, in, &vala);
-+ idx = whatcond (idx, in, &cond2);
-+ idx = sb_skip_white (idx, in);
-+ if (in->ptr[idx] == '"')
-+ {
-+ WARNING ((stderr, _("String compared against expression.\n")));
-+ res = 0;
-+ }
-+ else
-+ {
-+ idx = exp_get_abs (_("Conditional operator must have absolute operands.\n"), idx, in, &valb);
-+ switch (cond2)
-+ {
-+ default:
-+ res = 42;
-+ break;
-+ case EQ:
-+ res = vala == valb;
-+ break;
-+ case NE:
-+ res = vala != valb;
-+ break;
-+ case LT:
-+ res = vala < valb;
-+ break;
-+ case LE:
-+ res = vala <= valb;
-+ break;
-+ case GT:
-+ res = vala > valb;
-+ break;
-+ case GE:
-+ res = vala >= valb;
-+ break;
-+ case NEVER:
-+ res = 0;
-+ break;
-+ }
-+ }
-+ }
-+
-+ sb_kill (&acc_a);
-+ sb_kill (&cond);
-+ sb_kill (&acc_b);
-+ return res;
-+}
-+
-+/* .AIF */
-+
-+static void
-+do_aif (idx, in)
-+ size_t idx;
-+ sb *in;
-+{
-+ if (ifi >= IFNESTING)
-+ {
-+ FATAL ((stderr, _("AIF nesting unreasonable.\n")));
-+ }
-+ ifi++;
-+ ifstack[ifi].on = ifstack[ifi - 1].on ? istrue (idx, in) : 0;
-+ ifstack[ifi].hadelse = 0;
-+}
-+
-+/* .AELSE */
-+
-+static void
-+do_aelse ()
-+{
-+ ifstack[ifi].on = ifstack[ifi - 1].on ? !ifstack[ifi].on : 0;
-+ if (ifstack[ifi].hadelse)
<Skipped 1847 lines>
================================================================
---- gitweb:
http://git.pld-linux.org/gitweb.cgi/packages/binutils.git/commitdiff/222a2fedcaea1f2c583dc4c1610506a2d2411b78
More information about the pld-cvs-commit
mailing list