new gas main line
authorK. Richard Pixley <rich@cygnus>
Thu, 4 Apr 1991 18:19:56 +0000 (18:19 +0000)
committerK. Richard Pixley <rich@cygnus>
Thu, 4 Apr 1991 18:19:56 +0000 (18:19 +0000)
36 files changed:
gas/.gdbinit [new file with mode: 0644]
gas/GNUmakefile-host [new file with mode: 0755]
gas/Makefile.loic [new file with mode: 0755]
gas/Makefile.old [new file with mode: 0644]
gas/NOTES [new file with mode: 0644]
gas/NOTES.config [new file with mode: 0644]
gas/README-vms-dbg [new file with mode: 0644]
gas/README.coff [new file with mode: 0644]
gas/README.rich [new file with mode: 0644]
gas/VERSION [new file with mode: 0755]
gas/config/ho-ansi.h
gas/config/ho-cygnus.h
gas/config/ho-decstation.h [new file with mode: 0644]
gas/config/ho-generic.h
gas/config/ho-rs6000.h [new file with mode: 0644]
gas/config/ho-vax.h [new file with mode: 0644]
gas/config/mh-cygnus [new file with mode: 0755]
gas/config/mh-i386 [new file with mode: 0644]
gas/config/obj-bfd-sunos.c [new file with mode: 0644]
gas/config/obj-bfd-sunos.h [new file with mode: 0644]
gas/config/te-motor.h [new file with mode: 0755]
gas/config/te-sco386.h [new file with mode: 0644]
gas/config/te-sparc.h [new file with mode: 0755]
gas/config/te-unisoft.h [new file with mode: 0755]
gas/config/tmake-sun3 [new file with mode: 0755]
gas/config/vms/objrecdef.h [new file with mode: 0644]
gas/config/vms/vms-dbg.c [new file with mode: 0644]
gas/config/vms/vms.c [new file with mode: 0644]
gas/make-gas.com [new file with mode: 0644]
gas/obsolete/gdb-blocks.c [new file with mode: 0644]
gas/obsolete/gdb-file.c [new file with mode: 0644]
gas/obsolete/gdb-lines.c [new file with mode: 0644]
gas/obsolete/gdb-symbols.c [new file with mode: 0644]
gas/obsolete/gdb.c [new file with mode: 0644]
gas/ver960.c [new file with mode: 0644]
gas/version.c [new file with mode: 0644]

diff --git a/gas/.gdbinit b/gas/.gdbinit
new file mode 100644 (file)
index 0000000..2044214
--- /dev/null
@@ -0,0 +1,4 @@
+break as_warn
+break as_bad
+break as_fatal
+set caution off
diff --git a/gas/GNUmakefile-host b/gas/GNUmakefile-host
new file mode 100755 (executable)
index 0000000..386c869
--- /dev/null
@@ -0,0 +1,6 @@
+ALL := $(shell ls -d =*)
+
+%:
+       $(foreach subdir,$(ALL),$(MAKE) -C $(subdir) $@ &&) true
+
+gas:
diff --git a/gas/Makefile.loic b/gas/Makefile.loic
new file mode 100755 (executable)
index 0000000..4de7da1
--- /dev/null
@@ -0,0 +1,203 @@
+# Makefile for GAS.
+# Copyright (C) 1989, Free Software Foundation
+# 
+# This file is part of GAS, the GNU Assembler.
+# 
+# GAS 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 1, or (at your option)
+# any later version.
+# 
+# GAS 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 GAS; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+BINDIR = /usr/local/bin
+
+BINARY = gas
+
+#
+# Add these flags to XCFLAGS below for specific use.
+#
+# If you machine does not have vfprintf, but does have _doprnt(),
+# -DNO_VARARGS
+#
+# If the return-type of a signal-hander is void (instead of int),
+# -DSIGTY
+#
+# To include the mc68851 mmu coprocessor instructions in the 68020 assembler,
+# -Dm68851 
+#
+# If you want the 80386 assembler to correctly handle fsub/fsubr and fdiv/fdivr
+# opcodes (unlike most 80386 assemblers)
+# -DNON_BROKEN_WORDS
+#
+XCFLAGS =
+
+# Your favorite compiler
+CC = gcc
+
+# Uncomment the following lines if you use USG
+
+INCLUDE_DIRS = -I.
+COFF_OBJECTS = stack.o
+CPPFLAGS = -DUSG
+CFLAGS = -g $(CPPFLAGS) $(XCFLAGS)
+LDFLAGS = 
+#LOADLIBES = -lPW
+
+# Uncomment the following lines if you use BSD
+#INCLUDE_DIRS = -I.
+#CPPFLAGS = 
+#CFLAGS = -g $(CPPFLAGS) $(XCFLAGS)
+#LDFLAGS = 
+#LOADLIBES =
+
+CONFIG_FILES = \
+       machine.c machine.h atof.c obj-format.c obj-format.h opcode.h
+
+OBJECTS = \
+       as.o xrealloc.o xmalloc.o hash.o hex-value.o \
+       atof-generic.o append.o messages.o expr.o app.o \
+       frags.o input-file.o input-scrub.o output-file.o \
+       subsegs.o symbols.o version.o flonum-const.o flonum-copy.o \
+       flonum-mult.o strstr.o bignum-copy.o obstack.o write.o read.o \
+       obj-format.o machine.o atof.o $(COFF_OBJECTS)
+
+SOURCES = $(OBJECTS:.o=.c)
+
+all : $(BINARY)
+
+install : all
+       cp $(BINARY) $(BINDIR)
+
+clean : 
+       rm -f $(OBJECTS)
+
+clobber : clean
+       rm -f $(BINARY) $(CONFIG_FILES) dependencies TAGS m68k.h
+
+$(BINARY) : $(OBJECTS)
+       $(CC) -o $(BINARY) $(LDFLAGS) $(OBJECTS) $(LOADLIBES)
+
+TAGS : $(SOURCES)
+       etags $(SOURCES) *.h
+
+CXREF : $(SOURCES)
+       cxref -c $(INCLUDE_DIRS) $(SOURCES)
+
+stack.o: stack.c
+       $(CC) $(CFLAGS) -c stack.c
+
+atof.o: \
+       flonum.h \
+       bignum.h
+obj-format.o: \
+       as.h \
+       md.h \
+       aout.h \
+       a.out.gnu.h \
+       struc-symbol.h \
+       write.h \
+       append.h
+read.o: \
+       obj-format.h \
+       a.out.gnu.h \
+       as.h \
+       read.h \
+       md.h \
+       hash.h \
+       obstack.h \
+       frags.h \
+       flonum.h \
+       bignum.h \
+       struc-symbol.h \
+       expr.h \
+       symbols.h \
+       sparc.h
+write.o: \
+       obj-format.h \
+       a.out.gnu.h \
+       as.h \
+       md.h \
+       subsegs.h \
+       obstack.h \
+       struc-symbol.h \
+       write.h \
+       symbols.h \
+       append.h \
+       sparc.h
+obstack.o: \
+       obstack.h
+bignum-copy.o: \
+       bignum.h
+flonum-mult.o: \
+       flonum.h \
+       bignum.h
+flonum-copy.o: \
+       flonum.h \
+       bignum.h
+flonum-const.o: \
+       flonum.h \
+       bignum.h
+symbols.o: \
+       obj-format.h \
+       a.out.gnu.h \
+       as.h \
+       hash.h \
+       obstack.h \
+       struc-symbol.h \
+       symbols.h \
+       frags.h
+subsegs.o: \
+       obj-format.h \
+       a.out.gnu.h \
+       as.h \
+       subsegs.h \
+       obstack.h \
+       frags.h \
+       struc-symbol.h \
+       write.h
+input-scrub.o: \
+       as.h \
+       read.h \
+       input-file.h
+input-file.o: \
+       input-file.h
+frags.o: \
+       obj-format.h \
+       a.out.gnu.h \
+       as.h \
+       subsegs.h \
+       obstack.h \
+       frags.h \
+       struc-symbol.h
+expr.o: \
+       obj-format.h \
+       a.out.gnu.h \
+       as.h \
+       flonum.h \
+       bignum.h \
+       read.h \
+       struc-symbol.h \
+       expr.h \
+       obstack.h \
+       symbols.h
+messages.o: \
+       as.h
+atof-generic.o: \
+       flonum.h \
+       bignum.h
+hash.o: \
+       hash.h
+as.o: \
+       obj-format.h \
+       a.out.gnu.h \
+       as.h \
+       struc-symbol.h \
+       write.h
diff --git a/gas/Makefile.old b/gas/Makefile.old
new file mode 100644 (file)
index 0000000..9cbb532
--- /dev/null
@@ -0,0 +1,434 @@
+# Makefile for GAS.
+# Copyright (C) 1989, Free Software Foundation
+# 
+# This file is part of GAS, the GNU Assembler.
+# 
+# GAS 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 1, or (at your option)
+# any later version.
+# 
+# GAS 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 GAS; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+# This makefile may be used to make the VAX, 68020, 80386, 
+# SPARC, AMD 29000, ns32k, or i860 assembler(s).
+ALL = asm29k avax a68 a386 asparc a32k a860 a960
+MDSRC=vax.c m68k.c i386.c sparc.c am29k.c ns32k.c
+
+BINDIR = $(DESTDIR)/bin
+
+# If you are on a BSD system, un-comment the next two lines, and comment out
+# the lines for SystemV and HPUX below
+#G0 = -g  -I. #-O -Wall
+#LDFLAGS = $(CFLAGS)
+#
+# To compile gas on a System Five machine, comment out the two lines above
+# and un-comment out the next three lines
+# Comment out the -lPW on the LOADLIBES line if you are using GCC.
+G0 = -g -I. -DUSG
+LDFLAGS = $(CFLAGS)
+LOADLIBES = # -lmalloc -lPW
+#
+# To compile gas for HPUX, link m-hpux.h to m68k.h , and un-comment the
+# next two lines.  (If you are using GCC, comment out the alloca.o part)
+# (Get alloca from the emacs distribution, or use GCC.)
+# HPUX 7.0 may have a bug in setvbuf.  gas gives an error message like
+# 1:"Unknown operator" -- Statement 'NO_APP' ignored
+# if setvbuf is broken.  Re-compile input-file.c (and only input-file.c
+# with -DVMS and the problem should go away.
+#
+# G0 = -g -I. -DUSG
+# LOADLIBES = alloca.o
+#
+# To compile gas for a Sequent Symmetry, comment out all the above lines,
+# and un-comment the next two lines.
+# G0 = -g -I. -DUSE_SYSTEM_HDR -DEXEC_VERSION=1
+# LOADLIBES = -lc /usr/att/lib/libc.a
+
+# Use these lines to build gas using hc.
+#CC=hc29 -cmdlink.cmd -Dconst= -I../include/msdos
+#CC=gcc29k
+#LOADLIBES= ../binutils/alloca.o
+
+# If you just want to compile the vax assembler, type 'make avax'
+
+# If you just want to compile the i386 assembler, type 'make a386'
+
+# If you just want to compile the ns32k assembler, type 'make a32k'
+
+# If you just want to compile the sparc assembler, type 'make asparc'
+
+# If you just want to compile the AMD 29000 assembler, type 'make asm29k'
+
+# If you just want to compile the a860 assembler, type 'make a860'
+
+# If you just want to compile the a960 assembler, type 'make a960'
+
+# If you just want to compile the mc68020 assembler, make sure m68k.h
+# is correctly set up, and type type 'make a68'  (Except on HPUX machines,
+# where you will have to make the changes marked below before typing
+# 'make a68'
+# m68k.h should be a symbolic or hard-link to one of
+# m-sun3.h , m-hpux.h or m-generic.h
+# depending on which machine you want to compile the 68020 assembler for.
+#
+# If you want the 68k assembler to be completely compatable with the the
+# SUN one, un-comment the -DLOCAL_LABELS_FB and -DLOCAL_LABELS_DOLLAR
+# lines below.
+#
+# Gas prefers STDARG's, but if your machine doesn't have stdarg.h, you
+# should define remove the # from the -DNO_STDARG line below.  In this
+# case gas will try to use VARARGS instead.  (but keep reading).
+#
+# If your machine does not have vfprintf, but does have _doprnt(),
+# remove the # from the -DNO_VARARGS line below.
+#
+# If the return-type of a signal-hander is void (instead of int),
+# remove the # from the -DSIGTY line below.
+#
+# To include the mc68851 mmu coprocessor instructions in the 68020 assembler,
+# remove the # from the -Dm68851 line below.
+#
+# If you want the 68020 assembler use a register prefix character, un-comment
+# the REGISTER_PREFIX line, and (maybe) change the '%' to the appropriate
+# character.
+#
+# If you want the assembler to treat .L* or ..* symbols as local, instead of
+# the usual L* symbols, un-comment the DOT_LABEL_PREFIX line.
+#
+# If you want the 80386 assembler to correctly handle fsub/fsubr and fdiv/fdivr
+# opcodes (unlike most 80386 assemblers), remove the # from
+# the -DNON_BROKEN_WORDS line below.
+#
+# To compile 80386 Gas for the Sequent Symmetry, un-comment the -DEXEC_VERSION
+# and the -DUSE_SYSTEM_HDR lines below.
+#
+# To compile gas for the HP 9000/300 un-comment the -DUSE_HP_HDR line below.
+#
+# For the ns32k, the options are 32532 or 32032 CPU and 32381 or 32081 FPU.
+# To select the NS32532, remove the # from the -DNS32532 line below.
+# To compile in tne NS32381 opcodes in addition to the NS32081 opcodes
+# (the 32381 is a superset of the 32081), remove the # from the -DNS32381
+# line below.
+#
+# For the ns32k on a Sequent, uncomment the SEQUENT_COMPATABILITY line below.
+#
+# If you want character constants to *require* closing single quotes,
+# eg 'c' rather than 'c then use the -DREQUIRE_CHAR_CLOSE_QUOTE lines
+# below.  The default is for the closing quote to be optional.
+#
+# To produce intel's b.out format, use the B_OUT line below.
+#
+# if you want to allow "\v" to mean a control-k, use the BACKSLASH_V
+# line below.
+
+# [Why is there a distinction between "Ox" and "Gx"?  It would seem easier
+#  to not have to figure out that your code isn't working because some
+#  define's are only seen by some modules and you tested it in a module
+#  where it never gets defined...  gnu@cygnus.com]
+
+O1 = -DNO_STDARG
+O2 = # -DNO_VARARGS
+O3 = # -DNON_BROKEN_WORDS
+O4 = # -Dm68851
+O5 = # -DEXEC_VERSION=1
+O6 = # -DSIGTY=void
+O6 = # -DNS32532
+O7 = # -DNS32381
+O8 = # -DDOT_LABEL_PREFIX
+O9 = # -DSEQUENT_COMPATABILITY
+
+G1 = # -DREGISTER_PREFIX=\'%\'
+G2 = # -DUSE_SYSTEM_HDR
+G3 = # -DUSE_HP_HDR
+G4 = # -DLOCAL_LABELS_DOLLAR
+G5 = # -DLOCAL_LABELS_FB
+G6 = #  -DDEBUG
+G7 = # -DREQUIRE_CHAR_CLOSE_QUOTE
+G8 = -DB_OUT
+G9 = -DBACKSLASH_V
+
+OPTIONS = $(O1) $(O2) $(O3) $(O4) $(O5) $(O6) $(O7) $(O8) $(O9)
+
+CFLAGS = $(G0) $(G1) $(G2) $(G3) $(G4) $(G5) $(G6) $(G7) $(G8) $(G9) $(OPTIONS)
+
+#
+# To make the 68020 assembler compile as the default, un-comment the next
+# line, and comment out all the other lines that start with DEFAULT_GAS
+#DEFAULT_GAS=a68
+#
+# To make the VAX assembler compile as the default, un-comment the next
+# line and commment out all the other lines that start with DEFAULT_GAS
+#DEFAULT_GAS=avax
+#
+# To make the 80386 assembler compile as the default, un-comment the next
+# line and commment out all the other lines that start with DEFAULT_GAS
+#DEFAULT_GAS=a386
+#
+# To make the ns32k assembler compile as the default, un-comment the next
+# line and commment out all the other lines that start with DEFAULT_GAS
+#DEFAULT_GAS=a32k
+#
+# To make the sparc assembler compile as the default, un-comment the next
+# line and commment out all the other lines that start with DEFAULT_GAS
+#DEFAULT_GAS=asparc
+#
+#
+# To make the i860 assembler compile as the default, un-comment the next
+# line and comment out all the other lines that start with DEFAULT_GAS
+#DEFAULT_GAS=a860
+#
+# To make the asm29k assembler compile as the default, un-comment the next
+# line and commment out all the other lines that start with DEFAULT_GAS
+#DEFAULT_GAS=asm29k
+#
+# To make the i960 assembler compile as the default, un-comment the next
+# line and commment out all the other lines that start with DEFAULT_GAS
+#DEFAULT_GAS=a960
+
+# Global Sources -------------------------------------------------------------
+
+a =\
+as.o           xrealloc.o      xmalloc.o       hash.o          hex-value.o   \
+atof-generic.o messages.o      expr.o          app.o         \
+frags.o                input-file.o    input-scrub.o   output-file.o                 \
+subsegs.o      symbols.o                                       version.o     \
+flonum-const.o flonum-copy.o   flonum-mult.o   strstr.o        bignum-copy.o \
+obstack.o      cond.o
+#gdb.o         gdb-file.o      gdb-symbols.o   gdb-blocks.o    gdb-lines.o
+
+a:     $(DEFAULT_GAS)
+       @rm -f a
+       @ln $(DEFAULT_GAS) a
+
+# i960 GAS ------------------------------------------------------------------
+t = i960.o i960-opcode.o atof-ieee.o ver960.o read-i960.o write-i960.o
+
+T = i960.c i960-opcode.c atof-ieee.c ver960.c
+
+i960.o:        i960.c i960-opcode.h as.h frags.h struc-symbol.h
+i960.o:        flonum.h expr.h hash.h md.h write.h read.h symbols.h
+       $(CC) -c $(CFLAGS) -DI80960 i960.c
+
+write-i960.o:  write.c
+       $(CC) -c $(CFLAGS) write.c
+       mv write.o write-i960.o
+
+read-i960.o: read.c
+       $(CC) -c $(CFLAGS) read.c
+       mv read.o read-i960.o
+
+a960_cheat: $a $t
+       $(CC) -o a960 $(LDFLAGS) $a $t $(LOADLIBES)
+
+a960: force
+       $(MAKE) 'CFLAGS=$(CFLAGS) -DI80960' a960_cheat
+
+force:
+
+# AM29K GAS ------------------------------------------------------------------
+u = am29k.o  atof-ieee.o  write.o  read.o
+
+U = am29k.c  am29k-opcode.h
+
+am29k.o:       am29k.c a.out.gnu.h as.h expr.h flonum.h frags.h hash.h
+am29k.o:       am29k-opcode.h md.h obstack.h struc-symbol.h
+       $(CC) $(CFLAGS) -c am29k.c
+
+asm29k: $a $u
+       $(CC) -o asm29k $(LDFLAGS) $a $u $(LOADLIBES)
+
+# I860 GAS ------------------------------------------------------------------
+u = i860.o  atof-ieee.o  write.o  read.o
+
+U = i860.c i860-opcode.h
+
+i860.o:        i860.c i860-opcode.h as.h frags.h struc-symbol.h
+i860.o:        flonum.h expr.h hash.h md.h write.h read.h symbols.h
+       $(CC) -c $(CFLAGS) i860.c
+
+atof-ieee.o:   flonum.h
+
+a860: $a $u
+       $(CC) -o a860 $(LDFLAGS) $a $u $(LOADLIBES)
+
+# SPARC GAS ------------------------------------------------------------------
+v = sparc.o  atof-ieee.o  write.o  read.o
+
+V = sparc.c  sparc-opcode.h
+
+atof-ieee.o:   flonum.h
+sparc.o:       sparc.c reloc.h sparc-opcode.h as.h frags.h struc-symbol.h
+sparc.o:       flonum.h expr.h hash.h md.h write.h read.h symbols.h
+       $(CC) -c $(CFLAGS) -DSPARC sparc.c
+
+asparc: $a $v
+       $(CC) -o asparc $(LDFLAGS) $a $v $(LOADLIBES)
+
+# NS32K GAS ------------------------------------------------------------------
+w = ns32k.o  atof-ieee.o  write-ns32k.o  read-ns32k.o
+
+W = ns32k.c ns32k-opcode.h
+
+atof-ieee.o:   flonum.h
+ns32k.o:       as.h frags.h struc-symbol.h flonum.h expr.h md.h hash.h
+ns32k.o:       write.h symbols.h ns32k-opcode.h ns32k.c
+       $(CC) $(CFLAGS) $(OPTIONS) -c ns32k.c
+
+write-ns32k.o: write.c
+       rm -f write-ns32k.c
+       cp write.c write-ns32k.c
+       $(CC) -c -DNS32K $(CFLAGS) write-ns32k.c
+       rm -f write-ns32k.c
+
+read-ns32k.o: read.c
+       rm -f read-ns32k.c
+       cp read.c read-ns32k.c
+       $(CC) -c -DNS32K $(CFLAGS) read-ns32k.c
+       rm -f read-ns32k.c
+
+a32k: $a $w
+       $(CC) -o a32k $(LDFLAGS) $a $w $(LOADLIBES)
+
+# 80386 GAS ------------------------------------------------------------------
+x = i386.o  atof-ieee.o  write.o  read.o
+
+X = i386.c  i386.h  i386-opcode.h
+
+i386.o:                i386.c as.h read.h flonum.h frags.h struc-symbol.h expr.h
+i386.o:                symbols.h hash.h md.h i386.h i386-opcode.h
+       $(CC) $(CFLAGS) $(OPTIONS) -c i386.c
+
+atof-ieee.o:   flonum.h
+
+a386: $a $x
+       $(CC) -o a386 $(LDFLAGS) $a $x $(LOADLIBES)
+
+# 68020 GAS ------------------------------------------------------------------
+y = m68k.o  atof-ieee.o write.o read.o
+
+Y = m68k.c atof-ieee.c m68k-opcode.h m-hpux.h m-sun3.h m-generic.h
+
+atof-ieee.o:   flonum.h
+
+m68k.o:                m68k.c a.out.gnu.h as.h expr.h flonum.h frags.h hash.h
+m68k.o:                m68k-opcode.h m68k.h md.h obstack.h struc-symbol.h
+       $(CC) $(CFLAGS) $(OPTIONS) -c m68k.c
+
+a68: $a $y
+       $(CC) -o a68 $(LDFLAGS) $a $y $(LOADLIBES)
+
+# VAX GAS --------------------------------------------------------------------
+z = vax.o  atof-vax.o  write.o  read.o
+
+Z = vax.c atof-vax.c vax-opcode.h vax-inst.h \
+    make-gas.com objrecdef.h vms.c vms-dbg.c README-vms-dbg
+
+vax.o:         vax.c a.out.gnu.h as.h expr.h flonum.h frags.h md.h obstack.h
+vax.o:         read.h struc-symbol.h symbols.h vax-inst.h vax-opcode.h
+atof-vax.o:    as.h flonum.h read.h
+
+avax:  $a $z
+       $(CC) -o avax $(LDFLAGS) $a $z $(LOADLIBES)
+
+# global files ---------------------------------------------------------------
+
+hash.o:        hash.c
+       $(CC) $(CFLAGS) -Derror=as_fatal -c hash.c
+
+xmalloc.o:     xmalloc.c
+       $(CC) $(CFLAGS) -Derror=as_fatal -c xmalloc.c
+
+xrealloc.o:    xrealloc.c
+       $(CC) $(CFLAGS) -Derror=as_fatal -c xrealloc.c
+
+A =\
+as.c           xrealloc.c      xmalloc.c       hash.c          hex-value.c \
+atof-generic.c messages.c      expr.c          bignum-copy.c \
+frags.c                input-file.c    input-scrub.c   output-file.c   read.c \
+subsegs.c      symbols.c       write.c                         strstr.c \
+flonum-const.c flonum-copy.c   flonum-mult.c   app.c           version.c \
+obstack.c      cond.c \
+#gdb.c         gdb-file.c      gdb-symbols.c   gdb-blocks.c \
+#gdb-lines.c
+
+H = \
+a.out.gnu.h    as.h            bignum.h        expr.h          flonum.h \
+frags.h                hash.h          input-file.h    md.h     \
+obstack.h      read.h          reloc.h         struc-symbol.h  subsegs.h \
+symbols.h      write.h
+
+dist: COPYING README ChangeLog $A $H $U $V $W $X $Y $Z Makefile
+       echo gas-`sed -n -e '/ version /s/[^0-9.]*\([0-9.]*\).*/\1/p' < version.c` > .fname
+       mkdir `cat .fname`
+
+       ln COPYING README ChangeLog $A $H $U $V $W $X $Y $Z Makefile `cat .fname`
+       tar cvhZf `cat .fname`.tar.Z `cat .fname`
+       -rm -rf .fname `cat .fname`
+
+clean:
+       rm -f a avax a68 a386 a32k asparc asm29k a860 a960 $a $u $v $w $x $y $z a core gmon.out bugs a.out
+
+all:   $(ALL)
+
+install:  install_tools
+install_tools: a
+       cp a $(BINDIR)/as
+
+# For things like:  emacs `make mdsrc`
+mdsrc:
+       @ls $(MDSRC)
+
+LINT = /usr/5bin/lint
+LINTFLAGS =
+
+lint:
+       $(LINT) $(LINTFLAGS) $(CFLAGS) $A
+
+# General .o-->.h dependencies
+
+app.o:         as.h
+as.o:          a.out.gnu.h as.h read.h struc-symbol.h write.h
+atof-generic.o:        flonum.h
+bignum-copy.o: bignum.h
+expr.o:                a.out.gnu.h as.h expr.h flonum.h obstack.h read.h struc-symbol.h
+expr.o:                 symbols.h
+flonum-const.o:        flonum.h
+flonum-copy.o: flonum.h
+flonum-mult.o: flonum.h
+flonum-normal.o:flonum.h
+flonum-print.o:        flonum.h
+frags.o:       a.out.gnu.h as.h frags.h obstack.h struc-symbol.h subsegs.h
+#gdb.o:                as.h
+#gdb-blocks.o: as.h
+#gdb-lines.o:  as.h frags.h obstack.h
+#gdb-symbols.o:        a.out.gnu.h as.h struc-symbol.h
+hash.o:                hash.h
+input-file.o:  input-file.h
+input-scrub.o: as.h input-file.h read.h
+messages.o:    as.h
+obstack.o:     obstack.h
+read.o:                a.out.gnu.h as.h expr.h flonum.h frags.h hash.h md.h obstack.h
+read.o:                read.h struc-symbol.h symbols.h reloc.h
+subsegs.o:     a.out.gnu.h as.h frags.h obstack.h struc-symbol.h subsegs.h write.h
+symbols.o:     a.out.gnu.h as.h frags.h hash.h obstack.h struc-symbol.h symbols.h
+write.o:       a.out.gnu.h as.h md.h obstack.h struc-symbol.h subsegs.h
+write.o:       symbols.h write.h reloc.h
+
+flonum.h:                                      bignum.h
+
+etags tags: TAGS
+
+TAGS: force
+       etags Makefile* README* config.gas *.[hc]
+
+force:
+
+# End of Makefile
diff --git a/gas/NOTES b/gas/NOTES
new file mode 100644 (file)
index 0000000..0669aa7
--- /dev/null
+++ b/gas/NOTES
@@ -0,0 +1,19 @@
+to do:
+
+fucked up on a.out.gnu.h, etc.
+fucked up on foo-opcode.h.
+remove the ifdef's from fx_callj tests?
+what are callj tests?
+search for (), build prototypes.
+space tighten sparc alignment.
+convert md_ri_to_chars to not pass structs.
+convert md_ri_to_chars to emit fixP's.
+fix number_to_chars, & family to have no side effects.
+prototype.
+md_ => tp_
+use CROSS_ASSEMBLE
+multiple segments.
+share b.out with a.out.
+
+
+stack:
diff --git a/gas/NOTES.config b/gas/NOTES.config
new file mode 100644 (file)
index 0000000..e12797d
--- /dev/null
@@ -0,0 +1,52 @@
+
+                     The GAS Configuration Plan
+
+Theory:
+
+The goal of the new configuration scheme is to bury all object format,
+target processor, and host machine dependancies in object, target, and
+host specific files.  That is, to move all #ifdef's out of the gas
+common code.
+
+Here's how it works.  There is a .h and a .c file for each object file
+format, a .h and a .c file for each target processor, and a .h for
+each host.  config.gas creates {sym}links in the current directory to
+the appropriate files in the config directory.  config.gas also serves
+as a list of triplets {host, target, object-format} that have been
+tested at one time or another.  I also recommend that config.gas be
+used to document triplet specific notes as to purpose of the triplet,
+etc.
+
+Implementation:
+
+host.h is a {sym}link to .../config/xm-yourhost.h.  It is intended to
+be used to hide host compiler, system header file, and system library
+differences between host machines.  If your host needs actual c source
+files, then either: these are generally useful functions, in which
+case you should probably build a local library outside of the gas
+source tree, or someone, perhaps me, is confused about what is needed
+by different hosts.
+
+obj-format.h is a {sym}link to .../config/obj-something.h.  It is intended
+
+All gas .c files include as.h.
+
+as.h #define's "gas", includes host.h, defines a number of gas
+specific structures and types, and then includes tp.h, obj.h, and
+target-environment.h.
+
+target-environment.h defines a target environment specific
+preprocessor flag, eg, TE_SUN, and then includes obj-format.h.
+
+obj-format.h defines an object format specific preprocessor flag, eg,
+OBJ_AOUT, OBJ_BOUT, OBJ_COFF, includes "target-processor.h", and then
+defines the object specific macros, functions, types, and structures.
+
+target-processor.h 
+
+target-processor.
+
+Porting:
+
+There appear to be four major types of ports; new hosts, new target
+processors, new object file formats, and new target environments.
diff --git a/gas/README-vms-dbg b/gas/README-vms-dbg
new file mode 100644 (file)
index 0000000..61ab6dd
--- /dev/null
@@ -0,0 +1,127 @@
+       1) You should be aware that GNU-C, as with any other decent compiler,
+will do things when optimization is turned on that you may not expect. 
+Sometimes intermediate results are not written to variables, if they are only
+used in one place, and sometimes variables that are not used at all will not be
+written to the symbol table.  Also, parameters to inline functions are often
+inaccessible. You can see the assembly code equivalent by using KP7 in the
+debugger, and from this you can tell if in fact a variable should have the
+value that you expect.  You can find out if a variable lives withing a register
+by doing a 'show symbol/addr'.
+
+       2) Overly complex data types, such as:
+
+int (*(*(*(*(*(* sarr6)[1])[1])[2])[3])[4])[5];
+
+will not be debugged properly, since the debugging record overflows an internal
+debugger buffer.  gcc-as will convert these to *void as far as the debugger
+symbol table is concerned, which will avoid any problems, and the assembler
+will give you a message informing you that this has happened.
+
+       3) You must, of course, compile and link with /debug.  If you link
+without debug, you still get traceback table in the executable, but there is no
+symbol table for variables.
+
+       4) Included in the patches to VMS.C are fixes to two bugs that are
+unrelated to the changes that I have made.  One of these made it impossible to
+debug small programs sometimes, and the other caused the debugger to become
+confused about which routine it was in, and give this incorrect info in
+tracebacks.
+
+       5) If you are using the GNU-C++ compiler, you should modify the
+compiler driver file GNU_CC:[000000]GCC.COM (or GXX.COM).  If you have a
+seperate GXX.COM, then you need to change one line in GXX.COM to:
+$ if f$locate("D",p2) .ne. P2_Length then Debug = " ""-G0"""
+                                       Notice zero--->  ^
+If you are using a GCC.COM that does both C and C++, add the following lines to
+GCC.COM:
+
+$!
+$! Use old style debugging records for VMS
+$!
+$ if (Debug.nes."" ).and. Plus then Debug = " ""-G0"""
+
+after the variables Plus and Debug are set.  The reason for this, is that C++
+compiler by default generates debugging records that are more complex,
+with many new syntactical elements that allow for the new features of the
+language.  The -G0 switch tells the C++ compiler to use the old style debugging
+records.  Until the debugger understands C++ there is not any point to try and
+use the expanded syntax.
+
+       6) When you have nested scopes, i.e.:
+main(){
+       int i;
+       {int i;
+               {int i;
+};};}
+and you say "EXAM i" the debugger needs to figure out which variable you
+actually want to reference.  I have arranged things to define a block to the
+debugger when you use brackets to enter a new scope, so in the example above,
+the variables would be described as:
+TEST\main\i
+TEST\main\$0\i
+TEST\main\$0\$0\i
+At each level, the block name is a number with a dollar sign prefix, the
+numbers start with 0 and count upward.  When you say EXAM i, the debugger looks
+at the current PC, and decides which block it is currently in.  It works from
+the innermost level outward until it finds a block that has the variable "i"
+defined.  You can always specify the scope explicitly.
+
+       7)  With C++, there can be a lot of inline functions, and it would be
+rather restrictive to force the user to debug the program by converting all of
+the inline functions to normal functions.  What I have done is to essentially
+"add" (with the debugger) source lines from the include files that contain the
+inline functions.  Thus when you step into an inline function it appears as if
+you have called the function, and you can examine variables and so forth. 
+There are several *very* important differences, however.  First of all, since
+there is no function call involved, you cannot step over the inline function
+call - you always step into it. Secondly, since the same source lines are used
+in many locations, there is a seperate copy of the source for *each* usage. 
+Without this, breakpoints do not work, since we must have a 1-to-1 mapping
+between source lines and PC.
+       Since you cannot step over inline function calls, it can be a real pain
+if you are not really interested in what is going on for that function call.
+What I have done is to use the "-D" switch for the assembler to toggle the
+following behavior.  With the "-D" switch, all inline functions are included in
+the object file, and you can debug everything.  Without the "-D" switch
+(default case with VMS implementation), inline functions are included *only* if
+they did not come from system header files (i.e. from GNU_CC_INCLUDE: or
+GNU_GXX_INCLUDE:).  Thus, without the switch the user only debugs his/her own
+inline functions, and not the system ones. (This is especially useful if you do
+a lot of stream I/O in C++).  This probably will not provide enough granularity
+for many users, but for now this is still somewhat experimental, and I would
+like to reflect upon it and get some feedback before I go any further. 
+Possible solutions include an interactive prompting, a logical name, or a new
+command line option in gcc.c (which is then passed through somehow to the guts
+of the assembler).
+       The inline functions from header files appear after the source code
+for the source file.  This has the advantage that the source file itself is
+numbered with the same line numbers that you get with an editor.  In addition,
+the entire header file is not included, since the assembler makes a list of
+the min and max source lines that are used, and only includes those lines from
+the first to the last actually used. (It is easy to change it to include the
+whole file).
+
+       8) When you are debugging C++ objects, the object "this" is refered to
+as "$this".  Actually, the compiler writes it as ".this", but the period is
+not good for the debugger, so I have a routine to convert it to a $.  (It
+actually converts all periods to $, but only for variables, since this was
+intended to allow us to access "this".
+
+       9) If you use the asm("...") keyword for global symbols, you will not
+be able to see that symbol with the debugger.  The reason is that there are two
+records for the symbol stored in the data structures of the assembler.  One
+contains the info such as psect number and offset, and the other one contains
+the information having to do with the data type of the variable.  In order to
+debug as symbol, you need to be able to coorelate these records, and the only
+way to do this is by name.  The record with the storage attributes will take
+the name used in the asm directive, and the record that specifies the data type
+has the actual variable name, and thus when you use the asm directive to change
+a variable name, the symbol becomes invisible.
+
+       10) Older versions of the compiler ( GNU-C 1.37.92 and earlier) place
+global constants in the text psect.  This is unfortunate, since to the linker
+this appears to be an entry point.  I sent a patch to the compiler to RMS,
+which will generate a .const section for these variables, and patched the
+assembler to put these variables into a psect just like that for normal
+variables, except that they are marked NOWRT.  static constants are still
+placed in the text psect, since there is no need for any external access.
diff --git a/gas/README.coff b/gas/README.coff
new file mode 100644 (file)
index 0000000..46c61cd
--- /dev/null
@@ -0,0 +1,79 @@
+The coff patches intend to do the following :
+
+   . Generate coff files very compatible with vanilla linker.
+   . Understands coff debug directives.
+
+Here are the guidelines of the work I have done :
+
+   . Encapsulate format dependent code in macros where it is possible.
+   . Where not possible differenciate with #ifdef
+   . try not to change the calling conventions of the existing functions. 
+       I made one exception : symbol_new. I would be pleased to hear about
+       a better solution. (symbols.c)
+   . Extend the use of N_TYPE_seg seg_N_TYPE tables so that segments can
+       be manipulated without using their format dependent name. (subsegs.c)
+   . Write a function to parse the .def debug directives
+   . Write two small peaces of code to handle the .ln directive.
+   . In write.c try to move all the cross compilation specifics (md_..) to
+     format dependent files.
+   . Encapsulate the data structures using generic types, macros calls.
+   . Added too much code to resolve the complexity of the symbol table
+     generated. Most of the code deals with debug stuff.
+   . Create another makefile, shorter, cleaner.
+   . Create a config.gas shell script to mimic the gcc,gdb... configuration
+       mechanism. This reduce the complexity of the makefile.
+   . Isolate the format dependent code in two files 
+       coff.c coff.h
+       aout.c aout.h
+       elf.c elf.h    [ Not yet ;-]
+   . added a little stack management routine for coff in file stack.c
+   . isolate os specific flags in m- files
+
+If further development is planed on it is should solve the following problems :
+
+   . Encapsulate DESC & OTHER tests in a macro call. I'm not aware
+       of their exact semantics.
+   . Clean up the seg_N_TYPE N_TYPE_seg naming scheme
+   . Try to remove as much reference to segment dependent names as possible
+   . Find a cleaner solution for symbol_new.
+   . Report the modifications on vax, ns32k, sparc machine dependent files.
+       To acheive this goal, search for \<N_, sy_, symbol_new and symbolS.
+   . Allow an arbitrary number of segments (spare sections .ctor .dtor .bletch)
+   . Find a way to extend the debug information without breaking sdb
+     compatibility. Mainly intended for G++.
+   . should it do something to generate shared libraries objects ?
+
+I have tested this code on the following processor/os. gcc-1.37.1 was
+   used for all the tests.
+
+386    SCO unix ODT
+       gcc-1.37.1, gas, emacs-18.55
+
+386    Esix rev C
+       gas-1.37/write.s
+
+386    Ix 2.02
+       gas, all the X11R4 mit clients
+
+386    CTIX 3.2
+       xsol (X11R4 solitary game), gas
+
+68030  unisoft 1.3     
+       the kernel (V.3.2) + tcp/ip extensions
+       bash-1.05, bison-1.11, compress-4.0, cproto, shar-3.49, diff-1.14,
+       dist-18.55, flex-2.3, gas-1.37, gcc-1.37.1, gdb-3.6, grep-1.5,
+       kermit, make-3.58, makedep, patch, printf, makeinfo, g++-1.37.1,
+       tar-1.08, texi2roff, uuencode, uutraf-1.2, libg++-1.37.2, groff-0.5
+
+68020  sunos 3.5 (no, not coff, just to be sure that I didn't
+                       introduce errors)
+       gcc-1.37.1, gas, emacs-18.55, gdb-3.6, bison-1.11, diff-1.14, 
+       make-3.58, tar-1.08
+
+68030   sunos 4.0.3 (idem)
+       gas
+
+I would be glad to hear about new experiences
+
+       Loic  (loic@adesign.uucp or loic@afp.uucp)
+
diff --git a/gas/README.rich b/gas/README.rich
new file mode 100644 (file)
index 0000000..1ac53c7
--- /dev/null
@@ -0,0 +1,143 @@
+
+
+                The Code Pedigree of This Directory
+
+
+This directory contains a big merge of several development lines of
+gas as well as a few bug fixes and some configuration that I've added
+in order to retain my own sanity.
+
+A little history.
+
+The only common baseline of all versions was gas-1.31.
+
+From 1.31, Intel branched off and added:
+
+       support for the Intel 80960 (i960) processor.
+       support for b.out object files.
+       some bug fixes.
+       sloppy mac MPW support
+       Intel gnu/960 makefiles and version numbering.
+
+Many of the bug fixes found their way into the main development line
+prior to 1.36.  ALL intel changes were ifdef'd I80960.  This was good
+as it isolated the changes, but bad in that it connected the b.out
+support to the i960 support, and bad in that the bug fixes were only
+active in the i960+b.out executables of gas, (although most of these
+were nicely marked with comments indicating that they were probably
+general bug fixes.)
+
+To pick up the main FSF development line again, along the way to 1.36,
+several new processors were added, many bugs fixed, and the world was
+a somewhat better place in general.
+
+From gas-1.36, Loic at Axis Design (france!) encapsulated object
+format specific actions, added coff versions of those encapsulations,
+and a config.gas style configuration and Makefile.  This was a big
+change and a lot of work.
+
+Then along came the FIRST FSF release of gas-1.37.  I say this because
+there have been at least two releases of gas-1.37.  Only two of them
+do we care about for this story, so let's call them gas-1.37.1 and
+gas-1.37.2.
+
+Here starts the confusion.  Firstly, gas-1.37.1 did not compile.
+
+In the meantime, John Gilmore at Cygnus Support had been hacking
+gas-1.37.1.  He got it to compile.  He added support for the AMD 29000
+processor.  AND he started encapsulating some of the a.out specific
+pieces of code mostly into functions.  AND he rebuilt the relocation
+info to be generic.  AND he restructured somewhat so that for a single
+host, cross assemblers could be built for all targets in the same
+directory.  Useful work but a considerable nuisance because the a29k
+changes were not partitioned from the encapsulation changes, the
+encapsulation changes were incomplete, and the encapsulation required
+functions where alternate structuring might have used macros. Let's
+call this version gas-1.37.1+a29k.
+
+By the time gas-1.37.2 was "released", (remember that it TOO was
+labelled by FSF as gas-1.37), it compiled, but it also added i860
+support and ansi style const declarations.
+
+At this point, Loic rolled his changes into gas-1.37.2.
+
+What I've done.
+
+I collected all the stray versions of gas that sounded relevant to my
+goals of cross assembly and alternate object file formats and the FSF
+releases from which the stray versions had branched.
+
+I rolled the Intel i960 changes from 1.31 into versions that I call
+1.34+i960, 1.36+i960, and then 1.37.1+i960.
+
+Then I merged 1.37.1+i960 with 1.37.1+a29k to produce what I call
+1.37.1+i960+a29k or 1.37.3.
+
+From 1.37.3, I pulled in Loic's stuff.  This wasn't easy as Loic's
+stuff hit all the same points as John's encapsulations.  Loic's goal
+was to split the a.out from coff dependancies for native assembly on
+coff, while John's was to split for multiple cross assembly from a
+single host.
+
+Loic's config arranged files much like emacs into m-*, etc.  I've
+rearranged these somewhat.
+
+Theory:
+
+The goal of the new configuration scheme is to bury all object format,
+target processor, and host machine dependancies in object, target, and
+host specific files.  That is, to move all #ifdef's out of the gas
+common code.
+
+Here's how it works.  There is a .h and a .c file for each object file
+format, a .h and a .c file for each target processor, and a .h for
+each host.  config.gas creates {sym}links in the current directory to
+the appropriate files in the config directory.  config.gas also serves
+as a list of triplets {host, target, object-format} that have been
+tested at one time or another.  I also recommend that config.gas be
+used to document triplet specific notes as to purpose of the triplet,
+etc.
+
+Implementation:
+
+host.h is a {sym}link to .../config/xm-yourhost.h.  It is intended to
+be used to hide host compiler, system header file, and system library
+differences between host machines.  If your host needs actual c source
+files, then either: these are generally useful functions, in which
+case you should probably build a local library outside of the gas
+source tree, or someone, perhaps me, is confused about what is needed
+by different hosts.
+
+obj-format.h is a {sym}link to .../config/obj-something.h.  It is intended
+
+All gas .c files include as.h.
+
+as.h #define's "gas", includes host.h, defines a number of gas
+specific structures and types, and then includes tp.h, obj.h, and
+target-environment.h.
+
+target-environment.h defines a target environment specific
+preprocessor flag, eg, TE_SUN, and then includes obj-format.h.
+
+obj-format.h defines an object format specific preprocessor flag, eg,
+OBJ_AOUT, OBJ_BOUT, OBJ_COFF, includes "target-processor.h", and then
+defines the object specific macros, functions, types, and structures.
+
+target-processor.h 
+
+target-processor.
+
+Porting:
+
+There appear to be four major types of ports; new hosts, new target
+processors, new object file formats, and new target environments.
+
+
+-----
+
+reloc now stored internally as generic. (symbols too?) (segment types
+vs. names?)
+
+I don't mean to overlook anyone here.  There have also been several
+other development lines here that I looked at and elected to bypass.
+Specifically, xxx's stabs in coff stuff was particularly tempting.
diff --git a/gas/VERSION b/gas/VERSION
new file mode 100755 (executable)
index 0000000..5625e59
--- /dev/null
@@ -0,0 +1 @@
+1.2
index b7fc58772270c79848605e5a495e7d31d654a189..977808f9be534bb02aec042721ac462fb7d8564c 100644 (file)
@@ -31,7 +31,10 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 /*
  * $Log$
- * Revision 1.1  1991/04/04 18:15:38  rich
+ * Revision 1.1.1.1  1991/04/04 18:15:39  rich
+ * new gas main line
+ *
+ * Revision 1.1  1991/04/04  18:15:38  rich
  * Initial revision
  *
  *
index 9b39153fc07821dfad881d8dadcb8b7ca9a91c8b..e2667a0ed23e861cf4d172a7c31a8d609a942dcd 100755 (executable)
@@ -32,7 +32,10 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 /*
  * $Log$
- * Revision 1.1  1991/04/04 18:15:40  rich
+ * Revision 1.1.1.1  1991/04/04 18:15:42  rich
+ * new gas main line
+ *
+ * Revision 1.1  1991/04/04  18:15:40  rich
  * Initial revision
  *
  *
diff --git a/gas/config/ho-decstation.h b/gas/config/ho-decstation.h
new file mode 100644 (file)
index 0000000..f307e20
--- /dev/null
@@ -0,0 +1,25 @@
+/* ho-pmax.h  Host-specific header file for decstation 3100.
+   Copyright (C) 1987, 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of GAS, the GNU Assembler.
+
+GAS 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 1, or (at your option)
+any later version.
+
+GAS 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 GAS; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <string.h>
+
+extern char *malloc();
+extern int free();
+
+/* end of ho-pmax.h */
index 40c49e961c1ec21151745313f21a4b59b303cb4c..c474665b2dd3e761073dcaa85c629d57799805b6 100644 (file)
@@ -23,7 +23,10 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 /*
  * $Log$
- * Revision 1.1  1991/04/04 18:15:42  rich
+ * Revision 1.1.1.1  1991/04/04 18:15:43  rich
+ * new gas main line
+ *
+ * Revision 1.1  1991/04/04  18:15:42  rich
  * Initial revision
  *
  *
diff --git a/gas/config/ho-rs6000.h b/gas/config/ho-rs6000.h
new file mode 100644 (file)
index 0000000..8f624f4
--- /dev/null
@@ -0,0 +1,22 @@
+/* ho-rs6000.h  Rs6000 host-specific header file.
+   Copyright (C) 1987, 1991 Free Software Foundation, Inc.
+
+This file is part of GAS, the GNU Assembler.
+
+GAS 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 1, or (at your option)
+any later version.
+
+GAS 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 GAS; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#define M_RS6000 1
+
+/* end of ho-rs6000.h */
diff --git a/gas/config/ho-vax.h b/gas/config/ho-vax.h
new file mode 100644 (file)
index 0000000..735a215
--- /dev/null
@@ -0,0 +1,29 @@
+/* ho-vax.h  Intended for vax ultrix
+   Copyright (C) 1987, 1991 Free Software Foundation, Inc.
+
+This file is part of GAS, the GNU Assembler.
+
+GAS 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 1, or (at your option)
+any later version.
+
+GAS 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 GAS; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#define M_VAX 1
+
+#ifndef __STDC__
+#define NO_STDARG
+#endif /* not ansi */
+
+extern char *malloc();
+extern int free();
+
+/* end of ho-vax.h */
diff --git a/gas/config/mh-cygnus b/gas/config/mh-cygnus
new file mode 100755 (executable)
index 0000000..774d205
--- /dev/null
@@ -0,0 +1,8 @@
+CC = gcc -b$(target) -Wall -nostdinc -nostdlib \
+       -I$(srcdir)/../clib/ansi/include -I$(srcdir)/../os-layer/include
+
+CLIB = $(srcdir)/../clib/Host-$(host)/Target-$(target)/libc.a \
+       $(srcdir)/../gcc/Host-sun4/Target-$(target)/gnulib
+
+LDFLAGS = /lib/crt0.o
+
diff --git a/gas/config/mh-i386 b/gas/config/mh-i386
new file mode 100644 (file)
index 0000000..3375d42
--- /dev/null
@@ -0,0 +1 @@
+ALLOCA=alloca.o
diff --git a/gas/config/obj-bfd-sunos.c b/gas/config/obj-bfd-sunos.c
new file mode 100644 (file)
index 0000000..0bbc600
--- /dev/null
@@ -0,0 +1,51 @@
+#include "as.h"
+
+static 
+
+const short seg_N_TYPE[] = {
+  N_ABS,
+  N_TEXT,
+  N_DATA,
+  N_BSS,
+  N_UNDF, /* unknown */
+  N_UNDF, /* absent */
+  N_UNDF, /* pass1 */
+  N_UNDF, /* error */
+  N_UNDF, /* bignum/flonum */
+  N_UNDF, /* difference */
+  N_REGISTER, /* register */
+};
+
+const segT N_TYPE_seg [N_TYPE+2] = {   /* N_TYPE == 0x1E = 32-2 */
+       SEG_UNKNOWN,                    /* N_UNDF == 0 */
+       SEG_GOOF,
+       SEG_ABSOLUTE,                   /* N_ABS == 2 */
+       SEG_GOOF,
+       SEG_TEXT,                       /* N_TEXT == 4 */
+       SEG_GOOF,
+       SEG_DATA,                       /* N_DATA == 6 */
+       SEG_GOOF,
+       SEG_BSS,                        /* N_BSS == 8 */
+       SEG_GOOF,
+       SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
+       SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
+       SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
+       SEG_REGISTER,                   /* dummy N_REGISTER for regs = 30 */
+       SEG_GOOF,
+};
+
+
+void obj_symbol_new_hook(symbolP)
+symbolS *symbolP;
+{
+       return;
+} /* obj_symbol_new_hook() */
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of obj-bfd-sunos.c */
diff --git a/gas/config/obj-bfd-sunos.h b/gas/config/obj-bfd-sunos.h
new file mode 100644 (file)
index 0000000..0d32758
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * This file is obj-bfd-sunos.h.
+ */
+
+ /* define an obj specific macro off which target cpu back ends may key. */
+#define OBJ_BFD
+#define OBJ_BFD_SUNOS
+
+#include "bfd.h"
+
+ /* include whatever target cpu is appropriate. */
+#include "targ-cpu.h"
+
+/*
+ * SYMBOLS
+ */
+
+/*
+ * If your object format needs to reorder symbols, define this.  When
+ * defined, symbols are kept on a doubly linked list and functions are
+ * made available for push, insert, append, and delete.  If not defined,
+ * symbols are kept on a singly linked list, only the append and clear
+ * facilities are available, and they are macros.
+ */
+
+ /* #define SYMBOLS_NEED_PACKPOINTERS */
+
+typedef asymbol obj_symbol_type;
+typedef void *object_headers;
+
+#define S_SET_NAME(s, v)               ((s)->sy_symbol.name = (v))
+#define S_GET_NAME(s)          ((s)->sy_symbol.name)
+#define S_SET_SEGMENT(s,v)     ((s)->sy_symbol.udata = (v))
+#define S_GET_SEGMENT(s)       ((s)->sy_symbol.udata)
+#define S_SET_EXTERNAL(s)      ((s)->sy_symbol.flags |= BSF_GLOBAL)
+#define S_SET_VALUE(s,v)       ((s)->sy_symbol.value  = (v))
+#define S_GET_VALUE(s)         ((s)->sy_symbol.value)
+#define S_IS_DEFINED(s)                (!((s)->sy_symbol.flags & BSF_UNDEFINED))
+
+#define DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE (0) /* your magic number */
+#define OBJ_EMIT_LINENO(a,b,c) /* must be *something*.  This no-op's it out. */
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of obj-bfd-sunos.h */
diff --git a/gas/config/te-motor.h b/gas/config/te-motor.h
new file mode 100755 (executable)
index 0000000..2254841
--- /dev/null
@@ -0,0 +1,4 @@
+/* Machine specific defines for the unisoft 680x0 V.3.2 version 1.3 */
+
+/* Remove leading underscore from the gcc generated symbol names */
+#define STRIP_UNDERSCORE 1
diff --git a/gas/config/te-sco386.h b/gas/config/te-sco386.h
new file mode 100644 (file)
index 0000000..8bcb688
--- /dev/null
@@ -0,0 +1,8 @@
+/* Machine specific defines for the SCO Unix V.3.2 ODT */
+#define scounix
+
+/* Return true if s (a non null string pointer), points to a local variable name. */
+#define LOCAL_LABEL(n)  ((n)[0] == '.' && (n)[1] == 'L')
+
+/* Compiler does not generate symbol names with a leading underscore. */
+#define STRIP_UNDERSCORE 0
diff --git a/gas/config/te-sparc.h b/gas/config/te-sparc.h
new file mode 100755 (executable)
index 0000000..fcd3535
--- /dev/null
@@ -0,0 +1,52 @@
+/* sparc.h -- Header file for the SPARC
+   Copyright (C) 1989 Free Software Foundation, Inc.
+
+This file is part of GAS, the GNU Assembler.
+
+GAS 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 1, or (at your option)
+any later version.
+
+GAS 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 GAS; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/*
+ * The following enum and struct were borrowed from
+ * sunOS  /usr/include/sun4/a.out.h
+ *
+ */
+
+enum reloc_type
+{
+    RELOC_8,        RELOC_16,        RELOC_32,       RELOC_DISP8,
+    RELOC_DISP16,   RELOC_DISP32,    RELOC_WDISP30,  RELOC_WDISP22,
+    RELOC_HI22,     RELOC_22,        RELOC_13,       RELOC_LO10,
+    RELOC_SFA_BASE, RELOC_SFA_OFF13, RELOC_BASE10,   RELOC_BASE13,
+    RELOC_BASE22,   RELOC_PC10,      RELOC_PC22,     RELOC_JMP_TBL,
+    RELOC_SEGOFF16, RELOC_GLOB_DAT,  RELOC_JMP_SLOT, RELOC_RELATIVE,
+
+    NO_RELOC
+};
+
+struct reloc_info_sparc
+{
+    unsigned long r_address;
+/*
+ * Using bit fields here is a bad idea because the order is not portable. :-(
+ */
+    unsigned int r_index    : 24;
+    unsigned int r_extern   : 1;
+    unsigned int unused     : 2;
+    enum reloc_type r_type  : 5;
+    long r_addend;
+};
+
+#define relocation_info reloc_info_sparc
+
diff --git a/gas/config/te-unisoft.h b/gas/config/te-unisoft.h
new file mode 100755 (executable)
index 0000000..2254841
--- /dev/null
@@ -0,0 +1,4 @@
+/* Machine specific defines for the unisoft 680x0 V.3.2 version 1.3 */
+
+/* Remove leading underscore from the gcc generated symbol names */
+#define STRIP_UNDERSCORE 1
diff --git a/gas/config/tmake-sun3 b/gas/config/tmake-sun3
new file mode 100755 (executable)
index 0000000..9681e6d
--- /dev/null
@@ -0,0 +1 @@
+# This line from make-sun3.
diff --git a/gas/config/vms/objrecdef.h b/gas/config/vms/objrecdef.h
new file mode 100644 (file)
index 0000000..fca8af4
--- /dev/null
@@ -0,0 +1,255 @@
+/*
+ *
+ *     $OBJRECDEF
+ *     Generated automatically by "vms_struct Version 1.00"
+ *     Created from VMS definition file "objrecdef.mar"
+ *     Mon Oct 14 14:01:29 1985
+ *
+ */
+struct OBJREC {
+       unsigned char   obj$b_rectyp;
+       unsigned char   obj$b_subtyp;
+       unsigned char   obj$b_mhd_strlv;
+       unsigned char   obj$b_mhd_recsz[2];
+       unsigned char   obj$t_mhd_name[1];
+       };
+\f
+#define        OBJ$C_HDR       0
+#define        OBJ$C_HDR_MHD   0
+#define        OBJ$C_HDR_LNM   1
+#define        OBJ$C_HDR_SRC   2
+#define        OBJ$C_HDR_TTL   3
+#define        OBJ$C_HDR_CPR   4
+#define        OBJ$C_HDR_MTC   5
+#define        OBJ$C_HDR_GTX   6
+#define        OBJ$C_GSD       1
+#define        OBJ$C_GSD_PSC   0
+#define        OBJ$C_GSD_SYM   1
+#define        OBJ$C_GSD_EPM   2
+#define        OBJ$C_GSD_PRO   3
+#define        OBJ$C_GSD_SYMW  4
+#define        OBJ$C_GSD_EPMW  5
+#define        OBJ$C_GSD_PROW  6
+#define        OBJ$C_GSD_IDC   7
+#define        OBJ$C_GSD_ENV   8
+#define        OBJ$C_GSD_LSY   9
+#define        OBJ$C_GSD_LEPM  10
+#define        OBJ$C_GSD_LPRO  11
+#define        OBJ$C_GSD_SPSC  12
+#define        OBJ$C_TIR       2
+#define        OBJ$C_EOM       3
+#define        OBJ$C_DBG       4
+#define        OBJ$C_TBT       5
+#define        OBJ$C_LNK       6
+#define        OBJ$C_EOMW      7
+#define        OBJ$C_MAXRECTYP 7
+#define        OBJ$K_SUBTYP    1
+#define        OBJ$C_SUBTYP    1
+#define        OBJ$C_MAXRECSIZ 2048
+#define        OBJ$C_STRLVL    0
+#define        OBJ$C_SYMSIZ    31
+#define        OBJ$C_STOREPLIM -1
+#define        OBJ$C_PSCALILIM 9
+\f
+#define        MHD$C_MHD       0
+#define        MHD$C_LNM       1
+#define        MHD$C_SRC       2
+#define        MHD$C_TTL       3
+#define        MHD$C_CPR       4
+#define        MHD$C_MTC       5
+#define        MHD$C_GTX       6
+#define        MHD$C_MAXHDRTYP 6
+\f
+#define        GSD$K_ENTRIES   1
+#define        GSD$C_ENTRIES   1
+#define        GSD$C_PSC       0
+#define        GSD$C_SYM       1
+#define        GSD$C_EPM       2
+#define        GSD$C_PRO       3
+#define        GSD$C_SYMW      4
+#define        GSD$C_EPMW      5
+#define        GSD$C_PROW      6
+#define        GSD$C_IDC       7
+#define        GSD$C_ENV       8
+#define        GSD$C_LSY       9
+#define        GSD$C_LEPM      10
+#define        GSD$C_LPRO      11
+#define        GSD$C_SPSC      12
+#define        GSD$C_SYMV      13
+#define        GSD$C_EPMV      14
+#define        GSD$C_PROV      15
+#define        GSD$C_MAXRECTYP 15
+\f
+#define        GSY$M_WEAK      1
+#define        GSY$M_DEF       2
+#define        GSY$M_UNI       4
+#define        GSY$M_REL       8
+\f
+#define        GPS$M_PIC       1
+#define        GPS$M_LIB       2
+#define        GPS$M_OVR       4
+#define        GPS$M_REL       8
+#define        GPS$M_GBL       16
+#define        GPS$M_SHR       32
+#define        GPS$M_EXE       64
+#define        GPS$M_RD        128
+#define        GPS$M_WRT       256
+#define        GPS$M_VEC       512
+#define        GPS$K_NAME      9
+#define        GPS$C_NAME      9
+\f
+#define        TIR$C_STA_GBL   0
+#define        TIR$C_STA_SB    1
+#define        TIR$C_STA_SW    2
+#define        TIR$C_STA_LW    3
+#define        TIR$C_STA_PB    4
+#define        TIR$C_STA_PW    5
+#define        TIR$C_STA_PL    6
+#define        TIR$C_STA_UB    7
+#define        TIR$C_STA_UW    8
+#define        TIR$C_STA_BFI   9
+#define        TIR$C_STA_WFI   10
+#define        TIR$C_STA_LFI   11
+#define        TIR$C_STA_EPM   12
+#define        TIR$C_STA_CKARG 13
+#define        TIR$C_STA_WPB   14
+#define        TIR$C_STA_WPW   15
+#define        TIR$C_STA_WPL   16
+#define        TIR$C_STA_LSY   17
+#define        TIR$C_STA_LIT   18
+#define        TIR$C_STA_LEPM  19
+#define        TIR$C_MAXSTACOD 19
+#define        TIR$C_MINSTOCOD 20
+#define        TIR$C_STO_SB    20
+#define        TIR$C_STO_SW    21
+#define        TIR$C_STO_L     22
+#define        TIR$C_STO_BD    23
+#define        TIR$C_STO_WD    24
+#define        TIR$C_STO_LD    25
+#define        TIR$C_STO_LI    26
+#define        TIR$C_STO_PIDR  27
+#define        TIR$C_STO_PICR  28
+#define        TIR$C_STO_RSB   29
+#define        TIR$C_STO_RSW   30
+#define        TIR$C_STO_RL    31
+#define        TIR$C_STO_VPS   32
+#define        TIR$C_STO_USB   33
+#define        TIR$C_STO_USW   34
+#define        TIR$C_STO_RUB   35
+#define        TIR$C_STO_RUW   36
+#define        TIR$C_STO_B     37
+#define        TIR$C_STO_W     38
+#define        TIR$C_STO_RB    39
+#define        TIR$C_STO_RW    40
+#define        TIR$C_STO_RIVB  41
+#define        TIR$C_STO_PIRR  42
+#define        TIR$C_MAXSTOCOD 42
+#define        TIR$C_MINOPRCOD 50
+#define        TIR$C_OPR_NOP   50
+#define        TIR$C_OPR_ADD   51
+#define        TIR$C_OPR_SUB   52
+#define        TIR$C_OPR_MUL   53
+#define        TIR$C_OPR_DIV   54
+#define        TIR$C_OPR_AND   55
+#define        TIR$C_OPR_IOR   56
+#define        TIR$C_OPR_EOR   57
+#define        TIR$C_OPR_NEG   58
+#define        TIR$C_OPR_COM   59
+#define        TIR$C_OPR_INSV  60
+#define        TIR$C_OPR_ASH   61
+#define        TIR$C_OPR_USH   62
+#define        TIR$C_OPR_ROT   63
+#define        TIR$C_OPR_SEL   64
+#define        TIR$C_OPR_REDEF 65
+#define        TIR$C_OPR_DFLIT 66
+#define        TIR$C_MAXOPRCOD 66
+#define        TIR$C_MINCTLCOD 80
+#define        TIR$C_CTL_SETRB 80
+#define        TIR$C_CTL_AUGRB 81
+#define        TIR$C_CTL_DFLOC 82
+#define        TIR$C_CTL_STLOC 83
+#define        TIR$C_CTL_STKDL 84
+#define        TIR$C_MAXCTLCOD 84
+\f
+/*
+ *     Debugger symbol definitions:  These are done by hand, as no
+ *                                     machine-readable version seems
+ *                                     to be available.
+ */
+#define        DST$C_C         7               /* Language == "C"      */
+#define DST$C_VERSION  153
+#define        DST$C_SOURCE    155             /* Source file          */
+#define DST$C_PROLOG   162
+#define        DST$C_BLKBEG    176             /* Beginning of block   */
+#define        DST$C_BLKEND    177             /* End of block */
+#define DST$C_ENTRY    181
+#define DST$C_PSECT    184
+#define        DST$C_LINE_NUM  185             /* Line Number          */
+#define DST$C_LBLORLIT 186
+#define DST$C_LABEL    187
+#define        DST$C_MODBEG    188             /* Beginning of module  */
+#define        DST$C_MODEND    189             /* End of module        */
+#define        DST$C_RTNBEG    190             /* Beginning of routine */
+#define        DST$C_RTNEND    191             /* End of routine       */
+#define        DST$C_DELTA_PC_W        1               /* Incr PC      */
+#define        DST$C_INCR_LINUM        2               /* Incr Line #  */
+#define        DST$C_INCR_LINUM_W      3               /* Incr Line #  */
+#define DST$C_SET_LINUM_INCR   4
+#define DST$C_SET_LINUM_INCR_W 5
+#define DST$C_RESET_LINUM_INCR 6
+#define DST$C_BEG_STMT_MODE    7
+#define DST$C_END_STMT_MODE    8
+#define        DST$C_SET_LINE_NUM      9               /* Set Line #   */
+#define DST$C_SET_PC           10
+#define DST$C_SET_PC_W         11
+#define DST$C_SET_PC_L         12
+#define DST$C_SET_STMTNUM      13
+#define DST$C_TERM             14              /* End of lines */
+#define DST$C_TERM_W           15              /* End of lines */
+#define        DST$C_SET_ABS_PC        16              /* Set PC       */
+#define        DST$C_DELTA_PC_L        17              /* Incr PC      */
+#define DST$C_INCR_LINUM_L     18              /* Incr Line #  */
+#define DST$C_SET_LINUM_B      19              /* Set Line #   */
+#define DST$C_SET_LINUM_L      20              /* Set Line #   */
+#define        DST$C_TERM_L            21              /* End of lines */
+/* these are used with DST$C_SOURCE */
+#define        DST$C_SRC_FORMFEED      16              /* ^L counts    */
+#define        DST$C_SRC_DECLFILE      1               /* Declare file */
+#define        DST$C_SRC_SETFILE       2               /* Set file     */
+#define        DST$C_SRC_SETREC_L      3               /* Set record   */
+#define        DST$C_SRC_DEFLINES_W    10              /* # of line    */
+/* the following are the codes for the various data types.  Anything not on
+ * the list is included under 'advanced_type'
+ */
+#define DBG$C_UCHAR            0x02
+#define DBG$C_USINT            0x03
+#define DBG$C_ULINT            0x04
+#define DBG$C_SCHAR            0x06
+#define DBG$C_SSINT            0x07
+#define DBG$C_SLINT            0x08
+#define DBG$C_REAL4            0x0a
+#define DBG$C_REAL8            0x0b
+#define DBG$C_FUNCTION_ADDR    0x17
+#define DBG$C_ADVANCED_TYPE    0xa3
+/*  These are the codes that are used to generate the definitions of struct
+ *  union and enum records
+ */
+#define DBG$C_ENUM_ITEM                        0xa4
+#define DBG$C_ENUM_START               0xa5
+#define DBG$C_ENUM_END                 0xa6
+#define DBG$C_STRUCT_START             0xab
+#define DBG$C_STRUCT_ITEM              0xff
+#define DBG$C_STRUCT_END               0xac
+/*  These are the codes that are used in the suffix records to determine the
+ *  actual data type
+ */
+#define DBG$C_BASIC                    0x01
+#define DBG$C_BASIC_ARRAY              0x02
+#define DBG$C_STRUCT                   0x03
+#define DBG$C_POINTER                  0x04
+#define DBG$C_VOID                     0x05
+#define DBG$C_COMPLEX_ARRAY            0x07
+/* These codes are used in the generation of the symbol definition records
+ */
+#define DBG$C_FUNCTION_PARAMETER       0xc9
+#define DBG$C_LOCAL_SYM                        0xd9
diff --git a/gas/config/vms/vms-dbg.c b/gas/config/vms/vms-dbg.c
new file mode 100644 (file)
index 0000000..19c6c93
--- /dev/null
@@ -0,0 +1,1125 @@
+#include <stdio.h>
+#include "as.h"
+#include "struc-symbol.h"
+#include "symbols.h"
+#include "objrecdef.h"
+#include <stab.h>
+
+/* This file contains many of the routines needed to output debugging info into
+ * the object file that the VMS debugger needs to understand symbols.  These
+ * routines are called very late in the assembly process, and thus we can be
+ * fairly lax about changing things, since the GSD and the TIR sections have
+ * already been output.
+ */
+
+/* We need this info to cross correlate between the stabs def for a symbol and
+ * the actual symbol def.  The actual symbol def contains the psect number and
+ * offset, which is needed to declare a variable to the debugger for global
+ * and static variables
+ */
+struct VMS_Symbol {
+       struct VMS_Symbol *Next;
+       struct symbol *Symbol;
+       int Size;
+       int Psect_Index;
+       int Psect_Offset;
+       };
+extern struct VMS_Symbol *VMS_Symbols;
+
+enum advanced_type {BASIC,POINTER,ARRAY,ENUM,STRUCT,UNION,FUNCTION,VOID,UNKNOWN};
+
+/* this structure contains the information from the stabs directives, and the
+ * information is filled in by VMS_typedef_parse.  Everything that is needed
+ * to generate the debugging record for a given symbol is present here.
+ * This could be done more efficiently, using nested struct/unions, but for now
+ * I am happy that it works.
+ */
+struct VMS_DBG_Symbol{
+       struct VMS_DBG_Symbol * next;
+       enum advanced_type advanced;    /* description of what this is */
+       int dbx_type;   /* this record is for this type */
+       int type2;      /* For advanced types this is the type referred to.
+                               i.e. the type a pointer points to, or the type
+                               of object that makes up an array */
+       int VMS_type;   /* Use this type when generating a variable def */
+       int index_min;  /* used for arrays - this will be present for all */
+       int index_max;  /* entries, but will be meaningless for non-arrays */
+       int data_size;  /* size in bytes of the data type.  For an array, this
+                          is the size of one element in the array */
+       int struc_numb; /* Number of the structure/union/enum - used for ref */
+};
+
+struct VMS_DBG_Symbol *VMS_Symbol_type_list={(struct VMS_DBG_Symbol*) NULL};
+
+/* we need this structure to keep track of forward references to
+ * struct/union/enum that have not been defined yet.  When they are ultimately
+ * defined, then we can go back and generate the TIR commands to make a back
+ * reference.
+ */
+
+struct forward_ref{
+       struct forward_ref * next;
+       int dbx_type;
+       int struc_numb;
+       char resolved;
+       };
+
+struct forward_ref * f_ref_root={(struct forward_ref*) NULL};
+
+static char * symbol_name;
+static structure_count=0;
+
+/* this routine converts a number string into an integer, and stops when it
+ * sees an invalid character the return value is the address of the character 
+ * just past the last character read.  No error is generated.
+ */
+static char * cvt_integer(char* str,int * rtn){
+       int ival, neg;
+               neg = *str == '-' ? ++str, -1 : 1;
+               ival=0; /* first get the number of the type for dbx */
+               while((*str <= '9') && (*str >= '0'))
+                       ival = 10*ival + *str++ -'0';
+       *rtn = neg*ival;
+       return str;
+}
+
+/* this routine fixes the names that are generated by C++, ".this" is a good
+ * example.  The period does not work for the debugger, since it looks like
+ * the syntax for a structure element, and thus it gets mightily confused
+ */
+static fix_name(char* pnt){
+       for( ;*pnt != 0; pnt++){
+       if(*pnt == '.') *pnt = '$';
+       };
+}
+
+/* this routine is used to compare the names of certain types to various
+ * fixed types that are known by the debugger.
+ */
+#define type_check(x)  !strcmp( symbol_name , x )
+
+/* When defining a structure, this routine is called to find the name of
+ * the actual structure.  It is assumed that str points to the equal sign
+ * in the definition, and it moves backward until it finds the start of the
+ * name.  If it finds a 0, then it knows that this structure def is in the
+ * outermost level, and thus symbol_name points to the symbol name.
+ */
+static char* get_struct_name(char* str){
+       char* pnt;
+       pnt=str;
+       while((*pnt != ':') && (*pnt != '\0')) pnt--;
+       if(*pnt == '\0') return symbol_name;
+       *pnt-- = '\0';
+       while((*pnt != ';') && (*pnt != '=')) pnt--;
+       if(*pnt == ';') return pnt+1;
+       while((*pnt < '0') || (*pnt > '9')) pnt++;
+       while((*pnt >= '0') && (*pnt <= '9')) pnt++;
+       return pnt;
+}      
+/* search symbol list for type number dbx_type.  Return a pointer to struct */
+static struct VMS_DBG_Symbol* find_symbol(int dbx_type){
+       struct VMS_DBG_Symbol* spnt;
+       spnt=VMS_Symbol_type_list;
+       while (spnt!=(struct VMS_DBG_Symbol*) NULL){
+               if(spnt->dbx_type==dbx_type) break;
+               spnt=spnt->next;};
+       if(spnt==(struct VMS_DBG_Symbol*) NULL) return 0;/*Dunno what this is*/
+       return spnt;
+}
+
+
+/* Many good programmers cringe when they see a fixed size array - since I am
+ * using this to generate the various descriptors for the data types present,
+ * you might argue that the descriptor could overflow the array for a
+ * complicated variable, and then I am in deep doo-doo.  My answer to this is
+ * that the debugger records that we write have all sorts of length bytes
+ * stored in them all over the place, and if we exceed 127 bytes (since the top
+ * bit indicates data, rather than a command), we are dead anyhow.  So I figure
+ * why not do this the easy way.  Besides, to get 128 bytes, you need something
+ * like an array with 10 indicies, or something like
+ *       char **************************************** var; 
+ * Lets get real.  If some idiot writes programs like that he/she gets what
+ * they deserve.  (It is possible to overflow the record with a somewhat
+ * simpler example, like: int (*(*(*(*(*(* sarr6)[1])[1])[2])[3])[4])[5];
+ * but still...).  And if someone in the peanut gallery wants to know "What
+ * does VAX-C do with something like this?", I will tell you.  It crashes.
+ * At least this code has the good sense to convert it to *void.
+ * In practice, I do not think that this presents too much of a problem, since
+ * struct/union/enum all use defined types, which sort of terminate the
+ * definition.  It occurs to me that we could possibly do the same thing with
+ * arrays and pointers, but I don't know quite how it would be coded.
+ *
+ * And now back to the regularly scheduled program...
+ */
+#define MAX_DEBUG_RECORD 128
+static char Local[MAX_DEBUG_RECORD]; /* buffer for variable descriptor */
+static int Lpnt;               /* index into Local */
+static char Asuffix[MAX_DEBUG_RECORD]; /* buffer for array descriptor */
+static int Apoint;     /* index into Asuffix */
+static char overflow;  /* flag to indicate we have written too much*/
+static int total_len;  /* used to calculate the total length of variable
+                       descriptor plus array descriptor - used for len byte*/
+static int struct_number;      /* counter used to assign indexes to struct
+                                       unions and enums */
+
+/* this routine puts info into either Local or Asuffix, depending on the sign
+ * of size.  The reason is that it is easier to build the variable descriptor
+ * backwards, while the array descriptor is best built forwards.  In the end
+ * they get put together, if there is not a struct/union/enum along the way
+ */
+push(int value, int size){
+       char * pnt;
+       int i;
+       int size1;
+       long int val;
+       val=value;
+       pnt=(char*) &val;
+       size1 = size;
+       if (size < 0) {size1 = -size; pnt += size1-1;};
+       if(size < 0)
+       for(i=0;i<size1;i++) {
+               Local[Lpnt--] = *pnt--;
+               if(Lpnt < 0) {overflow = 1; Lpnt = 1;};}
+       else for(i=0;i<size1;i++){
+                Asuffix[Apoint++] = *pnt++;
+                if(Apoint >= MAX_DEBUG_RECORD) 
+                       {overflow = 1; Apoint =MAX_DEBUG_RECORD-1;};}
+}
+
+/* this routine generates the array descriptor for a given array */
+static array_suffix(struct VMS_DBG_Symbol* spnt2){
+       struct VMS_DBG_Symbol * spnt;
+       struct VMS_DBG_Symbol * spnt1;
+       int rank;
+       int total_size;
+       int i;
+       rank=0;
+       spnt=spnt2;
+       while(spnt->advanced != ARRAY) {
+               spnt=find_symbol(spnt->type2);
+               if(spnt == (struct VMS_DBG_Symbol *) NULL) return;};
+       spnt1=spnt;
+       spnt1=spnt;
+       total_size= 1;
+       while(spnt1->advanced == ARRAY) {rank++;
+               total_size *= (spnt1->index_max - spnt1->index_min +1);
+               spnt1=find_symbol(spnt1->type2);};
+       total_size = total_size * spnt1->data_size;
+       push(spnt1->data_size,2);
+       if(spnt1->VMS_type == 0xa3) push(0,1);
+                       else push(spnt1->VMS_type,1);
+       push(4,1);
+       for(i=0;i<6;i++) push(0,1);
+       push(0xc0,1);
+       push(rank,1);
+       push(total_size,4);
+       push(0,4);
+       spnt1=spnt;
+       while(spnt1->advanced == ARRAY) {
+               push(spnt1->index_max - spnt1->index_min+1,4);
+               spnt1=find_symbol(spnt1->type2);};
+       spnt1=spnt;
+       while(spnt1->advanced == ARRAY) {
+               push(spnt1->index_min,4);
+               push(spnt1->index_max,4);
+               spnt1=find_symbol(spnt1->type2);};
+}
+
+/* this routine generates the start of a variable descriptor based upon
+ * a struct/union/enum that has yet to be defined.  We define this spot as
+ * a new location, and save four bytes for the address.  When the struct is
+ * finally defined, then we can go back and plug in the correct address
+*/
+static new_forward_ref(int dbx_type){
+       struct forward_ref* fpnt;
+       fpnt = (struct forward_ref*) malloc(sizeof(struct forward_ref));
+       fpnt->next = f_ref_root;
+       f_ref_root = fpnt;
+       fpnt->dbx_type = dbx_type;
+       fpnt->struc_numb = ++structure_count;
+       fpnt->resolved = 'N';
+       push(3,-1);
+       total_len = 5;
+       push(total_len,-2);
+       struct_number = - fpnt->struc_numb;
+}
+
+/* this routine generates the variable descriptor used to describe non-basic
+ * variables.  It calls itself recursively until it gets to the bottom of it
+ * all, and then builds the descriptor backwards.  It is easiest to do it this
+ *way since we must periodically write length bytes, and it is easiest if we know
+ *the value when it is time to write it.
+ */
+static int gen1(struct VMS_DBG_Symbol * spnt,int array_suffix_len){
+       struct VMS_DBG_Symbol * spnt1;
+       int i;
+       switch(spnt->advanced){
+       case VOID:
+               push(DBG$C_VOID,-1);
+               total_len += 1;
+               push(total_len,-2);
+               return 0;
+       case BASIC:
+       case FUNCTION:
+               if(array_suffix_len == 0) {
+                               push(spnt->VMS_type,-1);
+                               push(DBG$C_BASIC,-1);           
+                               total_len = 2;
+                               push(total_len,-2);
+                               return 1;};
+               push(0,-4);
+               push(0xfa02,-2);                
+               total_len = -2;
+               return 1;
+       case STRUCT:
+       case UNION:
+       case ENUM:
+               struct_number=spnt->struc_numb;
+               if(struct_number < 0) {
+                       new_forward_ref(spnt->dbx_type);
+                       return 1;
+               }
+               push(DBG$C_STRUCT,-1);
+               total_len = 5;
+               push(total_len,-2);
+               return 1;
+       case POINTER:
+               spnt1=find_symbol(spnt->type2);
+               i=1;
+               if(spnt1 == (struct VMS_DBG_Symbol *) NULL)     
+                       new_forward_ref(spnt->type2);
+               else  i=gen1(spnt1,0);
+               if(i){ /* (*void) is a special case, do not put pointer suffix*/
+                 push(DBG$C_POINTER,-1);
+                 total_len += 3;
+                 push(total_len,-2);
+               };
+               return 1;
+       case ARRAY:
+               spnt1=spnt;
+               while(spnt1->advanced == ARRAY)
+                       {spnt1 = find_symbol(spnt1->type2);
+                       if(spnt1 == (struct VMS_DBG_Symbol *) NULL) {
+                           printf("gcc-as warning(debugger output):");
+                           printf("Forward reference error, dbx type %d\n",
+                                       spnt->type2);
+                           return;}
+                       };
+/* It is too late to generate forward references, so the user gets a message.
+ * This should only happen on a compiler error */
+               i=gen1(spnt1,1);
+               i=Apoint;
+               array_suffix(spnt);
+               array_suffix_len = Apoint - i;
+               switch(spnt1->advanced){
+               case BASIC:
+               case FUNCTION:
+                       break;
+               default:
+                       push(0,-2);
+                       total_len += 2;
+                       push(total_len,-2);
+                       push(0xfa,-1);
+                       push(0x0101,-2);
+                       push(DBG$C_COMPLEX_ARRAY,-1);
+               };
+               total_len += array_suffix_len + 8;
+               push(total_len,-2);                     
+       };
+}
+
+/* this generates a suffix for a variable.  If it is not a defined type yet,
+ * then dbx_type contains the type we are expecting so we can generate a
+ * forward reference.  This calls gen1 to build most of the descriptor, and
+ * then it puts the icing on at the end.  It then dumps whatever is needed
+ * to get a complete descriptor (i.e. struct reference, array suffix ).
+ */
+static generate_suffix(struct VMS_DBG_Symbol * spnt,int dbx_type){
+       int ilen;
+       int i;
+       char pvoid[6] = {5,0xaf,0,1,0,5};
+       struct VMS_DBG_Symbol * spnt1;
+       Apoint=0;
+       Lpnt =MAX_DEBUG_RECORD-1;
+       total_len=0;
+       struct_number = 0;
+       overflow = 0;
+       if(spnt == (struct VMS_DBG_Symbol*) NULL)
+               new_forward_ref(dbx_type);
+       else{
+               if(spnt->VMS_type != 0xa3) return 0; /* no suffix needed */
+               gen1(spnt,0);
+       };
+       push(0x00af,-2);
+       total_len += 4;
+       push(total_len,-1);
+/* if the variable descriptor overflows the record, output a descriptor for
+ * a pointer to void.
+ */
+       if((total_len >= MAX_DEBUG_RECORD) || overflow) {
+                printf(" Variable descriptor %d too complicated. Defined as *void ",spnt->dbx_type);
+                VMS_Store_Immediate_Data(pvoid, 6, OBJ$C_DBG);
+                 return;
+               };              
+       i=0;
+       while(Lpnt < MAX_DEBUG_RECORD-1) Local[i++] = Local[++Lpnt];
+       Lpnt = i; 
+/* we use this for a reference to a structure that has already been defined */
+       if(struct_number > 0){
+                VMS_Store_Immediate_Data(Local, Lpnt, OBJ$C_DBG);Lpnt=0;
+                VMS_Store_Struct(struct_number);}; 
+/* we use this for a forward reference to a structure that has yet to be
+*defined.  We store four bytes of zero to make room for the actual address once
+* it is known
+*/
+       if(struct_number < 0){
+                struct_number = -struct_number;
+                 VMS_Store_Immediate_Data(Local, Lpnt,OBJ$C_DBG);Lpnt=0;
+                 VMS_Def_Struct(struct_number);
+                for(i=0;i<4;i++) Local[Lpnt++] = 0;
+                VMS_Store_Immediate_Data(Local, Lpnt, OBJ$C_DBG);Lpnt=0;
+                 };
+       i=0;
+       while(i<Apoint) Local[Lpnt++] = Asuffix[i++];
+       if(Lpnt != 0)
+       VMS_Store_Immediate_Data(Local, Lpnt, OBJ$C_DBG);
+       Lpnt=0;
+ }
+
+/* This routine generates a symbol definition for a C sybmol for the debugger.
+ * It takes a psect and offset for global symbols - if psect < 0, then this is
+ * a local variable and the offset is relative to FP.  In this case it can
+ * be either a variable (Offset < 0) or a parameter (Offset > 0).
+ */
+VMS_DBG_record(struct VMS_DBG_Symbol* spnt,int Psect,int  Offset, char* Name)
+{
+       char* pnt;
+       int j;
+       int maxlen;
+       int i=0;
+       if(Psect < 0) { /* this is a local variable, referenced to SP */
+         maxlen=7+strlen(Name);
+         Local[i++] = maxlen;
+         Local[i++]=spnt->VMS_type;
+         if(Offset > 0) Local[i++] = DBG$C_FUNCTION_PARAMETER;
+               else Local[i++] = DBG$C_LOCAL_SYM;
+         pnt=(char*) &Offset;
+         for(j=0;j<4;j++) Local[i++]=*pnt++; /* copy the offset */
+       } else {
+         maxlen=7+strlen(Name); /* symbols fixed in memory */
+         Local[i++]=7+strlen(Name);
+         Local[i++]=spnt->VMS_type;
+         Local[i++]=1;
+         VMS_Store_Immediate_Data(Local, i, OBJ$C_DBG); i=0;
+         VMS_Set_Data(Psect,Offset,OBJ$C_DBG,0);
+       }
+       Local[i++]=strlen(Name);
+       pnt=Name;
+       fix_name(pnt);  /* if there are bad characters in name, convert them */
+       while(*pnt!='\0') Local[i++]=*pnt++;
+       VMS_Store_Immediate_Data(Local, i, OBJ$C_DBG);
+       if(spnt->VMS_type == DBG$C_ADVANCED_TYPE) generate_suffix(spnt,0);
+}
+
+
+/* This routine parses the stabs entries in order to make the definition
+ * for the debugger of local symbols and function parameters
+ */
+int VMS_local_stab_Parse(symbolS * sp){
+       char *pnt;
+       char *pnt1;
+       char *str;
+       struct VMS_DBG_Symbol* spnt;
+       struct VMS_Symbol *     vsp;
+       int dbx_type;
+       int VMS_type;
+       dbx_type=0;
+       str=sp->sy_nlist.n_un.n_name;
+       pnt=(char*) strchr(str,':');
+       if(pnt==(char*) NULL) return;   /* no colon present */
+       pnt1=pnt++;     /* save this for later, and skip colon */
+       if(*pnt == 'c') return 0;       /* ignore static constants */
+/* there is one little catch that we must be aware of.  Sometimes function
+ * parameters are optimized into registers, and the compiler, in its infiite
+ * wisdom outputs stabs records for *both*.  In general we want to use the
+ * register if it is present, so we must search the rest of the symbols for 
+ * this function to see if this parameter is assigned to a register.
+ */
+       {
+       char *str1;
+       char *pnt2;
+       symbolS * sp1;
+       if(*pnt == 'p'){
+         for(sp1 = symbol_next(sp); sp1; sp1 = symbol_next(sp1)) {
+           if ((sp1->sy_nlist.n_type & N_STAB) == 0) continue;
+           if((unsigned char)sp1->sy_nlist.n_type == N_FUN) break;
+           if((unsigned char)sp1->sy_nlist.n_type != N_RSYM) continue;
+           str1=sp1->sy_nlist.n_un.n_name;     /* and get the name */
+           pnt2=str;
+           while(*pnt2 != ':') {
+               if(*pnt2 != *str1) break;
+               pnt2++; str1++;};
+           if((*str1 != ':') || (*pnt2 != ':') ) continue;
+           return;     /* they are the same!  lets skip this one */
+         }; /* for */
+/* first find the dbx symbol type from list, and then find VMS type */
+         pnt++;        /* skip p in case no register */
+       };/* if */ }; /* p block */
+       pnt = cvt_integer( pnt, &dbx_type);
+       spnt = find_symbol(dbx_type);
+       if(spnt==(struct VMS_DBG_Symbol*) NULL) return 0;/*Dunno what this is*/
+       *pnt1='\0';
+       VMS_DBG_record(spnt,-1,sp->sy_nlist.n_value,str);
+       *pnt1=':';      /* and restore the string */
+       return 1;
+}
+
+/* this routine parses a stabs entry to find the information required to define
+ * a variable.  It is used for global and static variables. 
+ * Basically we need to know the address of the symbol.  With older versions
+ * of the compiler, const symbols are
+ * treated differently, in that if they are global they are written into the
+ * text psect.  The global symbol entry for such a const is actually written
+ * as a program entry point (Yuk!!), so if we cannot find a symbol in the list
+ * of psects, we must search the entry points as well.  static consts are even
+ * harder, since they are never assigned a memory address.  The compiler passes
+ * a stab to tell us the value, but I am not sure what to do with it.
+ */
+static gave_compiler_message = 0;
+
+static int VMS_stab_parse(symbolS * sp,char expected_type,
+       int type1,int type2,int Text_Psect){
+       char *pnt;
+       char *pnt1;
+       char *str;
+       symbolS * sp1;
+       struct VMS_DBG_Symbol* spnt;
+       struct VMS_Symbol *     vsp;
+       int dbx_type;
+       int VMS_type;
+       dbx_type=0;
+       str=sp->sy_nlist.n_un.n_name;
+       pnt=(char*) strchr(str,':');
+       if(pnt==(char*) NULL) return;   /* no colon present */
+       pnt1=pnt;       /* save this for later*/
+       pnt++;
+       if(*pnt==expected_type){
+               pnt = cvt_integer(pnt+1,&dbx_type);
+               spnt = find_symbol(dbx_type);
+               if(spnt==(struct VMS_DBG_Symbol*) NULL) return 0;/*Dunno what this is*/
+/* now we need to search the symbol table to find the psect and offset for
+ * this variable.
+ */
+       *pnt1='\0';
+       vsp=VMS_Symbols;
+       while(vsp != (struct VMS_Symbol*) NULL) 
+         {pnt=vsp->Symbol->sy_nlist.n_un.n_name;
+          if(pnt!=(char*) NULL)  if(*pnt++ == '_') 
+/* make sure name is the same, and make sure correct symbol type */
+          if((strlen(pnt) == strlen(str)) && (strcmp(pnt,str)==0) 
+               && ((vsp->Symbol->sy_type == type1) ||
+               (vsp->Symbol->sy_type == type2))) break;
+                       vsp=vsp->Next;};
+               if(vsp != (struct VMS_Symbol*) NULL){
+           VMS_DBG_record(spnt,vsp->Psect_Index,vsp->Psect_Offset,str);
+               *pnt1=':';      /* and restore the string */
+               return 1;};
+/* the symbol was not in the symbol list, but it may be an "entry point"
+   if it was a constant */
+          for(sp1 = symbol_rootP; sp1; sp1 = symbol_next(sp1)) {
+                 /*
+                  *    Dispatch on STAB type
+                  */
+                 if(sp1->sy_type != (N_TEXT | N_EXT) && sp1->sy_type!=N_TEXT)
+                     continue;
+                 pnt = sp1->sy_nlist.n_un.n_name;
+                 if(*pnt == '_') pnt++;
+                 if(strcmp(pnt,str) == 0){
+                       if(!gave_compiler_message && expected_type=='G'){
+printf("***Warning - the assembly code generated by the compiler has placed\n");
+printf("global constant(s) in the text psect.  These will not be available to\n");
+printf("other modules, since this is not the correct way to handle this. You\n");
+printf("have two options: 1) get a patched compiler that does not put global\n");
+printf("constants in the text psect, or 2) remove the 'const' keyword from\n");
+printf("definitions of global variables in your source module(s).  Don't say\n");
+printf("I didn't warn you!");
+gave_compiler_message = 1;};
+                               VMS_DBG_record(spnt,
+                               Text_Psect,
+                               sp1->sy_nlist.n_value,
+                               str);
+                       *pnt1=':';
+                       *(sp1->sy_nlist.n_un.n_name) = 'L';
+                                       /* fool assembler to not output this
+                                        * as a routine in the TBT */
+                       return 1;};
+           };
+       };
+       *pnt1=':';      /* and restore the string */
+       return 0;
+}
+
+
+VMS_GSYM_Parse(symbolS * sp,int Text_Psect){ /* Global variables */
+       VMS_stab_parse(sp,'G',(N_UNDF | N_EXT),(N_DATA | N_EXT),Text_Psect);
+}
+
+
+VMS_LCSYM_Parse(symbolS * sp,int Text_Psect){/* Static symbols - uninitialized */
+       VMS_stab_parse(sp,'S',N_BSS,-1,Text_Psect);
+}
+
+VMS_STSYM_Parse(symbolS * sp,int Text_Psect){ /*Static symbols - initialized */
+       VMS_stab_parse(sp,'S',N_DATA,-1,Text_Psect);
+}
+
+
+/* for register symbols, we must figure out what range of addresses within the
+ * psect are valid. We will use the brackets in the stab directives to give us
+ * guidance as to the PC range that this variable is in scope.  I am still not
+ * completely comfortable with this but as I learn more, I seem to get a better
+ * handle on what is going on.
+ * Caveat Emptor.
+ */
+VMS_RSYM_Parse(symbolS * sp,symbolS * Current_Routine,int Text_Psect){
+       char* pnt;
+       char* pnt1;
+       char* str;
+       int dbx_type;
+       struct VMS_DBG_Symbol* spnt;
+       int j;
+       int maxlen;
+       int i=0;
+       int bcnt=0;
+       int Min_Offset=-1;      /* min PC of validity */
+       int Max_Offset=0; /* max PC of validity */
+       symbolS * symbolP;
+          for(symbolP = sp; symbolP; symbolP = symbol_next(symbolP)) {
+                 /*
+                  *    Dispatch on STAB type
+                  */
+                 switch((unsigned char)symbolP->sy_type) {
+                    case N_LBRAC:
+                               if(bcnt++==0) Min_Offset = symbolP->sy_nlist.n_value;
+                               break;
+                    case N_RBRAC:
+                               if(--bcnt==0) Max_Offset = 
+                                       symbolP->sy_nlist.n_value-1;
+                               break;
+                 }
+          if((Min_Offset != -1) && (bcnt == 0)) break;
+          if((unsigned char)symbolP->sy_type == N_FUN) break;
+          }
+/* check to see that the addresses were defined.  If not, then there were no
+ * brackets in the function, and we must try to search for the next function
+ * Since functions can be in any order, we should search all of the symbol list
+ * to find the correct ending address. */
+       if(Min_Offset == -1){
+         int Max_Source_Offset;
+         int This_Offset;
+         Min_Offset = sp->sy_nlist.n_value;
+          for(symbolP = symbol_rootP; symbolP; symbolP = symbol_next(symbolP)) {
+                 /*
+                  *    Dispatch on STAB type
+                  */
+                 This_Offset = symbolP->sy_nlist.n_value;
+                 switch(symbolP->sy_type) {
+                    case N_TEXT | N_EXT:
+                       if((This_Offset > Min_Offset) && (This_Offset < Max_Offset))
+                                       Max_Offset = This_Offset;
+                               break;
+                    case N_SLINE:
+                       if(This_Offset > Max_Source_Offset)
+                               Max_Source_Offset=This_Offset;
+                 }
+          }
+/* if this is the last routine, then we use the PC of the last source line
+ * as a marker of the max PC for which this reg is valid */
+         if(Max_Offset == 0x7fffffff) Max_Offset = Max_Source_Offset;
+       };
+       dbx_type=0;
+       str=sp->sy_nlist.n_un.n_name;
+       pnt=(char*) strchr(str,':');
+       if(pnt==(char*) NULL) return;   /* no colon present */
+       pnt1=pnt;       /* save this for later*/
+       pnt++;
+       if(*pnt!='r') return 0;
+       pnt = cvt_integer( pnt+1, &dbx_type);
+       spnt = find_symbol(dbx_type);
+       if(spnt==(struct VMS_DBG_Symbol*) NULL) return 0;/*Dunno what this is yet*/
+       *pnt1='\0';
+       maxlen=25+strlen(sp->sy_nlist.n_un.n_name);
+       Local[i++]=maxlen;
+       Local[i++]=spnt->VMS_type;
+       Local[i++]=0xfb;
+       Local[i++]=strlen(sp->sy_nlist.n_un.n_name)+1;
+       Local[i++]=0x00;
+       Local[i++]=0x00;
+       Local[i++]=0x00;
+       Local[i++]=strlen(sp->sy_nlist.n_un.n_name);
+       pnt=sp->sy_nlist.n_un.n_name;
+       fix_name(pnt);  /* if there are bad characters in name, convert them */
+       while(*pnt!='\0') Local[i++]=*pnt++;
+       Local[i++]=0xfd;
+       Local[i++]=0x0f;
+       Local[i++]=0x00;
+       Local[i++]=0x03;
+       Local[i++]=0x01;
+       VMS_Store_Immediate_Data(Local, i, OBJ$C_DBG); i=0;
+       VMS_Set_Data(Text_Psect,Min_Offset,OBJ$C_DBG,1);
+       VMS_Set_Data(Text_Psect,Max_Offset,OBJ$C_DBG,1);
+       Local[i++]=0x03;
+       Local[i++]=sp->sy_nlist.n_value;
+       Local[i++]=0x00;
+       Local[i++]=0x00;
+       Local[i++]=0x00;
+       VMS_Store_Immediate_Data(Local, i, OBJ$C_DBG);
+       *pnt1=':';
+       if(spnt->VMS_type == DBG$C_ADVANCED_TYPE) generate_suffix(spnt,0);
+}
+
+/* this function examines a structure definition, checking all of the elements
+ * to make sure that all of them are fully defined.  The only thing that we
+ * kick out are arrays of undefined structs, since we do not know how big
+ * they are.  All others we can handle with a normal forward reference.
+ */
+static int forward_reference(char* pnt){
+       int i;
+       struct VMS_DBG_Symbol * spnt;
+       struct VMS_DBG_Symbol * spnt1;
+       pnt = cvt_integer(pnt+1,&i);
+       if(*pnt == ';') return 0; /* no forward references */
+       do{
+         pnt=(char*) strchr(pnt,':');
+         pnt = cvt_integer(pnt+1,&i);
+         spnt = find_symbol(i);
+         if(spnt == (struct VMS_DBG_Symbol*) NULL) return 0;
+         while((spnt->advanced == POINTER) || (spnt->advanced == ARRAY)){
+                 i=spnt->type2;
+                 spnt1 = find_symbol(spnt->type2);
+                 if((spnt->advanced == ARRAY) &&
+                       (spnt1 == (struct VMS_DBG_Symbol*) NULL))return 1;
+                 if(spnt1 == (struct VMS_DBG_Symbol*) NULL) break;
+                 spnt=spnt1;
+         };
+         pnt = cvt_integer(pnt+1,&i);
+         pnt = cvt_integer(pnt+1,&i);
+       }while(*++pnt != ';');
+       return 0;       /* no forward refences found */
+}
+
+/* This routine parses the stabs directives to find any definitions of dbx type
+ * numbers.  It makes a note of all of them, creating a structure element
+ * of VMS_DBG_Symbol that describes it.  This also generates the info for the
+ * debugger that describes the struct/union/enum, so that further references
+ * to these data types will be by number
+ *     We have to process pointers right away, since there can be references
+ * to them later in the same stabs directive.  We cannot have forward
+ * references to pointers, (but we can have a forward reference to a pointer to
+ * a structure/enum/union) and this is why we process them immediately.
+ * After we process the pointer, then we search for defs that are nested even
+ * deeper.
+ */
+static int VMS_typedef_parse(char* str){
+       char* pnt;
+       char* pnt1;
+       char* pnt2;
+       int i;
+       int dtype;
+       struct forward_ref * fpnt;
+       int i1,i2,i3;
+       int convert_integer;
+       struct VMS_DBG_Symbol* spnt;
+       struct VMS_DBG_Symbol* spnt1;
+/* check for any nested def's */
+       pnt=(char*)strchr(str+1,'=');
+       if((pnt != (char*) NULL) && (*(str+1) != '*')) 
+               if(VMS_typedef_parse(pnt) == 1 ) return 1;
+/* now find dbx_type of entry */
+       pnt=str-1;
+       if(*pnt == 'c'){        /* check for static constants */
+               *str = '\0';    /* for now we ignore them */
+               return 0;};
+       while((*pnt <= '9')&& (*pnt >= '0')) pnt--;
+       pnt++;  /* and get back to the number */
+       cvt_integer(pnt,&i1);
+       spnt = find_symbol(i1);
+/* first we see if this has been defined already, due to a forward reference*/
+       if(spnt == (struct VMS_DBG_Symbol*) NULL) {
+         if(VMS_Symbol_type_list==(struct VMS_DBG_Symbol*) NULL)
+           {spnt=(struct VMS_DBG_Symbol*) malloc(sizeof(struct VMS_DBG_Symbol));
+            spnt->next = (struct VMS_DBG_Symbol*) NULL;
+           VMS_Symbol_type_list=spnt;}
+         else
+           {spnt=(struct VMS_DBG_Symbol*) malloc(sizeof(struct VMS_DBG_Symbol));
+           spnt->next=VMS_Symbol_type_list;
+           VMS_Symbol_type_list = spnt;};
+         spnt->dbx_type = i1;  /* and save the type */
+       };
+/* for structs and unions, do a partial parse, otherwise we sometimes get
+ * circular definitions that are impossible to resolve. We read enough info
+ * so that any reference to this type has enough info to be resolved 
+ */
+       pnt=str + 1;    /* point to character past equal sign */
+       if((*pnt == 'u') || (*pnt == 's')){
+       };
+       if((*pnt <= '9') && (*pnt >= '0')){
+          if(type_check("void")){ /* this is the void symbol */
+               *str='\0';
+               spnt->advanced = VOID;
+               return 0;};
+          printf("gcc-as warning(debugger output):");
+          printf(" %d is an unknown untyped variable.\n",spnt->dbx_type);
+          return 1;    /* do not know what this is */
+       };
+/* now define this module*/
+       pnt=str + 1;    /* point to character past equal sign */
+       switch (*pnt){
+           case 'r':
+               spnt->advanced= BASIC;
+               if(type_check("int")) {
+                       spnt->VMS_type=DBG$C_SLINT; spnt->data_size=4;}
+               else if(type_check("long int")) {
+                       spnt->VMS_type=DBG$C_SLINT; spnt->data_size=4;}
+               else if(type_check("unsigned int")) {
+                       spnt->VMS_type=DBG$C_ULINT; spnt->data_size = 4;}
+               else if(type_check("long unsigned int")) {
+                       spnt->VMS_type=DBG$C_ULINT; spnt->data_size = 4;}
+               else if(type_check("short int")) {
+                       spnt->VMS_type=DBG$C_SSINT; spnt->data_size = 2;}
+               else if(type_check("short unsigned int")) {
+                       spnt->VMS_type=DBG$C_USINT; spnt->data_size = 2;}
+               else if(type_check("char")) {
+                       spnt->VMS_type=DBG$C_SCHAR; spnt->data_size = 1;}
+               else if(type_check("signed char")) {
+                       spnt->VMS_type=DBG$C_SCHAR; spnt->data_size = 1;}
+               else if(type_check("unsigned char")) {
+                       spnt->VMS_type=DBG$C_UCHAR; spnt->data_size = 1;}
+               else if(type_check("float")) {
+                       spnt->VMS_type=DBG$C_REAL4; spnt->data_size = 4;}
+               else if(type_check("double")) {
+                       spnt->VMS_type=DBG$C_REAL8; spnt->data_size = 8;}
+               pnt1=(char*) strchr(str,';')+1;
+               break;
+           case 's':
+           case 'u':
+               if(*pnt == 's') spnt->advanced= STRUCT;
+                               else spnt->advanced= UNION;
+               spnt->VMS_type = DBG$C_ADVANCED_TYPE;
+               pnt1 = cvt_integer(pnt+1,&spnt->data_size);
+               if(forward_reference(pnt)) {
+                       spnt->struc_numb = -1;
+                       return 1;
+               }
+               spnt->struc_numb = ++structure_count;
+               pnt1--;
+               pnt=get_struct_name(str);
+               VMS_Def_Struct(spnt->struc_numb);
+               fpnt = f_ref_root;
+               while(fpnt != (struct forward_ref*) NULL){
+                       if(fpnt->dbx_type == spnt->dbx_type) {
+                               fpnt->resolved = 'Y';
+                               VMS_Set_Struct(fpnt->struc_numb);
+                               VMS_Store_Struct(spnt->struc_numb);};
+                       fpnt = fpnt->next;};
+               VMS_Set_Struct(spnt->struc_numb);
+               i=0;
+               Local[i++] = 11+strlen(pnt);
+               Local[i++] = DBG$C_STRUCT_START;
+               Local[i++] = 0x80;
+               for(i1=0;i1<4;i1++) Local[i++] = 0x00;
+               Local[i++] = strlen(pnt);
+               pnt2=pnt;
+               while(*pnt2 != '\0') Local[i++] = *pnt2++;
+               i2=spnt->data_size * 8;         /* number of bits */
+               pnt2=(char*) &i2;
+               for(i1=0;i1<4;i1++) Local[i++] = *pnt2++;
+               VMS_Store_Immediate_Data(Local, i, OBJ$C_DBG); i=0;
+               if(pnt != symbol_name) {
+                       pnt += strlen(pnt);
+                       *pnt=':';};     /* replace colon for later */
+               while(*++pnt1 != ';'){
+                 pnt=(char*) strchr(pnt1,':');
+                 *pnt='\0';
+                 pnt2=pnt1;
+                 pnt1 = cvt_integer(pnt+1,&dtype);
+                 pnt1 = cvt_integer(pnt1+1,&i2);
+                 pnt1 = cvt_integer(pnt1+1,&i3);
+                 if((dtype == 1) && (i3 != 32)) { /* bitfield */
+                   Apoint = 0;
+                   push(19+strlen(pnt2),1);
+                   push(0xfa22,2);
+                   push(1+strlen(pnt2),4);
+                   push(strlen(pnt2),1);
+                   while(*pnt2 != '\0') push(*pnt2++,1);
+                   push(i3,2); /* size of bitfield */
+                   push(0x0d22,2);
+                   push(0x00,4);
+                   push(i2,4); /* start position */
+                   VMS_Store_Immediate_Data(Asuffix,Apoint,OBJ$C_DBG);
+                   Apoint=0;
+                 }else{
+                   Local[i++] = 7+strlen(pnt2);
+                   spnt1 = find_symbol(dtype);
+               /* check if this is a forward reference */
+                   if(spnt1 != (struct VMS_DBG_Symbol*) NULL)
+                                Local[i++] = spnt1->VMS_type;
+                       else
+                                Local[i++] = DBG$C_ADVANCED_TYPE;
+                   Local[i++] = DBG$C_STRUCT_ITEM;
+                   pnt=(char*) &i2;            
+                   for(i1=0;i1<4;i1++) Local[i++] = *pnt++;
+                   Local[i++] = strlen(pnt2);
+                   while(*pnt2 != '\0') Local[i++] = *pnt2++;
+                   VMS_Store_Immediate_Data(Local, i, OBJ$C_DBG); i=0;
+                   if(spnt1 == (struct VMS_DBG_Symbol*) NULL)
+                               generate_suffix(spnt1,dtype);
+                   else if(spnt1->VMS_type == DBG$C_ADVANCED_TYPE)
+                               generate_suffix(spnt1,0);
+               };
+               };
+               pnt1++;
+               Local[i++] = 0x01;      /* length byte */
+               Local[i++] = DBG$C_STRUCT_END;
+               VMS_Store_Immediate_Data(Local, i, OBJ$C_DBG); i=0;
+               break;
+           case 'e':
+               spnt->advanced= ENUM;
+               spnt->VMS_type = DBG$C_ADVANCED_TYPE;
+               spnt->struc_numb = ++structure_count;
+               spnt->data_size=4;
+               VMS_Def_Struct(spnt->struc_numb);
+               fpnt = f_ref_root;
+               while(fpnt != (struct forward_ref*) NULL){
+                       if(fpnt->dbx_type == spnt->dbx_type) {
+                               fpnt->resolved = 'Y';
+                               VMS_Set_Struct(fpnt->struc_numb);
+                               VMS_Store_Struct(spnt->struc_numb);};
+                       fpnt = fpnt->next;};
+               VMS_Set_Struct(spnt->struc_numb);
+               i=0;
+               Local[i++] = 3+strlen(symbol_name);
+               Local[i++] = DBG$C_ENUM_START;
+               Local[i++] = 0x20;
+               Local[i++] = strlen(symbol_name);
+               pnt2=symbol_name;
+               while(*pnt2 != '\0') Local[i++] = *pnt2++;
+               VMS_Store_Immediate_Data(Local, i, OBJ$C_DBG); i=0;
+               while(*++pnt != ';') {
+                 pnt1=(char*) strchr(pnt,':');
+                 *pnt1++='\0';
+                 pnt1 = cvt_integer(pnt1,&i1);
+                 Local[i++] = 7+strlen(pnt);
+                 Local[i++] = DBG$C_ENUM_ITEM;
+                 Local[i++] = 0x00;
+                 pnt2=(char*) &i1;
+                 for(i2=0;i2<4;i2++) Local[i++] = *pnt2++;
+                 Local[i++] = strlen(pnt);
+                 pnt2=pnt;
+                 while(*pnt != '\0') Local[i++] = *pnt++;
+                 VMS_Store_Immediate_Data(Local, i, OBJ$C_DBG); i=0;
+                 pnt= pnt1;    /* Skip final semicolon */
+               };
+               Local[i++] = 0x01; /* len byte */
+               Local[i++] = DBG$C_ENUM_END;
+               VMS_Store_Immediate_Data(Local, i, OBJ$C_DBG); i=0;
+               pnt1=pnt + 1;
+               break;
+           case 'a':
+               spnt->advanced= ARRAY;
+               spnt->VMS_type = DBG$C_ADVANCED_TYPE;
+               pnt=(char*)strchr(pnt,';');  if (pnt == (char*) NULL) return 1;
+               pnt1 = cvt_integer(pnt+1,&spnt->index_min);
+               pnt1 = cvt_integer(pnt1+1,&spnt->index_max);
+               pnt1 = cvt_integer(pnt1+1,&spnt->type2);
+               break;
+           case 'f':
+               spnt->advanced= FUNCTION;
+               spnt->VMS_type = DBG$C_FUNCTION_ADDR;
+                       /* this masquerades as a basic type*/
+               spnt->data_size=4;
+               pnt1 = cvt_integer(pnt+1,&spnt->type2);
+               break;
+           case '*':
+               spnt->advanced= POINTER;
+               spnt->VMS_type = DBG$C_ADVANCED_TYPE;
+               spnt->data_size=4;
+               pnt1 = cvt_integer(pnt+1,&spnt->type2);
+               pnt=(char*)strchr(str+1,'=');
+               if((pnt != (char*) NULL)) 
+                       if(VMS_typedef_parse(pnt) == 1 ) return 1;
+               break;
+           default:
+               spnt->advanced= UNKNOWN;
+               spnt->VMS_type = 0;
+               printf("gcc-as warning(debugger output):");
+               printf(" %d is an unknown type of variable.\n",spnt->dbx_type);
+               return 1; /* unable to decipher */
+       };
+/* this removes the evidence of the definition so that the outer levels of 
+parsing do not have to worry about it */
+       pnt=str;
+       while (*pnt1 != '\0') *pnt++ = *pnt1++;
+       *pnt = '\0';
+       return 0;
+}
+
+
+/* 
+ * This is the root routine that parses the stabs entries for definitions.
+ * it calls VMS_typedef_parse, which can in turn call itself.
+ * We need to be careful, since sometimes there are forward references to
+ * other symbol types, and these cannot be resolved until we have completed
+ * the parse.
+ */
+int VMS_LSYM_Parse(){
+       char *pnt;
+       char *pnt1;
+       char *pnt2;
+       char *str;
+       char fixit[10];
+       int incomplete,i,pass,incom1;
+       struct VMS_DBG_Symbol* spnt;
+       struct VMS_Symbol *     vsp;
+       struct forward_ref * fpnt;
+       symbolS * sp;
+       pass=0;
+       incomplete = 0;
+          do{
+          incom1=incomplete;
+          incomplete = 0;
+          for(sp = symbol_rootP; sp; sp = symbol_next(sp)) {
+               /*
+                *      Deal with STAB symbols
+                */
+               if ((sp->sy_nlist.n_type & N_STAB) != 0) {
+                 /*
+                  *    Dispatch on STAB type
+                  */
+                 switch((unsigned char)sp->sy_nlist.n_type) {
+                       case N_GSYM:
+                       case N_LCSYM:
+                       case N_STSYM:
+                       case N_PSYM:
+                       case N_RSYM:
+                       case N_LSYM:
+                       case N_FUN:     /*sometimes these contain typedefs*/
+                               str=sp->sy_nlist.n_un.n_name;
+                               symbol_name = str;
+                               pnt=(char*)strchr(str,':');
+                               if(pnt== (char*) NULL) break;
+                               *pnt='\0';
+                               pnt1=pnt+1;
+                               pnt2=(char*)strchr(pnt1,'=');
+                               if(pnt2 == (char*) NULL){
+                                               *pnt=':';       /* replace colon */
+                                               break;};        /* no symbol here */
+                               incomplete += VMS_typedef_parse(pnt2);
+                               *pnt=':';    /* put back colon so variable def code finds dbx_type*/
+                               break;
+                 }     /*switch*/
+               }       /* if */
+          }            /*for*/
+       pass++;
+       } while((incomplete != 0) && (incomplete != incom1 ));
+                       /* repeat until all refs resolved if possible */
+/*     if(pass > 1) printf(" Required %d passes\n",pass);*/
+       if(incomplete != 0){    
+               printf("gcc-as warning(debugger output):");
+               printf("Unable to resolve %d circular references.\n",incomplete);
+               };
+       fpnt = f_ref_root;
+       symbol_name="\0";
+       while(fpnt != (struct forward_ref*) NULL){
+               if(fpnt->resolved != 'Y') {
+                 if( find_symbol(fpnt->dbx_type) != 
+                       (struct VMS_DBG_Symbol*) NULL){
+                           printf("gcc-as warning(debugger output):");
+                           printf("Forward reference error, dbx type %d\n",
+                                       fpnt->dbx_type);
+                           break;};
+                 fixit[0]=0;
+                 sprintf(&fixit[1],"%d=s4;",fpnt->dbx_type);
+                 pnt2=(char*)strchr(&fixit[1],'=');
+                 VMS_typedef_parse(pnt2);
+                 };
+               fpnt = fpnt->next;};
+}
+
+static symbolS* Current_Routine;
+static int Text_Psect;
+
+static Define_Local_Symbols(symbolS* s1,symbolS* s2){
+       symbolS * symbolP1;
+       for(symbolP1 = symbol_next(s1); symbolP1 != s2; symbolP1 = symbol_next(symbolP1)) {
+               if (symbolP1 == (symbolS *)NULL) return;
+               if (symbolP1->sy_nlist.n_type == N_FUN) return;
+               /*
+                *      Deal with STAB symbols
+                */
+               if ((symbolP1->sy_nlist.n_type & N_STAB) != 0) {
+                 /*
+                  *    Dispatch on STAB type
+                  */
+                 switch((unsigned char)symbolP1->sy_nlist.n_type) {
+                       case N_LSYM:
+                       case N_PSYM:
+                          VMS_local_stab_Parse(symbolP1);
+                          break;
+                       case N_RSYM:
+                          VMS_RSYM_Parse(symbolP1,Current_Routine,Text_Psect);
+                               break;
+                 }     /*switch*/
+               }       /* if */
+          }            /* for */
+}
+
+static symbolS* Define_Routine(symbolS* symbolP,int Level){
+       symbolS * sstart;
+       symbolS * symbolP1;
+       char    str[10];
+       char * pnt;
+       int rcount = 0;
+       int Offset;
+       sstart = symbolP;
+       for(symbolP1 = symbol_next(symbolP); symbolP1; symbolP1 = symbol_next(symbolP1)) {
+               if (symbolP1->sy_nlist.n_type == N_FUN) break;
+               /*
+                *      Deal with STAB symbols
+                */
+               if ((symbolP1->sy_nlist.n_type & N_STAB) != 0) {
+                 /*
+                  *    Dispatch on STAB type
+                  */
+                 if((unsigned char)symbolP1->sy_nlist.n_type == N_FUN) break;
+                 switch((unsigned char)symbolP1->sy_nlist.n_type) {
+                       case N_LBRAC:
+                               if(Level != 0) {
+                                  pnt = str +sprintf(str,"$%d",rcount++);
+                                  *pnt = '\0';
+                                  VMS_TBT_Block_Begin(symbolP1,Text_Psect,str);
+                               };
+                               Offset = symbolP1->sy_nlist.n_value;
+                               Define_Local_Symbols(sstart,symbolP1);
+                               symbolP1 = 
+                                   Define_Routine(symbolP1,Level+1);
+                               if(Level != 0)
+                                 VMS_TBT_Block_End(symbolP1->sy_nlist.n_value -
+                                          Offset);
+                               sstart=symbolP1;
+                               break;
+                       case N_RBRAC:
+                               return symbolP1;
+                 }     /*switch*/
+               }       /* if */
+          }            /* for */
+       /* we end up here if there were no brackets in this function. Define
+everything */
+       Define_Local_Symbols(sstart,(symbolS *) 0);
+}
+
+VMS_DBG_Define_Routine(symbolS* symbolP,symbolS* Curr_Routine,int Txt_Psect){
+       Current_Routine = Curr_Routine;
+       Text_Psect = Txt_Psect;
+       Define_Routine(symbolP,0);
+}
diff --git a/gas/config/vms/vms.c b/gas/config/vms/vms.c
new file mode 100644 (file)
index 0000000..cd3bb59
--- /dev/null
@@ -0,0 +1,3741 @@
+/* vms.c -- Write out a VAX/VMS object file
+   Copyright (C) 1987, 1988 Free Software Foundation, Inc.
+
+This file is part of GAS, the GNU Assembler.
+
+GAS 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 1, or (at your option)
+any later version.
+
+GAS 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 GAS; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* Written by David L. Kashtan */
+#include <ctype.h>
+#include <stdio.h>
+
+#include "as.h"
+#include "subsegs.h"
+#include "obstack.h"
+#include "struc-symbol.h"
+#include "write.h"
+#include "symbols.h"
+
+#ifdef VMS             /* THIS MODULE IS FOR VMS ONLY */
+
+#include <stab.h>
+#include "objrecdef.h"                 /* Define VMS Object record lang. */
+#include <vms/fabdef.h>                        /* Define File Access Block       */
+#include <vms/namdef.h>                        /* Define NAM Block               */
+#include <vms/xabdef.h>                        /* Define XAB                     */
+#include <vms/xabdatdef.h>             /* Define Date XAB                */
+#include <vms/xabfhcdef.h>             /* Define File Header XAB         */
+
+const pseudo_typeS obj_pseudo_table[] = {
+  { "const",   s_const,        0       },
+
+}; /* obj_pseudo_table */
+
+/*
+ *     Version string of the compiler that produced the code we are
+ *     assembling.  (And this assembler, if we do not have compiler info.)
+ */
+extern char version_string[];
+char *compiler_version_string;
+
+extern char *myname;
+static symbolS *Entry_Point_Symbol = 0;        /* Pointer to "_main"    */
+
+/*
+ *     We augment the "gas" symbol structure with this
+ */
+struct VMS_Symbol {
+       struct VMS_Symbol *Next;
+       struct symbol *Symbol;
+       int Size;
+       int Psect_Index;
+       int Psect_Offset;
+       };
+struct VMS_Symbol *VMS_Symbols = 0;
+
+/* we need this to keep track of the various input files, so that we can
+ * give the debugger the correct source line 
+ */
+
+struct input_file{
+       struct input_file* next;
+       struct input_file* same_file_fpnt;
+       int file_number;
+       int max_line;
+       int min_line;
+       int offset;
+       char flag;
+       char * name;
+       symbolS * spnt;
+       };
+
+static struct input_file * file_root = (struct input_file*)NULL;
+
+struct input_file * find_file(symbolS *);
+
+\f
+/*
+ *     If the procedure "main()" exists we have to add the instruction
+ *     "jsb c$main_args" at the beginning to be compatible with VAX-11 "C".
+ */
+VMS_Check_For_Main()
+{
+  register symbolS *symbolP;
+#ifdef HACK_DEC_C_STARTUP      /* JF */
+  register struct frchain *frchainP;
+  register fragS *fragP;
+  register fragS **prev_fragPP;
+  register struct fix *fixP;
+  register fragS *New_Frag;
+  int i;
+#endif HACK_DEC_C_STARTUP
+
+  symbolP = (struct symbol *)symbol_find("_main");
+  if (symbolP && (symbolP->sy_nlist.n_type == (N_TEXT | N_EXT))) {
+#ifdef HACK_DEC_C_STARTUP
+       if( !flagseen['+']) {
+#endif
+               /*
+                *      Remember the entry point symbol
+                */
+               Entry_Point_Symbol = symbolP;
+#ifdef HACK_DEC_C_STARTUP
+       } else {
+               /*
+                *      Scan all the fragment chains for the one with "_main"
+                *      (Actually we know the fragment from the symbol, but we need
+                *       the previous fragment so we can change its pointer)
+                */
+               frchainP = frchain_root;
+               while(frchainP) {
+                       /*
+                        *      Scan all the fragments in this chain, remembering
+                        *      the "previous fragment"
+                        */
+                       prev_fragPP = &frchainP->frch_root;
+                       fragP = frchainP->frch_root;
+                       while(fragP && (fragP != frchainP->frch_last)) {
+                               /*
+                                *      Is this the fragment?
+                                */
+                               if (fragP == symbolP->sy_frag) {
+                                       /*
+                                        *      Yes: Modify the fragment by replacing
+                                        *           it with a new fragment.
+                                        */
+                                       New_Frag = (fragS *)
+                                               xmalloc(sizeof(*New_Frag) +
+                                                               fragP->fr_fix +
+                                                               fragP->fr_var +
+                                                               5);
+                                       /*
+                                        *      The fragments are the same except
+                                        *      that the "fixed" area is larger
+                                        */
+                                       *New_Frag = *fragP;
+                                       New_Frag->fr_fix += 6;
+                                       /*
+                                        *      Copy the literal data opening a hole
+                                        *      2 bytes after "_main" (i.e. just after
+                                        *      the entry mask).  Into which we place
+                                        *      the JSB instruction.
+                                        */
+                                       New_Frag->fr_literal[0] = fragP->fr_literal[0];
+                                       New_Frag->fr_literal[1] = fragP->fr_literal[1];
+                                       New_Frag->fr_literal[2] = 0x16; /* Jsb */
+                                       New_Frag->fr_literal[3] = 0xef;
+                                       New_Frag->fr_literal[4] = 0;
+                                       New_Frag->fr_literal[5] = 0;
+                                       New_Frag->fr_literal[6] = 0;
+                                       New_Frag->fr_literal[7] = 0;
+                                       for(i = 2; i < fragP->fr_fix + fragP->fr_var; i++)
+                                               New_Frag->fr_literal[i+6] =
+                                                       fragP->fr_literal[i];
+                                       /*
+                                        *      Now replace the old fragment with the
+                                        *      newly generated one.
+                                        */
+                                       *prev_fragPP = New_Frag;
+                                       /*
+                                        *      Remember the entry point symbol
+                                        */
+                                       Entry_Point_Symbol = symbolP;
+                                       /*
+                                        *      Scan the text area fixup structures
+                                        *      as offsets in the fragment may have
+                                        *      changed
+                                        */
+                                       for(fixP = text_fix_root; fixP; fixP = fixP->fx_next) {
+                                               /*
+                                                *      Look for references to this
+                                                *      fragment.
+                                                */
+                                               if (fixP->fx_frag == fragP) {
+                                                       /*
+                                                        *      Change the fragment
+                                                        *      pointer
+                                                        */
+                                                       fixP->fx_frag = New_Frag;
+                                                       /*
+                                                        *      If the offset is after
+                                                        *      the entry mask we need
+                                                        *      to account for the JSB
+                                                        *      instruction we just
+                                                        *      inserted.
+                                                        */
+                                                       if (fixP->fx_where >= 2)
+                                                               fixP->fx_where += 6;
+                                               }
+                                       }
+                                       /*
+                                        *      Scan the symbols as offsets in the
+                                        *      fragment may have changed
+                                        */
+                                       for(symbolP = symbol_rootP;
+                                           symbolP;
+                                           symbolP = symbol_next(symbolP)) {
+                                               /*
+                                                *      Look for references to this
+                                                *      fragment.
+                                                */
+                                               if (symbolP->sy_frag == fragP) {
+                                                       /*
+                                                        *      Change the fragment
+                                                        *      pointer
+                                                        */
+                                                       symbolP->sy_frag = New_Frag;
+                                                       /*
+                                                        *      If the offset is after
+                                                        *      the entry mask we need
+                                                        *      to account for the JSB
+                                                        *      instruction we just
+                                                        *      inserted.
+                                                        */
+                                                       if (symbolP->sy_nlist.n_value >= 2)
+                                                               symbolP->sy_nlist.n_value += 6;
+                                               }
+                                       }
+                                       /*
+                                        *      Make a symbol reference to
+                                        *      "_c$main_args" so we can get
+                                        *      its address inserted into the
+                                        *      JSB instruction.
+                                        */
+                                       symbolP = (symbolS *)xmalloc(sizeof(*symbolP));
+                                       symbolP->sy_nlist.n_un.n_name = "_c$main_args";
+                                       symbolP->sy_nlist.n_type = N_UNDF;
+                                       symbolP->sy_nlist.n_other = 0;
+                                       symbolP->sy_nlist.n_desc = 0;
+                                       symbolP->sy_nlist.n_value = 0;
+                                       symbolP->sy_name_offset = 0;
+                                       symbolP->sy_number = 0;
+                                       symbolP->sy_frag = New_Frag;
+                                       symbolP->sy_forward = 0;
+                                       /* this actually inserts at the beginning of the list */
+                                       symbol_append(symbol_rootP, symbolP, &symbol_rootP, &symbol_lastP);
+
+                                       symbol_rootP = symbolP;
+                                       /*
+                                        *      Generate a text fixup structure
+                                        *      to get "_c$main_args" stored into the
+                                        *      JSB instruction.
+                                        */
+                                       fixP = (struct fix *)xmalloc(sizeof(*fixP));
+                                       fixP->fx_frag = New_Frag;
+                                       fixP->fx_where = 4;
+                                       fixP->fx_addsy = symbolP;
+                                       fixP->fx_subsy = 0;
+                                       fixP->fx_offset = 0;
+                                       fixP->fx_size = sizeof(long);
+                                       fixP->fx_pcrel = 1;
+                                       fixP->fx_next = text_fix_root;
+                                       text_fix_root = fixP;
+                                       /*
+                                        *      Now make sure we exit from the loop
+                                        */
+                                       frchainP = 0;
+                                       break;
+                               }
+                               /*
+                                *      Try the next fragment
+                                */
+                               prev_fragPP = &fragP->fr_next;
+                               fragP = fragP->fr_next;
+                       }
+                       /*
+                        *      Try the next fragment chain
+                        */
+                       if (frchainP) frchainP=frchainP->frch_next;
+               }
+       }
+#endif /* HACK_DEC_C_STARTUP */
+  }
+}
+\f
+/*
+ *     Write a VAX/VMS object file (everything else has been done!)
+ */
+VMS_write_object_file(text_siz, data_siz, text_frag_root, data_frag_root)
+unsigned text_siz;
+unsigned data_siz;
+struct frag *text_frag_root;
+struct frag *data_frag_root;
+{
+   register fragS *            fragP;
+   register symbolS *          symbolP;
+   register symbolS *          sp;
+   register struct fix *       fixP;
+   register struct VMS_Symbol *        vsp;
+   int Local_Initialized_Data_Size = 0;
+   int Psect_Number = 0;               /* Psect Index Number */
+   int Text_Psect = -1;                        /* Text Psect Index   */
+   int Data_Psect = -2;                        /* Data Psect Index   JF: Was -1 */
+   int Bss_Psect = -3;                 /* Bss Psect Index    JF: Was -1 */
+
+   /*
+    *  Create the VMS object file
+    */
+   Create_VMS_Object_File();
+   /*
+    *  Write the module header records
+    */
+   Write_VMS_MHD_Records();
+\f
+    /*
+     * Generate the VMS object file records
+     * 1st GSD then TIR records
+     */
+
+       /*******       Global Symbol Dictionary       *******/
+       /*
+        *      Define the Text Psect
+        */
+       if (text_siz > 0) {
+               Text_Psect = Psect_Number++;
+               VMS_Psect_Spec("$code",text_siz,"TEXT");
+       }
+       /*
+        *      Define the BSS Psect
+        */
+       if (local_bss_counter > 0) {
+               Bss_Psect = Psect_Number++;
+               VMS_Psect_Spec("$uninitialized_data",local_bss_counter,"DATA");
+       }
+       /*
+        *      Now scan the symbols and emit the appropriate GSD records
+        */
+       for (sp = symbol_rootP; sp; sp = symbol_next(sp)) {
+               /*
+                *      Dispatch on symbol type
+                */
+               switch(sp->sy_type) {
+                       /*
+                        *      Global uninitialized data
+                        */
+                       case N_UNDF | N_EXT:
+                               /*
+                                *      Make a VMS data symbol entry
+                                */
+                               vsp = (struct VMS_Symbol *)
+                                       xmalloc(sizeof(*vsp));
+                               vsp->Symbol = sp;
+                               vsp->Size = sp->sy_nlist.n_value;
+                               vsp->Psect_Index = Psect_Number++;
+                               vsp->Psect_Offset = 0;
+                               vsp->Next = VMS_Symbols;
+                               VMS_Symbols = vsp;
+                               sp->sy_number = (int)vsp;
+                               /*
+                                *      Make the psect for this data
+                                */
+                               if(sp->sy_nlist.n_other)
+                                       VMS_Psect_Spec(sp->sy_nlist.n_un.n_name,
+                                              vsp->Size,
+                                              "CONST");
+                               else
+                                       VMS_Psect_Spec(sp->sy_nlist.n_un.n_name,
+                                              vsp->Size,
+                                              "COMMON");
+#ifdef NOT_VAX_11_C_COMPATIBLE
+                               /*
+                                *      Place a global symbol at the
+                                *      beginning of the Psect
+                                */
+                               VMS_Global_Symbol_Spec(sp->sy_nlist.n_un.n_name,
+                                                      vsp->Psect_Index,
+                                                      0,
+                                                      1);
+#endif NOT_VAX_11_C_COMPATIBLE
+                               break;
+                       /*
+                        *      Local uninitialized data
+                        */
+                       case N_BSS:
+                               /*
+                                *      Make a VMS data symbol entry
+                                */
+                               vsp = (struct VMS_Symbol *)
+                                       xmalloc(sizeof(*vsp));
+                               vsp->Symbol = sp;
+                               vsp->Size = 0;
+                               vsp->Psect_Index = Bss_Psect;
+                               vsp->Psect_Offset =
+                                       sp->sy_nlist.n_value -
+                                               bss_address_frag . fr_address;
+                               vsp->Next = VMS_Symbols;
+                               VMS_Symbols = vsp;
+                               sp->sy_number = (int)vsp;
+                               break;
+                       /*
+                        *      Global initialized data
+                        */
+                       case N_DATA | N_EXT:
+                               /*
+                                *      Make a VMS data symbol entry
+                                */
+                               vsp = (struct VMS_Symbol *)
+                                       xmalloc(sizeof(*vsp));
+                               vsp->Symbol = sp;
+                               vsp->Size = VMS_Initialized_Data_Size(sp,
+                                                       text_siz + data_siz);
+                               vsp->Psect_Index = Psect_Number++;
+                               vsp->Psect_Offset = 0;
+                               vsp->Next = VMS_Symbols;
+                               VMS_Symbols = vsp;
+                               sp->sy_number = (int)vsp;
+                               /*
+                                *      Make its psect
+                                */
+                               if(sp->sy_nlist.n_other)
+                                       VMS_Psect_Spec(sp->sy_nlist.n_un.n_name,
+                                              vsp->Size,
+                                              "CONST");
+                               else
+                                       VMS_Psect_Spec(sp->sy_nlist.n_un.n_name,
+                                              vsp->Size,
+                                              "COMMON");
+#ifdef NOT_VAX_11_C_COMPATIBLE
+                               /*
+                                *      Place a global symbol at the
+                                *      beginning of the Psect
+                                */
+                               VMS_Global_Symbol_Spec(sp->sy_nlist.n_un.n_name,
+                                                      vsp->Psect_Index,
+                                                      0,
+                                                      1);
+#endif NOT_VAX_11_C_COMPATIBLE
+                               break;
+                       /*
+                        *      Local initialized data
+                        */
+                       case N_DATA:
+                               /*
+                                *      Make a VMS data symbol entry
+                                */
+                               vsp = (struct VMS_Symbol *)
+                                       xmalloc(sizeof(*vsp));
+                               vsp->Symbol = sp;
+                               vsp->Size = 
+                                       VMS_Initialized_Data_Size(sp,
+                                                         text_siz + data_siz);
+                               vsp->Psect_Index = Data_Psect;
+                               vsp->Psect_Offset =
+                                       Local_Initialized_Data_Size;
+                               Local_Initialized_Data_Size += vsp->Size;
+                               vsp->Next = VMS_Symbols;
+                               VMS_Symbols = vsp;
+                               sp->sy_number = (int)vsp;
+                               break;
+                       /*
+                        *      Global Text definition
+                        */
+                       case N_TEXT | N_EXT: {
+                               unsigned short Entry_Mask;
+
+                               /*
+                                *      Get the entry mask
+                                */
+                               fragP = sp->sy_frag;
+                               Entry_Mask = (fragP->fr_literal[0] & 0xff) +
+                                               ((fragP->fr_literal[1] & 0xff)
+                                                       << 8);
+                               /*
+                                *      Define the Procedure entry pt.
+                                */
+                               VMS_Procedure_Entry_Pt(sp->sy_nlist.n_un.n_name,
+                                                      Text_Psect,
+                                                      sp->sy_nlist.n_value,
+                                                      Entry_Mask);
+                               break;
+                       }
+                       /*
+                        *      Local Text definition
+                        */
+                       case N_TEXT:
+                               /*
+                                *      Make a VMS data symbol entry
+                                */
+                                if(Text_Psect != -1) {
+                                       vsp = (struct VMS_Symbol *)
+                                               xmalloc(sizeof(*vsp));
+                                       vsp->Symbol = sp;
+                                       vsp->Size = 0;
+                                       vsp->Psect_Index = Text_Psect;
+                                       vsp->Psect_Offset = sp->sy_nlist.n_value;
+                                       vsp->Next = VMS_Symbols;
+                                       VMS_Symbols = vsp;
+                                       sp->sy_number = (int)vsp;
+                                }
+                               break;
+                       /*
+                        *      Global Reference
+                        */
+                       case N_UNDF:
+                               /*
+                                *      Make a GSD global symbol reference
+                                *      record.
+                                */
+                               VMS_Global_Symbol_Spec(sp->sy_nlist.n_un.n_name,
+                                                      0,
+                                                      0,
+                                                      0);
+                               break;
+                       /*
+                        *      Anything else
+                        */
+                       default:
+                               /*
+                                *      Ignore STAB symbols
+                                *      Including .stabs emitted by g++
+                                */
+                               if ((sp->sy_type & N_STAB) != 0 || sp->sy_nlist.n_type==22)
+                                       break;
+                               /*
+                                *      Error
+                                */
+                               if(sp->sy_nlist.n_type !=22)
+                                       printf(" ERROR, unknown type (%d)\n",
+                                               sp->sy_nlist.n_type);
+                               break;
+               }
+       }
+       /*
+        *      Define the Data Psect
+        */
+       if ((data_siz > 0) && (Local_Initialized_Data_Size > 0)) {
+               /*
+                *      Do it
+                */
+               Data_Psect = Psect_Number++;
+               VMS_Psect_Spec("$data",
+                               Local_Initialized_Data_Size,
+                               "DATA");
+               /*
+                *      Scan the VMS symbols and fill in the data psect
+                */
+               for (vsp = VMS_Symbols; vsp; vsp = vsp->Next) {
+                       /*
+                        *      Only look for undefined psects
+                        */
+                       if (vsp->Psect_Index < 0)  {
+                               /*
+                                *      And only initialized data
+                                */
+                               if (vsp->Symbol->sy_nlist.n_type == N_DATA)
+                                       vsp->Psect_Index = Data_Psect;
+                       }
+               }
+       }
+\f
+       /*******  Text Information and Relocation Records  *******/
+       /*
+        *      Write the text segment data
+        */
+       if (text_siz > 0) {
+               /*
+                *      Scan the text fragments
+                */
+               for(fragP = text_frag_root; fragP; fragP = fragP->fr_next) {
+                       /*
+                        *      Stop if we get to the data fragments
+                        */
+                       if (fragP == data_frag_root) break;
+                       /*
+                        *      Ignore fragments with no data
+                        */
+                       if ((fragP->fr_fix == 0) && (fragP->fr_var == 0))
+                               continue;
+                       /*
+                        *      Go the the appropriate offset in the
+                        *      Text Psect.
+                        */
+                       VMS_Set_Psect(Text_Psect,fragP->fr_address,OBJ$C_TIR);
+                       /*
+                        *      Store the "fixed" part
+                        */
+                       if (fragP->fr_fix)
+                               VMS_Store_Immediate_Data(fragP->fr_literal,
+                                                        fragP->fr_fix,
+                                                        OBJ$C_TIR);
+                       /*
+                        *      Store the "variable" part
+                        */
+                       if (fragP->fr_var && fragP->fr_offset)
+                               VMS_Store_Repeated_Data(fragP->fr_offset,
+                                                       fragP->fr_literal+
+                                                            fragP->fr_fix,
+                                                       fragP->fr_var,
+                                                       OBJ$C_TIR);
+               }
+               /*
+                *      Now we go through the text segment fixups and
+                *      generate TIR records to fix up addresses within
+                *      the Text Psect
+                */
+               for(fixP = text_fix_root; fixP; fixP = fixP->fx_next) {
+                       /*
+                        *      We DO handle the case of "Symbol - Symbol" as
+                        *      long as it is in the same segment.
+                        */
+                       if (fixP->fx_subsy && fixP->fx_addsy) {
+                               int i;
+
+                               /*
+                                *      They need to be in the same segment
+                                */
+                               if (fixP->fx_subsy->sy_type !=
+                                               fixP->fx_addsy->sy_type)
+                                       error("Fixup data addsy and subsy didn't have the same type");
+                               /*
+                                *      And they need to be in one that we
+                                *      can check the psect on
+                                */
+                               if (((fixP->fx_addsy->sy_type & ~N_EXT) != N_DATA) &&
+                                   ((fixP->fx_addsy->sy_type & ~N_EXT) != N_TEXT))
+                                       error("Fixup data addsy and subsy didn't have an appropriate type");
+                               /*
+                                *      This had better not be PC relative!
+                                */
+                               if (fixP->fx_pcrel)
+                                       error("Fixup data was erroneously \"pcrel\"");
+                               /*
+                                *      Subtract their values to get the
+                                *      difference.
+                                */
+                               i = fixP->fx_addsy->sy_value -
+                                               fixP->fx_subsy->sy_value;
+                               /*
+                                *      Now generate the fixup object records
+                                *      Set the psect and store the data
+                                */
+                               VMS_Set_Psect(Text_Psect,
+                                             fixP->fx_where +
+                                                fixP->fx_frag->fr_address,
+                                             OBJ$C_TIR);
+                               VMS_Store_Immediate_Data(&i,
+                                                        fixP->fx_size,
+                                                        OBJ$C_TIR);
+                               /*
+                                *      Done
+                                */
+                               continue;
+                       }
+                       /*
+                        *      Size will HAVE to be "long"
+                        */
+                       if (fixP->fx_size != sizeof(long))
+                               error("Fixup datum was not a longword");
+                       /*
+                        *      Symbol must be "added" (if it is ever
+                        *                              subtracted we can
+                        *                              fix this assumption)
+                        */
+                       if (fixP->fx_addsy == 0)
+                               error("Fixup datum was not \"fixP->fx_addsy\"");
+                       /*
+                        *      Store the symbol value in a PIC fashion
+                        */
+                       VMS_Store_PIC_Symbol_Reference(fixP->fx_addsy,
+                                                      fixP->fx_offset,
+                                                      fixP->fx_pcrel,
+                                                      Text_Psect,
+                                                      fixP->fx_where +
+                                                         fixP->fx_frag->fr_address,
+                                                      OBJ$C_TIR);
+                       /*
+                        *      Check for indirect address reference,
+                        *      which has to be fixed up (as the linker
+                        *      will screw it up with TIR$C_STO_PICR).
+                        */
+                       if (fixP->fx_pcrel)
+                               VMS_Fix_Indirect_Reference(Text_Psect,
+                                                          fixP->fx_where +
+                                                               fixP->fx_frag->fr_address,
+                                                          fixP->fx_frag,
+                                                          text_frag_root);
+               }
+       }
+       /*
+        *      Store the Data segment:
+        *
+        *      Since this is REALLY hard to do any other way,
+        *      we actually manufacture the data segment and
+        *      the store the appropriate values out of it.
+        */
+       if (data_siz > 0) {
+               char *Data_Segment;
+
+               /*
+                *      Allocate the data segment
+                */
+               Data_Segment = (char *)xmalloc(data_siz);
+               /*
+                *      Run through the data fragments, filling in the segment
+                */
+               for(fragP = data_frag_root; fragP; fragP = fragP->fr_next) {
+                       register long int               count;
+                       register char    *              fill_literal;
+                       register long int               fill_size;
+                       int i;
+
+                       i = fragP->fr_address - text_siz;
+                       if (fragP->fr_fix)
+                               bcopy(fragP->fr_literal,
+                                     Data_Segment + i,
+                                     fragP->fr_fix);
+                       i += fragP->fr_fix;
+
+                       fill_literal= fragP -> fr_literal + fragP -> fr_fix;
+                       fill_size   = fragP -> fr_var;
+                       for (count = fragP -> fr_offset;  count;  count --) {
+                               if (fill_size)
+                                       bcopy(fill_literal,
+                                             Data_Segment + i,
+                                             fill_size);
+                               i += fill_size;
+                       }
+               }
+               /*
+                *      Now we can run through all the data symbols
+                *      and store the data
+                */
+               for(vsp = VMS_Symbols; vsp; vsp = vsp->Next) {
+                       /*
+                        *      Ignore anything other than data symbols
+                        */
+                       if ((vsp->Symbol->sy_nlist.n_type & ~N_EXT) != N_DATA)
+                               continue;
+                       /*
+                        *      Set the Psect + Offset
+                        */
+                       VMS_Set_Psect(vsp->Psect_Index,
+                                     vsp->Psect_Offset,
+                                     OBJ$C_TIR);
+                       /*
+                        *      Store the data
+                        */
+                       VMS_Store_Immediate_Data(Data_Segment +
+                                                       vsp->Symbol->sy_nlist.n_value -
+                                                               text_siz,
+                                                vsp->Size,
+                                                OBJ$C_TIR);
+               }
+               /*
+                *      Now we go through the data segment fixups and
+                *      generate TIR records to fix up addresses within
+                *      the Data Psects
+                */
+               for(fixP = data_fix_root; fixP; fixP = fixP->fx_next) {
+                       /*
+                        *      Find the symbol for the containing datum
+                        */
+                       for(vsp = VMS_Symbols; vsp; vsp = vsp->Next) {
+                               /*
+                                *      Only bother with Data symbols
+                                */
+                               sp = vsp->Symbol;
+                               if ((sp->sy_nlist.n_type & ~N_EXT) != N_DATA)
+                                       continue;
+                               /*
+                                *      Ignore symbol if After fixup
+                                */
+                               if (sp->sy_nlist.n_value >
+                                       (fixP->fx_where +
+                                               fixP->fx_frag->fr_address))
+                                       continue;
+                               /*
+                                *      See if the datum is here
+                                */
+                               if ((sp->sy_nlist.n_value + vsp->Size) <=
+                                       (fixP->fx_where +
+                                               fixP->fx_frag->fr_address))
+                                       continue;
+                               /*
+                                *      We DO handle the case of "Symbol - Symbol" as
+                                *      long as it is in the same segment.
+                                */
+                               if (fixP->fx_subsy && fixP->fx_addsy) {
+                                       int i;
+
+                                       /*
+                                        *      They need to be in the same segment
+                                        */
+                                       if (fixP->fx_subsy->sy_type !=
+                                                       fixP->fx_addsy->sy_type)
+                                               error("Fixup data addsy and subsy didn't have the same type");
+                                       /*
+                                        *      And they need to be in one that we
+                                        *      can check the psect on
+                                        */
+                                       if (((fixP->fx_addsy->sy_type & ~N_EXT) != N_DATA) &&
+                                           ((fixP->fx_addsy->sy_type & ~N_EXT) != N_TEXT))
+                                               error("Fixup data addsy and subsy didn't have an appropriate type");
+                                       /*
+                                        *      This had better not be PC relative!
+                                        */
+                                       if (fixP->fx_pcrel)
+                                               error("Fixup data was erroneously \"pcrel\"");
+                                       /*
+                                        *      Subtract their values to get the
+                                        *      difference.
+                                        */
+                                       i = fixP->fx_addsy->sy_value -
+                                                       fixP->fx_subsy->sy_value;
+                                       /*
+                                        *      Now generate the fixup object records
+                                        *      Set the psect and store the data
+                                        */
+                                       VMS_Set_Psect(vsp->Psect_Index,
+                                                     fixP->fx_frag->fr_address +
+                                                       fixP->fx_where -
+                                                         vsp->Symbol->sy_value +
+                                                           vsp->Psect_Offset,
+                                                     OBJ$C_TIR);
+                                       VMS_Store_Immediate_Data(&i,
+                                                                fixP->fx_size,
+                                                                OBJ$C_TIR);
+                                       /*
+                                        *      Done
+                                        */
+                                       break;
+                               }
+                               /*
+                                *      Size will HAVE to be "long"
+                                */
+                               if (fixP->fx_size != sizeof(long))
+                                       error("Fixup datum was not a longword");
+                               /*
+                                *      Symbol must be "added" (if it is ever
+                                *                              subtracted we can
+                                *                              fix this assumption)
+                                */
+                               if (fixP->fx_addsy == 0)
+                                       error("Fixup datum was not \"fixP->fx_addsy\"");
+                               /*
+                                *      Store the symbol value in a PIC fashion
+                                */
+                               VMS_Store_PIC_Symbol_Reference(
+                                       fixP->fx_addsy,
+                                       fixP->fx_offset,
+                                       fixP->fx_pcrel,
+                                       vsp->Psect_Index,
+                                       fixP->fx_frag->fr_address +
+                                               fixP->fx_where -
+                                                 vsp->Symbol->sy_value +
+                                                    vsp->Psect_Offset,
+                                       OBJ$C_TIR);
+                               /*
+                                *      Done
+                                */
+                               break;
+                       }
+                       
+               }
+       }
+\f
+       /*
+        *      Write the Traceback Begin Module record
+        */
+       VMS_TBT_Module_Begin();
+       /*
+        *      Scan the symbols and write out the routines
+        *      (this makes the assumption that symbols are in
+        *       order of ascending text segment offset)
+        */
+       {
+          struct symbol *Current_Routine = 0;
+          int Current_Line_Number = 0;
+          int Current_Offset = -1;
+          struct input_file * Current_File;
+
+/* Output debugging info for global variables and static variables that are not
+ * specific to one routine. We also need to examine all stabs directives, to
+ * find the definitions to all of the advanced data types, and this is done by
+ * VMS_LSYM_Parse.  This needs to be done before any definitions are output to
+ * the object file, since there can be forward references in the stabs
+ * directives. When through with parsing, the text of the stabs directive
+ * is altered, with the definitions removed, so that later passes will see
+ * directives as they would be written if the type were already defined.
+ *
+ * We also look for files and include files, and make a list of them.  We
+ * examine the source file numbers to establish the actual lines that code was
+ * generated from, and then generate offsets.
+ */
+       VMS_LSYM_Parse();
+          for(symbolP = symbol_rootP; symbolP; symbolP = symbol_next(symbolP)) {
+               /*
+                *      Deal with STAB symbols
+                */
+               if ((symbolP->sy_nlist.n_type & N_STAB) != 0) {
+                 /*
+                  *    Dispatch on STAB type
+                  */
+                 switch((unsigned char)symbolP->sy_nlist.n_type) {
+                   case N_SLINE:
+                       if(symbolP->sy_nlist.n_desc > Current_File->max_line)
+                          Current_File->max_line = symbolP->sy_nlist.n_desc;
+                       if(symbolP->sy_nlist.n_desc < Current_File->min_line)
+                          Current_File->min_line = symbolP->sy_nlist.n_desc;
+                       break;                  
+                   case N_SO:
+                       Current_File =find_file(symbolP);
+                       Current_File->flag = 1;
+                       Current_File->min_line = 1;
+                               break;
+                   case N_SOL:
+                       Current_File = find_file(symbolP);
+                               break;
+                   case N_GSYM:
+                               VMS_GSYM_Parse(symbolP,Text_Psect);
+                               break;
+                   case N_LCSYM:
+                               VMS_LCSYM_Parse(symbolP,Text_Psect);
+                               break;
+                   case N_FUN:         /* For static constant symbols */
+                   case N_STSYM:
+                               VMS_STSYM_Parse(symbolP,Text_Psect);
+                               break;
+                 }
+               }
+          }
+
+       /* now we take a quick sweep through the files and assign offsets
+       to each one.  This will essentially be the starting line number to the
+       debugger for each file.  Output the info for the debugger to specify the
+       files, and then tell it how many lines to use */
+       {
+       int File_Number = 0;
+       int Debugger_Offset = 0;
+       int file_available;
+       Current_File = file_root;
+       for(Current_File = file_root; Current_File; Current_File = Current_File->next){
+         if(Current_File == (struct input_file*) NULL) break;
+         if(Current_File->max_line == 0) continue;
+         if((strncmp(Current_File->name,"GNU_GXX_INCLUDE:",16) == 0) &&
+               !flagseen['D']) continue;
+         if((strncmp(Current_File->name,"GNU_CC_INCLUDE:",15) == 0) &&
+               !flagseen['D']) continue;
+/* show a few extra lines at the start of the region selected */
+         if(Current_File->min_line > 2) Current_File->min_line -= 2;
+         Current_File->offset = Debugger_Offset - Current_File->min_line + 1;
+         Debugger_Offset += Current_File->max_line - Current_File->min_line + 1;
+         if(Current_File->same_file_fpnt != (struct input_file *) NULL)
+          Current_File->file_number =Current_File->same_file_fpnt->file_number;
+         else {
+           Current_File->file_number = ++File_Number;
+           file_available = VMS_TBT_Source_File(Current_File->name,
+               Current_File->file_number);
+           if(!file_available) {Current_File->file_number = 0;
+                               File_Number--;
+                               continue;};
+         };
+         VMS_TBT_Source_Lines(Current_File->file_number,
+                       Current_File->min_line,
+                       Current_File->max_line-Current_File->min_line+1);
+         }; /* for */
+       };      /* scope */
+       Current_File = (struct input_file*) NULL;
+
+          for(symbolP = symbol_rootP; symbolP; symbolP = symbol_next(symbolP)) {
+               /*
+                *      Deal with text symbols
+                */
+               if ((symbolP->sy_nlist.n_type & ~N_EXT) == N_TEXT) {
+                       /*
+                        *      Ignore symbols starting with "L",
+                        *      as they are local symbols
+                        */
+                       if (symbolP->sy_nlist.n_un.n_name[0] == 'L') continue;
+                       /*
+                        *      If there is a routine start defined,
+                        *      terminate it.
+                        */
+                       if (Current_Routine) {
+                               /*
+                                *      End the routine
+                                */
+                               VMS_TBT_Routine_End(text_siz,Current_Routine);
+                       }
+                       /*
+                        *      Store the routine begin traceback info
+                        */
+                       if(Text_Psect != -1) {
+                               VMS_TBT_Routine_Begin(symbolP,Text_Psect);
+                               Current_Routine = symbolP;
+                       }
+/* Output local symbols, i.e. all symbols that are associated with a specific
+ * routine.  We output them now so the debugger recognizes them as local to
+ * this routine.
+ */
+       { symbolS * symbolP1;
+         char* pnt;
+         char* pnt1;
+          for(symbolP1 = Current_Routine; symbolP1; symbolP1 = symbol_next(symbolP1)) {
+               if ((symbolP1->sy_nlist.n_type & N_STAB) == 0) continue;
+               if (symbolP1->sy_nlist.n_type != N_FUN) continue;
+               pnt=symbolP->sy_nlist.n_un.n_name;
+               pnt1=symbolP1->sy_nlist.n_un.n_name;
+               if(*pnt++ != '_') continue;
+               while(*pnt++ == *pnt1++) {};
+               if((*(--pnt) == '\0') && (*(--pnt1) == ':')) break;
+               };
+         if(symbolP1 != (symbolS *) NULL)
+               VMS_DBG_Define_Routine(symbolP1,Current_Routine,Text_Psect);
+       } /* local symbol block */
+                       /*
+                        *      Done
+                        */
+                       continue;
+               }
+               /*
+                *      Deal with STAB symbols
+                */
+               if ((symbolP->sy_nlist.n_type & N_STAB) != 0) {
+                 /*
+                  *    Dispatch on STAB type
+                  */
+                 switch((unsigned char)symbolP->sy_nlist.n_type) {
+                       /*
+                        *      Line number
+                        */
+                       case N_SLINE:
+                               /* Offset the line into the correct portion
+                                * of the file */
+                               if(Current_File->file_number == 0) break;
+                               /* Sometimes the same offset gets several source
+                                * lines assigned to it.
+                                * We should be selective about which lines
+                                * we allow, we should prefer lines that are
+                                * in the main source file when debugging
+                                * inline functions. */
+                               if((Current_File->file_number != 1) &&
+                                       symbolP->sy_nlist.n_value == 
+                                       Current_Offset) break;
+                               /* calculate actual debugger source line */
+                               symbolP->sy_nlist.n_desc 
+                                       += Current_File->offset;
+                               /*
+                                *      If this is the 1st N_SLINE, setup
+                                *      PC/Line correlation.  Otherwise
+                                *      do the delta PC/Line.  If the offset
+                                *      for the line number is not +ve we need
+                                *      to do another PC/Line correlation
+                                *      setup
+                                */
+                               if (Current_Offset == -1) {
+                                  VMS_TBT_Line_PC_Correlation(
+                                               symbolP->sy_nlist.n_desc,
+                                               symbolP->sy_nlist.n_value,
+                                               Text_Psect,
+                                               0);
+                               } else {
+                                  if ((symbolP->sy_nlist.n_desc -
+                                               Current_Line_Number) <= 0) {
+                                       /*
+                                        *      Line delta is not +ve, we
+                                        *      need to close the line and
+                                        *      start a new PC/Line
+                                        *      correlation.
+                                        */
+                                       VMS_TBT_Line_PC_Correlation(0,
+                                               symbolP->sy_nlist.n_value -
+                                                       Current_Offset,
+                                               0,
+                                               -1);
+                                       VMS_TBT_Line_PC_Correlation(
+                                               symbolP->sy_nlist.n_desc,
+                                               symbolP->sy_nlist.n_value,
+                                               Text_Psect,
+                                               0);
+                                  } else {
+                                       /*
+                                        *      Line delta is +ve, all is well
+                                        */
+                                       VMS_TBT_Line_PC_Correlation(
+                                               symbolP->sy_nlist.n_desc -
+                                                       Current_Line_Number,
+                                               symbolP->sy_nlist.n_value -
+                                                       Current_Offset,
+                                               0,
+                                               1);
+                                  }
+                               }
+                               /*
+                                *      Update the current line/PC
+                                */
+                               Current_Line_Number = symbolP->sy_nlist.n_desc;
+                               Current_Offset = symbolP->sy_nlist.n_value;
+                               /*
+                                *      Done
+                                */
+                               break;
+                       /*
+                        *      Source file
+                        */
+                       case N_SO:
+                               /*
+                                *      Remember that we had a source file
+                                *      and emit the source file debugger
+                                *      record
+                                */
+                               Current_File =
+                                   find_file(symbolP);
+                               break;
+/* We need to make sure that we are really in the actual source file when
+ * we compute the maximum line number.  Otherwise the debugger gets really
+ * confused */
+                       case N_SOL:
+                               Current_File =
+                                   find_file(symbolP);
+                               break;
+                 }
+               }
+          }
+          /*
+           *   If there is a routine start defined,
+           *   terminate it (and the line numbers)
+           */
+          if (Current_Routine) {
+               /*
+                *      Terminate the line numbers
+                */
+               VMS_TBT_Line_PC_Correlation(0,
+                                           text_siz - Current_Routine->sy_nlist.n_value,
+                                           0,
+                                           -1);
+               /*
+                *      Terminate the routine
+                */
+               VMS_TBT_Routine_End(text_siz,Current_Routine);
+          }
+       }
+       /*
+        *      Write the Traceback End Module TBT record
+        */
+       VMS_TBT_Module_End();
+\f
+       /*
+        *      Write the End Of Module record
+        */
+       if (Entry_Point_Symbol == 0)
+               Write_VMS_EOM_Record(-1,0);
+       else
+               Write_VMS_EOM_Record(Text_Psect,
+                                    Entry_Point_Symbol->sy_nlist.n_value);
+\f
+   /*
+    *  All done, close the object file
+    */
+   Close_VMS_Object_File();
+}
+
+\f
+       /****** VMS OBJECT FILE HACKING ROUTINES *******/
+
+
+/*
+ *     Global data (Object records limited to 512 bytes by VAX-11 "C" runtime)
+ */
+static int VMS_Object_File_FD;         /* File Descriptor for object file */
+static char Object_Record_Buffer[512]; /* Buffer for object file records  */
+static int Object_Record_Offset;       /* Offset to end of data           */
+static int Current_Object_Record_Type; /* Type of record in above         */
+
+/*
+ *     Macros for placing data into the object record buffer
+ */
+#define        PUT_LONG(val)   *((long *)(Object_Record_Buffer + \
+                                 Object_Record_Offset)) = val; \
+                       Object_Record_Offset += sizeof(long)
+
+#define        PUT_SHORT(val)  *((short *)(Object_Record_Buffer + \
+                                 Object_Record_Offset)) = val; \
+                       Object_Record_Offset += sizeof(short)
+
+#define        PUT_CHAR(val)   Object_Record_Buffer[Object_Record_Offset++] = val
+
+#define        PUT_COUNTED_STRING(cp) {\
+                       register char *p = cp; \
+                       PUT_CHAR(strlen(p)); \
+                       while(*p) PUT_CHAR(*p++);}
+
+/*
+ *     Macro for determining if a Name has psect attributes attached
+ *     to it.
+ */
+#define        PSECT_ATTRIBUTES_STRING         "$$PsectAttributes_"
+#define        PSECT_ATTRIBUTES_STRING_LENGTH  18
+
+#define        HAS_PSECT_ATTRIBUTES(Name) \
+               (strncmp((Name[0] == '_' ? Name + 1 : Name), \
+                PSECT_ATTRIBUTES_STRING, \
+                PSECT_ATTRIBUTES_STRING_LENGTH) == 0)
+
+\f
+/*
+ *     Create the VMS object file
+ */
+Create_VMS_Object_File()
+{
+#ifdef eunice
+       VMS_Object_File_FD = creat(out_file_name, 0777, "var");
+#else  eunice
+       VMS_Object_File_FD = creat(out_file_name, 0, "rfm=var");
+#endif eunice
+       /*
+        *      Deal with errors
+        */
+       if (VMS_Object_File_FD < 0) {
+               char Error_Line[256];
+
+               sprintf(Error_Line,"Couldn't create VMS object file \"%s\"",
+                               out_file_name);
+               error(Error_Line);
+       }
+       /*
+        *      Initialize object file hacking variables
+        */
+       Object_Record_Offset = 0;
+       Current_Object_Record_Type = -1;
+}
+
+\f
+/*
+ *     Declare a particular type of object file record
+ */
+Set_VMS_Object_File_Record(Type)
+int Type;
+{
+       /*
+        *      If the type matches, we are done
+        */
+       if (Type == Current_Object_Record_Type) return;
+       /*
+        *      Otherwise: flush the buffer
+        */
+       Flush_VMS_Object_Record_Buffer();
+       /*
+        *      Set the new type
+        */
+       Current_Object_Record_Type = Type;
+}
+
+\f
+/*
+ *     Flush the object record buffer to the object file
+ */
+Flush_VMS_Object_Record_Buffer()
+{
+       int i;
+
+       /*
+        *      If the buffer is empty, we are done
+        */
+       if (Object_Record_Offset == 0) return;
+       /*
+        *      Write the data to the file
+        */
+       i= write(VMS_Object_File_FD,
+                Object_Record_Buffer,
+                Object_Record_Offset);
+       if (i != Object_Record_Offset)
+               error("I/O error writing VMS object file");
+       /*
+        *      The buffer is now empty
+        */
+       Object_Record_Offset = 0;
+}
+
+\f
+/*
+ *     Close the VMS Object file
+ */
+Close_VMS_Object_File()
+{
+       close(VMS_Object_File_FD);
+}
+
+\f
+/*
+ *     Write the MHD (Module Header) records
+ */
+Write_VMS_MHD_Records()
+{
+       register char *cp,*cp1;
+       register int i;
+       struct {int Size; char *Ptr;} Descriptor;
+       char Module_Name[256];
+       char Now[17];
+
+       /*
+        *      We are writing a module header record
+        */
+       Set_VMS_Object_File_Record(OBJ$C_HDR);
+       /*
+        *      ***************************
+        *      *MAIN MODULE HEADER RECORD*
+        *      ***************************
+        *
+        *      Store record type and header type
+        */
+       PUT_CHAR(OBJ$C_HDR);
+       PUT_CHAR(MHD$C_MHD);
+       /*
+        *      Structure level is 0
+        */
+       PUT_CHAR(OBJ$C_STRLVL);
+       /*
+        *      Maximum record size is size of the object record buffer
+        */
+       PUT_SHORT(sizeof(Object_Record_Buffer));
+       /*
+        *      Get module name (the FILENAME part of the object file)
+        */
+       cp = out_file_name;
+       cp1 = Module_Name;
+       while(*cp) {
+               if ((*cp == ']') || (*cp == '>') ||
+                   (*cp == ':') || (*cp == '/')) {
+                       cp1 = Module_Name;
+                       cp++;
+                       continue;
+               }
+               *cp1++ = islower(*cp) ? toupper(*cp++) : *cp++;
+       }
+       *cp1 = 0;
+       /*
+        *      Limit it to 31 characters and store in the object record
+        */
+       while(--cp1 >= Module_Name)
+               if (*cp1 == '.') *cp1 = 0;
+       if (strlen(Module_Name) > 31) {
+               if(flagseen['+'])
+                       printf("%s: Module name truncated: %s\n", myname, Module_Name);
+               Module_Name[31] = 0;
+       }
+       PUT_COUNTED_STRING(Module_Name);
+       /*
+        *      Module Version is "V1.0"
+        */
+       PUT_COUNTED_STRING("V1.0");
+       /*
+        *      Creation time is "now" (17 chars of time string)
+        */
+       Descriptor.Size = 17;
+       Descriptor.Ptr = Now;
+       sys$asctim(0,&Descriptor,0,0);
+       for(i = 0; i < 17; i++) PUT_CHAR(Now[i]);
+       /*
+        *      Patch time is "never" (17 zeros)
+        */
+       for(i = 0; i < 17; i++) PUT_CHAR(0);
+       /*
+        *      Flush the record
+        */
+       Flush_VMS_Object_Record_Buffer();
+       /*
+        *      *************************
+        *      *LANGUAGE PROCESSOR NAME*
+        *      *************************
+        *
+        *      Store record type and header type
+        */
+       PUT_CHAR(OBJ$C_HDR);
+       PUT_CHAR(MHD$C_LNM);
+       /*
+        *      Store language processor name and version
+        *      (not a counted string!)
+        */
+       cp = compiler_version_string;
+       if (cp == 0) {
+               cp ="GNU AS  V";
+               while(*cp) PUT_CHAR(*cp++);
+               cp = strchr(&version_string,'.');               
+               while(*cp != ' ') cp--; cp++;
+               };
+       while(*cp >= 32) PUT_CHAR(*cp++);
+       /*
+        *      Flush the record
+        */
+       Flush_VMS_Object_Record_Buffer();
+}
+
+\f
+/*
+ *     Write the EOM (End Of Module) record
+ */
+Write_VMS_EOM_Record(Psect, Offset)
+int Psect;
+int Offset;
+{
+       /*
+        *      We are writing an end-of-module record
+        */
+       Set_VMS_Object_File_Record(OBJ$C_EOM);
+       /*
+        *      Store record Type
+        */
+       PUT_CHAR(OBJ$C_EOM);
+       /*
+        *      Store the error severity (0)
+        */
+       PUT_CHAR(0);
+       /*
+        *      Store the entry point, if it exists
+        */
+       if (Psect >= 0) {
+               /*
+                *      Store the entry point Psect
+                */
+               PUT_CHAR(Psect);
+               /*
+                *      Store the entry point Psect offset
+                */
+               PUT_LONG(Offset);
+       }
+       /*
+        *      Flush the record
+        */
+       Flush_VMS_Object_Record_Buffer();
+}
+
+\f
+/* this hash routine borrowed from GNU-EMACS, and strengthened slightly  ERY*/
+
+static int
+hash_string (ptr)
+     unsigned char *ptr;
+{
+  register unsigned char *p = ptr;
+  register unsigned char *end = p + strlen(ptr);
+  register unsigned char c;
+  register int hash = 0;
+
+  while (p != end)
+    {
+      c = *p++;
+      hash = ((hash<<3) + (hash<<15) + (hash>>28) + c);
+    }
+  return hash;
+}
+
+/*
+ *     Generate a Case-Hacked VMS symbol name (limited to 31 chars)
+ */
+VMS_Case_Hack_Symbol(In,Out)
+register char *In;
+register char *Out;
+{
+       long int init = 0;
+       long int result;
+       char *pnt;
+       char *new_name;
+       char *old_name;
+       register int i;
+       int destructor = 0;     /*hack to allow for case sens in a destructor*/
+       int truncate = 0;
+       int Case_Hack_Bits = 0;
+       int Saw_Dollar = 0;
+       static char Hex_Table[16] =
+        {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
+
+       /*
+        *      Kill any leading "_"
+        */
+       if (*In == '_') In++;
+
+       new_name=Out;   /* save this for later*/
+
+       if((In[0]=='_')&&(In[1]=='$')&&(In[2]=='_'))
+                                                destructor=1;
+
+       /* We may need to truncate the symbol, save the hash for later*/
+       if(strlen(In)>23)  result = hash_string(In);
+       /*
+        *      Is there a Psect Attribute to skip??
+        */
+       if (HAS_PSECT_ATTRIBUTES(In)) {
+               /*
+                *      Yes: Skip it
+                */
+               In += PSECT_ATTRIBUTES_STRING_LENGTH;
+               while(*In) {
+                       if ((In[0] == '$') && (In[1] == '$')) {
+                               In += 2;
+                               break;
+                       }
+                       In++;
+               }
+       }
+
+       old_name=In;
+/*     if(strlen(In) > 31 && flagseen['+'])
+               printf("%s: Symbol name truncated: %s\n",myname,In);*/
+       /*
+        *      Do the case conversion
+        */
+       i = 23;         /* Maximum of 23 chars */
+       while(*In && (--i >= 0)) {
+               Case_Hack_Bits <<= 1;
+               if (*In == '$') Saw_Dollar = 1;
+               if ((destructor==1)&&(i==21)) Saw_Dollar = 0;
+               if (isupper(*In)) {
+                       *Out++ = *In++;
+                       Case_Hack_Bits |= 1;
+               } else {
+                       *Out++ = islower(*In) ? toupper(*In++) : *In++;
+               }
+       }
+       /*
+        *      If we saw a dollar sign, we don't do case hacking
+        */
+       if(flagseen['h'] || Saw_Dollar)
+               Case_Hack_Bits = 0;
+
+       /*
+        *      If we have more than 23 characters and everything is lowercase
+        *      we can insert the full 31 characters
+        */
+       if (*In) {
+               /*
+                *      We  have more than 23 characters
+                * If we must add the case hack, then we have truncated the str
+                */
+               pnt=Out;
+               truncate=1;
+               if (Case_Hack_Bits == 0) {
+                       /*
+                        *      And so far they are all lower case:
+                        *              Check up to 8 more characters
+                        *              and ensure that they are lowercase
+                        */
+                       if(flagseen['h'])
+                               i=8;
+                       else
+                               for(i = 0; (In[i] != 0) && (i < 8); i++)
+                                       if (isupper(In[i]) && !Saw_Dollar)
+                                               break;
+                       if(In[i]==0)
+                               truncate=0;
+
+                       if ((i >= 8) || (In[i] == 0)) {
+                               /*
+                                *      They are:  Copy up to 31 characters
+                                *                      to the output string
+                                */
+                               i = 8;
+                               while((--i >= 0) && (*In))
+                                       *Out++ = islower(*In) ?
+                                                       toupper(*In++) :
+                                                       *In++;
+                       }
+               }
+       }
+       /*
+        *      If there were any uppercase characters in the name we
+        *      take on the case hacking string
+        */
+
+       /* Old behavior for regular GNU-C compiler */
+       if (!flagseen['+'])
+               truncate=0;
+       if ((Case_Hack_Bits != 0)||(truncate==1)) {
+               if(truncate==0) {
+                       *Out++ = '_';
+                       for(i = 0; i < 6; i++) {
+                               *Out++ = Hex_Table[Case_Hack_Bits & 0xf];
+                               Case_Hack_Bits >>= 4;
+                       }
+                       *Out++ = 'X';
+               } else {
+                       Out=pnt;        /*Cut back to 23 characters maximum */
+                       *Out++ = '_';
+                       for( i=0; i < 7; i++) {
+                               init = result & 0x01f;
+                               if (init < 10)
+                                       *Out++='0'+init;
+                               else
+                                       *Out++ = 'A'+init-10;   
+                               result = result >> 5;
+                       }
+               }
+       } /*Case Hack */
+       /*
+        *      Done
+        */
+       *Out = 0;
+       if( truncate==1 && flagseen['+'] && flagseen['H'])
+               printf("%s: Symbol %s replaced by %s\n",myname,old_name,new_name);
+}
+
+\f
+/*
+ *     Scan a symbol name for a psect attribute specification
+ */
+VMS_Modify_Psect_Attributes(Name, Attribute_Pointer)
+char *Name;
+int *Attribute_Pointer;
+{
+       register int i;
+       register char *cp;
+       int Negate;
+       static struct {
+               char *Name;
+               int   Value;
+               } Attributes[] = {
+               {"PIC",         GPS$M_PIC},
+               {"LIB",         GPS$M_LIB},
+               {"OVR",         GPS$M_OVR},
+               {"REL",         GPS$M_REL},
+               {"GBL",         GPS$M_GBL},
+               {"SHR",         GPS$M_SHR},
+               {"EXE",         GPS$M_EXE},
+               {"RD",          GPS$M_RD},
+               {"WRT",         GPS$M_WRT},
+               {"VEC",         GPS$M_VEC},
+               {0,             0}};
+
+       /*
+        *      Kill leading "_"
+        */
+       if (*Name == '_') Name++;
+       /*
+        *      Check for a PSECT attribute list
+        */
+       if (!HAS_PSECT_ATTRIBUTES(Name)) return;        /* If not, return */
+       /*
+        *      Skip the attribute list indicator
+        */
+       Name += PSECT_ATTRIBUTES_STRING_LENGTH;
+       /*
+        *      Process the attributes ("_" separated, "$" terminated)
+        */
+       while(*Name != '$') {
+               /*
+                *      Assume not negating
+                */
+               Negate = 0;
+               /*
+                *      Check for "NO"
+                */
+               if ((Name[0] == 'N') && (Name[1] == 'O')) {
+                       /*
+                        *      We are negating (and skip the NO)
+                        */
+                       Negate = 1;
+                       Name += 2;
+               }
+               /*
+                *      Find the token delimiter
+                */
+               cp = Name;
+               while(*cp && (*cp != '_') && (*cp != '$')) cp++;
+               /*
+                *      Look for the token in the attribute list
+                */
+               for(i = 0; Attributes[i].Name; i++) {
+                       /*
+                        *      If the strings match, set/clear the attr.
+                        */
+                       if (strncmp(Name, Attributes[i].Name, cp - Name) == 0) {
+                               /*
+                                *      Set or clear
+                                */
+                               if (Negate)
+                                       *Attribute_Pointer &=
+                                               ~Attributes[i].Value;
+                               else
+                                       *Attribute_Pointer |=
+                                                Attributes[i].Value;
+                               /*
+                                *      Done
+                                */
+                               break;
+                       }
+               }
+               /*
+                *      Now skip the attribute
+                */
+               Name = cp;
+               if (*Name == '_') Name++;
+       }
+       /*
+        *      Done
+        */
+       return;
+}
+
+\f
+/*
+ *     Define a psect
+ */
+VMS_Psect_Spec(Name, Size, Type)
+char *Name;
+int Size;
+char *Type;
+{
+       char Local[32];
+       int Psect_Attributes;
+
+       /*
+        *      We are writing a GSD record
+        */
+       Set_VMS_Object_File_Record(OBJ$C_GSD);
+       /*
+        *      If the buffer is empty we must insert the GSD record type
+        */
+       if (Object_Record_Offset == 0) PUT_CHAR(OBJ$C_GSD);
+       /*
+        *      We are writing a PSECT definition subrecord
+        */
+       PUT_CHAR(GSD$C_PSC);
+       /*
+        *      Psects are always LONGWORD aligned
+        */
+       PUT_CHAR(2);
+       /*
+        *      Generate the appropriate PSECT flags given the PSECT type
+        */
+       if (strcmp(Type,"COMMON") == 0) {
+               /*
+                *      Common block psects are:  PIC,OVR,REL,GBL,SHR,RD,WRT
+                */
+               Psect_Attributes = (GPS$M_PIC|GPS$M_OVR|GPS$M_REL|GPS$M_GBL|
+                                         GPS$M_SHR|GPS$M_RD|GPS$M_WRT);
+       } else if (strcmp(Type,"CONST") == 0) {
+               /*
+                *      Common block psects are:  PIC,OVR,REL,GBL,SHR,RD
+                */
+               Psect_Attributes = (GPS$M_PIC|GPS$M_OVR|GPS$M_REL|GPS$M_GBL|
+                                         GPS$M_SHR|GPS$M_RD);
+       } else if (strcmp(Type,"DATA") == 0) {
+               /*
+                *      The Data psects are PIC,REL,RD,WRT
+                */
+               Psect_Attributes =
+                               (GPS$M_PIC|GPS$M_REL|GPS$M_RD|GPS$M_WRT);
+       } else if (strcmp(Type,"TEXT") == 0) {
+               /*
+                *      The Text psects are PIC,REL,SHR,EXE,RD
+                */
+               Psect_Attributes =
+                               (GPS$M_PIC|GPS$M_REL|GPS$M_SHR|
+                                                         GPS$M_EXE|GPS$M_RD);
+       } else {
+               /*
+                *      Error: Unknown psect type
+                */
+               error("Unknown VMS psect type");
+       }
+       /*
+        *      Modify the psect attributes according to any attribute string
+        */
+       if (HAS_PSECT_ATTRIBUTES(Name))
+               VMS_Modify_Psect_Attributes(Name,&Psect_Attributes);
+       /*
+        *      Specify the psect attributes
+        */
+       PUT_SHORT(Psect_Attributes);
+       /*
+        *      Specify the allocation
+        */
+       PUT_LONG(Size);
+       /*
+        *      Finally, the psect name
+        */
+       VMS_Case_Hack_Symbol(Name,Local);
+       PUT_COUNTED_STRING(Local);
+       /*
+        *      Flush the buffer if it is more than 75% full
+        */
+       if (Object_Record_Offset >
+               (sizeof(Object_Record_Buffer)*3/4))
+                       Flush_VMS_Object_Record_Buffer();
+}
+
+\f
+/*
+ *     Define a global symbol
+ */
+VMS_Global_Symbol_Spec(Name, Psect_Number, Psect_Offset, Defined)
+char *Name;
+int Psect_Number;
+int Psect_Offset;
+{
+       char Local[32];
+
+       /*
+        *      We are writing a GSD record
+        */
+       Set_VMS_Object_File_Record(OBJ$C_GSD);
+       /*
+        *      If the buffer is empty we must insert the GSD record type
+        */
+       if (Object_Record_Offset == 0) PUT_CHAR(OBJ$C_GSD);
+       /*
+        *      We are writing a Global symbol definition subrecord
+        */
+       if (Psect_Number <= 255) {
+               PUT_CHAR(GSD$C_SYM);
+       } else {
+               PUT_CHAR(GSD$C_SYMW);
+       }
+       /*
+        *      Data type is undefined
+        */
+       PUT_CHAR(0);
+       /*
+        *      Switch on Definition/Reference
+        */
+       if (Defined) {
+               /*
+                *      Definition:
+                *      Flags = "RELOCATABLE" and "DEFINED"
+                */
+               PUT_SHORT(GSY$M_DEF|GSY$M_REL);
+               /*
+                *      Psect Number
+                */
+               if (Psect_Number <= 255) {
+                       PUT_CHAR(Psect_Number);
+               } else {
+                       PUT_SHORT(Psect_Number);
+               }
+               /*
+                *      Offset
+                */
+               PUT_LONG(Psect_Offset);
+       } else {
+               /*
+                *      Reference:
+                *      Flags = "RELOCATABLE"
+                */
+               PUT_SHORT(GSY$M_REL);
+       }
+       /*
+        *      Finally, the global symbol name
+        */
+       VMS_Case_Hack_Symbol(Name,Local);
+       PUT_COUNTED_STRING(Local);
+       /*
+        *      Flush the buffer if it is more than 75% full
+        */
+       if (Object_Record_Offset >
+               (sizeof(Object_Record_Buffer)*3/4))
+                       Flush_VMS_Object_Record_Buffer();
+}
+
+\f
+/*
+ *     Define a procedure entry pt/mask
+ */
+VMS_Procedure_Entry_Pt(Name, Psect_Number, Psect_Offset, Entry_Mask)
+char *Name;
+int Psect_Number;
+int Psect_Offset;
+int Entry_Mask;
+{
+       char Local[32];
+
+       /*
+        *      We are writing a GSD record
+        */
+       Set_VMS_Object_File_Record(OBJ$C_GSD);
+       /*
+        *      If the buffer is empty we must insert the GSD record type
+        */
+       if (Object_Record_Offset == 0) PUT_CHAR(OBJ$C_GSD);
+       /*
+        *      We are writing a Procedure Entry Pt/Mask subrecord
+        */
+       if (Psect_Number <= 255) {
+               PUT_CHAR(GSD$C_EPM);
+       } else {
+               PUT_CHAR(GSD$C_EPMW);
+       }
+       /*
+        *      Data type is undefined
+        */
+       PUT_CHAR(0);
+       /*
+        *      Flags = "RELOCATABLE" and "DEFINED"
+        */
+       PUT_SHORT(GSY$M_DEF|GSY$M_REL);
+       /*
+        *      Psect Number
+        */
+       if (Psect_Number <= 255) {
+               PUT_CHAR(Psect_Number);
+       } else {
+               PUT_SHORT(Psect_Number);
+       }
+       /*
+        *      Offset
+        */
+       PUT_LONG(Psect_Offset);
+       /*
+        *      Entry mask
+        */
+       PUT_SHORT(Entry_Mask);
+       /*
+        *      Finally, the global symbol name
+        */
+       VMS_Case_Hack_Symbol(Name,Local);
+       PUT_COUNTED_STRING(Local);
+       /*
+        *      Flush the buffer if it is more than 75% full
+        */
+       if (Object_Record_Offset >
+               (sizeof(Object_Record_Buffer)*3/4))
+                       Flush_VMS_Object_Record_Buffer();
+}
+
+\f
+/*
+ *     Set the current location counter to a particular Psect and Offset
+ */
+VMS_Set_Psect(Psect_Index, Offset, Record_Type)
+int Psect_Index;
+int Offset;
+int Record_Type;
+{
+       /*
+        *      We are writing a "Record_Type" record
+        */
+       Set_VMS_Object_File_Record(Record_Type);
+       /*
+        *      If the buffer is empty we must insert the record type
+        */
+       if (Object_Record_Offset == 0) PUT_CHAR(Record_Type);
+       /*
+        *      Stack the Psect base + Longword Offset
+        */
+       if (Psect_Index < 255) {
+               PUT_CHAR(TIR$C_STA_PL);
+               PUT_CHAR(Psect_Index);
+       } else {
+               PUT_CHAR(TIR$C_STA_WPL);
+               PUT_SHORT(Psect_Index);
+       }
+       PUT_LONG(Offset);
+       /*
+        *      Set relocation base
+        */
+       PUT_CHAR(TIR$C_CTL_SETRB);
+       /*
+        *      Flush the buffer if it is more than 75% full
+        */
+       if (Object_Record_Offset >
+               (sizeof(Object_Record_Buffer)*3/4))
+                       Flush_VMS_Object_Record_Buffer();
+}
+
+/*
+ *     Make a data reference
+ */
+VMS_Set_Data(Psect_Index, Offset, Record_Type,Force)
+int Psect_Index;
+int Offset;
+int Record_Type;
+int Force;
+{
+       /*
+        *      We are writing a "Record_Type" record
+        */
+       Set_VMS_Object_File_Record(Record_Type);
+       /*
+        *      If the buffer is empty we must insert the record type
+        */
+       if (Object_Record_Offset == 0) PUT_CHAR(Record_Type);
+       /*
+        *      Stack the Psect base + Longword Offset
+        */
+       if(Force==1){
+          if(Psect_Index>127){
+               PUT_CHAR(TIR$C_STA_WPL);
+               PUT_SHORT(Psect_Index);
+               PUT_LONG(Offset);}
+           else {
+               PUT_CHAR(TIR$C_STA_PL);
+               PUT_CHAR(Psect_Index);
+               PUT_LONG(Offset);}
+       } else {if(Offset>32767){
+               PUT_CHAR(TIR$C_STA_WPL);
+               PUT_SHORT(Psect_Index);
+               PUT_LONG(Offset);}
+           else if(Offset>127){
+               PUT_CHAR(TIR$C_STA_WPW);
+               PUT_SHORT(Psect_Index);
+               PUT_SHORT(Offset);}
+           else{
+               PUT_CHAR(TIR$C_STA_WPB);
+               PUT_SHORT(Psect_Index);
+               PUT_CHAR(Offset);};};
+       /*
+        *      Set relocation base
+        */
+       PUT_CHAR(TIR$C_STO_PIDR);
+       /*
+        *      Flush the buffer if it is more than 75% full
+        */
+       if (Object_Record_Offset >
+               (sizeof(Object_Record_Buffer)*3/4))
+                       Flush_VMS_Object_Record_Buffer();
+}
+
+/*
+ *     Make a debugger reference to a struct, union or enum.
+ */
+VMS_Store_Struct(int Struct_Index)
+{
+       /*
+        *      We are writing a "OBJ$C_DBG" record
+        */
+       Set_VMS_Object_File_Record(OBJ$C_DBG);
+       /*
+        *      If the buffer is empty we must insert the record type
+        */
+       if (Object_Record_Offset == 0) PUT_CHAR(OBJ$C_DBG);
+       PUT_CHAR(TIR$C_STA_UW);
+       PUT_SHORT(Struct_Index);
+       PUT_CHAR(TIR$C_CTL_STKDL);
+       PUT_CHAR(TIR$C_STO_L);
+       /*
+        *      Flush the buffer if it is more than 75% full
+        */
+       if (Object_Record_Offset >
+               (sizeof(Object_Record_Buffer)*3/4))
+                       Flush_VMS_Object_Record_Buffer();
+}
+
+/*
+ *     Make a debugger reference to partially define a struct, union or enum.
+ */
+VMS_Def_Struct(int Struct_Index)
+{
+       /*
+        *      We are writing a "OBJ$C_DBG" record
+        */
+       Set_VMS_Object_File_Record(OBJ$C_DBG);
+       /*
+        *      If the buffer is empty we must insert the record type
+        */
+       if (Object_Record_Offset == 0) PUT_CHAR(OBJ$C_DBG);
+       PUT_CHAR(TIR$C_STA_UW);
+       PUT_SHORT(Struct_Index);
+       PUT_CHAR(TIR$C_CTL_DFLOC);
+       /*
+        *      Flush the buffer if it is more than 75% full
+        */
+       if (Object_Record_Offset >
+               (sizeof(Object_Record_Buffer)*3/4))
+                       Flush_VMS_Object_Record_Buffer();
+}
+
+VMS_Set_Struct(int Struct_Index)
+{/* see previous functions for comments */
+       Set_VMS_Object_File_Record(OBJ$C_DBG);
+       if (Object_Record_Offset == 0) PUT_CHAR(OBJ$C_DBG);
+       PUT_CHAR(TIR$C_STA_UW);
+       PUT_SHORT(Struct_Index);
+       PUT_CHAR(TIR$C_CTL_STLOC);
+       if (Object_Record_Offset >
+               (sizeof(Object_Record_Buffer)*3/4))
+                       Flush_VMS_Object_Record_Buffer();
+}
+\f
+/*
+ *     Store immediate data in current Psect
+ */
+VMS_Store_Immediate_Data(Pointer, Size, Record_Type)
+register char *Pointer;
+int Size;
+int Record_Type;
+{
+       register int i;
+
+       /*
+        *      We are writing a "Record_Type" record
+        */
+       Set_VMS_Object_File_Record(Record_Type);
+       /*
+        *      We can only store 128 bytes at a time
+        */
+       while(Size > 0) {
+               /*
+                *      Store a maximum of 128 bytes
+                */
+               i = (Size > 128) ? 128 : Size;
+               Size -= i;
+               /*
+                *      If we cannot accommodate this record, flush the
+                *      buffer.
+                */
+               if ((Object_Record_Offset + i + 1) >=
+                                       sizeof(Object_Record_Buffer))
+                       Flush_VMS_Object_Record_Buffer();
+               /*
+                *      If the buffer is empty we must insert record type
+                */
+               if (Object_Record_Offset == 0) PUT_CHAR(Record_Type);
+               /*
+                *      Store the count
+                */
+               PUT_CHAR(-i & 0xff);
+               /*
+                *      Store the data
+                */
+               while(--i >= 0) PUT_CHAR(*Pointer++);
+               /*
+                *      Flush the buffer if it is more than 75% full
+                */
+               if (Object_Record_Offset >
+                       (sizeof(Object_Record_Buffer)*3/4))
+                               Flush_VMS_Object_Record_Buffer();
+       }
+}
+
+\f
+/*
+ *     Store repeated immediate data in current Psect
+ */
+VMS_Store_Repeated_Data(Repeat_Count,Pointer, Size, Record_Type)
+int Repeat_Count;
+register char *Pointer;
+int Size;
+int Record_Type;
+{
+
+       /*
+        *      Ignore zero bytes/words/longwords
+        */
+       if ((Size == sizeof(char)) && (*Pointer == 0)) return;
+       if ((Size == sizeof(short)) && (*(short *)Pointer == 0)) return;
+       if ((Size == sizeof(long)) && (*(long *)Pointer == 0)) return;
+       /*
+        *      If the data is too big for a TIR$C_STO_RIVB sub-record
+        *      then we do it manually
+        */
+       if (Size > 255) {
+               while(--Repeat_Count >= 0)
+                       VMS_Store_Immediate_Data(Pointer,Size,Record_Type);
+               return;
+       }
+       /*
+        *      We are writing a "Record_Type" record
+        */
+       Set_VMS_Object_File_Record(Record_Type);
+       /*
+        *      If the buffer is empty we must insert record type
+        */
+       if (Object_Record_Offset == 0) PUT_CHAR(Record_Type);
+       /*
+        *      Stack the repeat count
+        */
+       PUT_CHAR(TIR$C_STA_LW);
+       PUT_LONG(Repeat_Count);
+       /*
+        *      And now the command and its data
+        */
+       PUT_CHAR(TIR$C_STO_RIVB);
+       PUT_CHAR(Size);
+       while(--Size >= 0) PUT_CHAR(*Pointer++);
+       /*
+        *      Flush the buffer if it is more than 75% full
+        */
+       if (Object_Record_Offset >
+               (sizeof(Object_Record_Buffer)*3/4))
+                       Flush_VMS_Object_Record_Buffer();
+}
+
+\f
+/*
+ *     Store a Position Independent Reference
+ */
+VMS_Store_PIC_Symbol_Reference(Symbol, Offset, PC_Relative,
+                                       Psect, Psect_Offset, Record_Type)
+struct symbol *Symbol;
+int Offset;
+int PC_Relative;
+int Psect;
+int Psect_Offset;
+int Record_Type;
+{
+       register struct VMS_Symbol *vsp =
+               (struct VMS_Symbol *)(Symbol->sy_number);
+       char Local[32];
+
+       /*
+        *      We are writing a "Record_Type" record
+        */
+       Set_VMS_Object_File_Record(Record_Type);
+       /*
+        *      If the buffer is empty we must insert record type
+        */
+       if (Object_Record_Offset == 0) PUT_CHAR(Record_Type);
+       /*
+        *      Set to the appropriate offset in the Psect
+        */
+       if (PC_Relative) {
+               /*
+                *      For a Code reference we need to fix the operand
+                *      specifier as well (so back up 1 byte)
+                */
+               VMS_Set_Psect(Psect, Psect_Offset - 1, Record_Type);
+       } else {
+               /*
+                *      For a Data reference we just store HERE
+                */
+               VMS_Set_Psect(Psect, Psect_Offset, Record_Type);
+       }
+       /*
+        *      Make sure we are still generating a "Record Type" record
+        */
+       if (Object_Record_Offset == 0) PUT_CHAR(Record_Type);
+       /*
+        *      Dispatch on symbol type (so we can stack its value)
+        */
+       switch(Symbol->sy_nlist.n_type) {
+               /*
+                *      Global symbol
+                */
+#ifdef NOT_VAX_11_C_COMPATIBLE
+               case N_UNDF | N_EXT:
+               case N_DATA | N_EXT:
+#endif NOT_VAX_11_C_COMPATIBLE
+               case N_UNDF:
+               case N_TEXT | N_EXT:
+                       /*
+                        *      Get the symbol name (case hacked)
+                        */
+                       VMS_Case_Hack_Symbol(Symbol->sy_nlist.n_un.n_name,Local);
+                       /*
+                        *      Stack the global symbol value
+                        */
+                       PUT_CHAR(TIR$C_STA_GBL);
+                       PUT_COUNTED_STRING(Local);
+                       if (Offset) {
+                               /*
+                                *      Stack the longword offset
+                                */
+                               PUT_CHAR(TIR$C_STA_LW);
+                               PUT_LONG(Offset);
+                               /*
+                                *      Add the two, leaving the result on the stack
+                                */
+                               PUT_CHAR(TIR$C_OPR_ADD);
+                       }
+                       break;
+               /*
+                *      Uninitialized local data
+                */
+               case N_BSS:
+                       /*
+                        *      Stack the Psect (+offset)
+                        */
+                       if (vsp->Psect_Index < 255) {
+                               PUT_CHAR(TIR$C_STA_PL);
+                               PUT_CHAR(vsp->Psect_Index);
+                       } else {
+                               PUT_CHAR(TIR$C_STA_WPL);
+                               PUT_SHORT(vsp->Psect_Index);
+                       }
+                       PUT_LONG(vsp->Psect_Offset + Offset);
+                       break;
+               /*
+                *      Local text
+                */
+               case N_TEXT:
+                       /*
+                        *      Stack the Psect (+offset)
+                        */
+                       if (vsp->Psect_Index < 255) {
+                               PUT_CHAR(TIR$C_STA_PL);
+                               PUT_CHAR(vsp->Psect_Index);
+                       } else {
+                               PUT_CHAR(TIR$C_STA_WPL);
+                               PUT_SHORT(vsp->Psect_Index);
+                       }
+                       PUT_LONG(Symbol->sy_nlist.n_value);
+                       break;
+               /*
+                *      Initialized local or global data
+                */
+               case N_DATA:
+#ifndef        NOT_VAX_11_C_COMPATIBLE
+               case N_UNDF | N_EXT:
+               case N_DATA | N_EXT:
+#endif NOT_VAX_11_C_COMPATIBLE
+                       /*
+                        *      Stack the Psect (+offset)
+                        */
+                       if (vsp->Psect_Index < 255) {
+                               PUT_CHAR(TIR$C_STA_PL);
+                               PUT_CHAR(vsp->Psect_Index);
+                       } else {
+                               PUT_CHAR(TIR$C_STA_WPL);
+                               PUT_SHORT(vsp->Psect_Index);
+                       }
+                       PUT_LONG(vsp->Psect_Offset + Offset);
+                       break;
+       }
+       /*
+        *      Store either a code or data reference
+        */
+       PUT_CHAR(PC_Relative ? TIR$C_STO_PICR : TIR$C_STO_PIDR);
+       /*
+        *      Flush the buffer if it is more than 75% full
+        */
+       if (Object_Record_Offset >
+               (sizeof(Object_Record_Buffer)*3/4))
+                       Flush_VMS_Object_Record_Buffer();
+}
+
+\f
+/*
+ *     Check in the text area for an indirect pc-relative reference
+ *     and fix it up with addressing mode 0xff [PC indirect]
+ *
+ *     THIS SHOULD BE REPLACED BY THE USE OF TIR$C_STO_PIRR IN THE
+ *     PIC CODE GENERATING FIXUP ROUTINE.
+ */
+VMS_Fix_Indirect_Reference(Text_Psect, Offset, fragP, text_frag_root)
+int Text_Psect;
+int Offset;
+register fragS *fragP;
+struct frag *text_frag_root;
+{
+       /*
+        *      The addressing mode byte is 1 byte before the address
+        */
+       Offset--;
+       /*
+        *      Is it in THIS frag??
+        */
+       if ((Offset < fragP->fr_address) ||
+           (Offset >= (fragP->fr_address + fragP->fr_fix))) {
+               /*
+                *      We need to search for the fragment containing this
+                *      Offset
+                */
+               for(fragP = text_frag_root; fragP; fragP = fragP->fr_next) {
+                       if ((Offset >= fragP->fr_address) &&
+                           (Offset < (fragP->fr_address + fragP->fr_fix)))
+                               break;
+               }
+               /*
+                *      If we couldn't find the frag, things are BAD!!
+                */
+               if (fragP == 0)
+                       error("Couldn't find fixup fragment when checking for indirect reference");
+       }
+       /*
+        *      Check for indirect PC relative addressing mode
+        */
+       if (fragP->fr_literal[Offset - fragP->fr_address] == (char)0xff) {
+               static char Address_Mode = 0xff;
+
+               /*
+                *      Yes: Store the indirect mode back into the image
+                *           to fix up the damage done by STO_PICR
+                */
+               VMS_Set_Psect(Text_Psect,Offset,OBJ$C_TIR);
+               VMS_Store_Immediate_Data(&Address_Mode,1,OBJ$C_TIR);
+       }
+}
+
+\f
+/*
+ *     Write the Traceback Module Begin record
+ */
+VMS_TBT_Module_Begin()
+{
+       register char *cp,*cp1;
+       int Size;
+       char Module_Name[256];
+       char Local[256];
+
+       /*
+        *      Get module name (the FILENAME part of the object file)
+        */
+       cp = out_file_name;
+       cp1 = Module_Name;
+       while(*cp) {
+               if ((*cp == ']') || (*cp == '>') ||
+                   (*cp == ':') || (*cp == '/')) {
+                       cp1 = Module_Name;
+                       cp++;
+                       continue;
+               }
+               *cp1++ = islower(*cp) ? toupper(*cp++) : *cp++;
+       }
+       *cp1 = 0;
+       /*
+        *      Limit it to 31 characters
+        */
+       while(--cp1 >= Module_Name)
+               if (*cp1 == '.') *cp1 = 0;
+       if (strlen(Module_Name) > 31) {
+               if(flagseen['+'])
+                       printf("%s: Module name truncated: %s\n",myname, Module_Name);
+               Module_Name[31] = 0;
+       }
+       /*
+        *      Arrange to store the data locally (leave room for size byte)
+        */
+       cp = Local+1;
+       /*
+        *      Begin module
+        */
+       *cp++ = DST$C_MODBEG;
+       /*
+        *      Unused
+        */
+       *cp++ = 0;
+       /*
+        *      Language type == "C"
+        */
+       *(long *)cp = DST$C_C;
+       cp += sizeof(long);
+       /*
+        *      Store the module name
+        */
+       *cp++ = strlen(Module_Name);
+       cp1 = Module_Name;
+       while(*cp1) *cp++ = *cp1++;
+       /*
+        *      Now we can store the record size
+        */
+       Size = (cp - Local);
+       Local[0] = Size-1;
+       /*
+        *      Put it into the object record
+        */
+       VMS_Store_Immediate_Data(Local, Size, OBJ$C_TBT);
+}
+
+\f
+/*
+ *     Write the Traceback Module End record
+*/
+VMS_TBT_Module_End()
+{
+       char Local[2];
+
+       /*
+        *      End module
+        */
+       Local[0] = 1;
+       Local[1] = DST$C_MODEND;
+       /*
+        *      Put it into the object record
+        */
+       VMS_Store_Immediate_Data(Local, 2, OBJ$C_TBT);
+}
+
+\f
+/*
+ *     Write the Traceback Routine Begin record
+ */
+VMS_TBT_Routine_Begin(symbolP, Psect)
+struct symbol *symbolP;
+int Psect;
+{
+       register char *cp,*cp1;
+       char *Name;
+       int Offset;
+       int Size;
+       char Local[512];
+
+       /*
+        *      Strip the leading "_" from the name
+        */
+       Name = symbolP->sy_nlist.n_un.n_name;
+       if (*Name == '_') Name++;
+       /*
+        *      Get the text psect offset
+        */
+       Offset = symbolP->sy_nlist.n_value;
+       /*
+        *      Calculate the record size
+        */
+       Size = 1+1+4+1+strlen(Name);
+       /*
+        *      Record Size
+        */
+       Local[0] = Size;
+       /*
+        *      Begin Routine
+        */
+       Local[1] = DST$C_RTNBEG;
+       /*
+        *      Uses CallS/CallG
+        */
+       Local[2] = 0;
+       /*
+        *      Store the data so far
+        */
+       VMS_Store_Immediate_Data(Local, 3, OBJ$C_TBT);
+       /*
+        *      Make sure we are still generating a OBJ$C_TBT record
+        */
+       if (Object_Record_Offset == 0) PUT_CHAR(OBJ$C_TBT);
+       /*
+        *      Now get the symbol address
+        */
+       PUT_CHAR(TIR$C_STA_WPL);
+       PUT_SHORT(Psect);
+       PUT_LONG(Offset);
+       /*
+        *      Store the data reference
+        */
+       PUT_CHAR(TIR$C_STO_PIDR);
+       /*
+        *      Store the counted string as data
+        */
+       cp = Local;
+       cp1 = Name;
+       Size = strlen(cp1) + 1;
+       *cp++ = Size - 1;
+       while(*cp1) *cp++ = *cp1++;
+       VMS_Store_Immediate_Data(Local, Size, OBJ$C_TBT);
+}
+
+\f
+/*
+ *     Write the Traceback Routine End record
+ *     We *must* search the symbol table to find the next routine, since
+ *     the assember has a way of reassembling the symbol table OUT OF ORDER
+ *     Thus the next routine in the symbol list is not necessarily the 
+ *     next one in memory.  For debugging to work correctly we must know the
+ *     size of the routine.
+ */
+VMS_TBT_Routine_End(Max_Size,sp)
+int Max_Size;
+symbolS *sp;
+{
+       symbolS *symbolP;
+       int Size = 0x7fffffff;
+       char Local[16];
+
+
+       for(symbolP = symbol_rootP; symbolP; symbolP = symbol_next(symbolP)) {
+         if ((symbolP->sy_nlist.n_type & ~N_EXT) == N_TEXT) {
+           if (symbolP->sy_nlist.n_un.n_name[0] == 'L') continue;
+           if((symbolP->sy_nlist.n_value > sp->sy_nlist.n_value) &&
+               (symbolP->sy_nlist.n_value < Size ))
+               Size = symbolP->sy_nlist.n_value;
+       /* check if gcc_compiled. has size of zero */
+           if((symbolP->sy_nlist.n_value == sp->sy_nlist.n_value) &&
+               sp != symbolP &&
+               !strcmp(sp->sy_nlist.n_un.n_name,"gcc_compiled."))
+               Size = symbolP->sy_nlist.n_value;
+
+               };
+       };
+       if(Size == 0x7fffffff) Size = Max_Size;
+       Size -= sp->sy_nlist.n_value; /* and get the size of the routine */
+       /*
+        *      Record Size
+        */
+       Local[0] = 6;
+       /*
+        *      End of Routine
+        */
+       Local[1] = DST$C_RTNEND;
+       /*
+        *      Unused
+        */
+       Local[2] = 0;
+       /*
+        *      Size of routine
+        */
+       *((long *)(Local+3)) = Size;
+       /*
+        *      Store the record
+        */
+       VMS_Store_Immediate_Data(Local,7, OBJ$C_TBT);
+}
+/*
+ *     Write the Traceback Block End record
+ */
+VMS_TBT_Block_Begin(symbolP, Psect, Name)
+struct symbol *symbolP;
+int Psect;
+char* Name;
+{
+       register char *cp,*cp1;
+       int Offset;
+       int Size;
+       char Local[512];
+       /*
+        *      Begin block
+        */
+       Size = 1+1+4+1+strlen(Name);
+       /*
+        *      Record Size
+        */
+       Local[0] = Size;
+       /*
+        *      Begin Block - We simulate with a phony routine
+        */
+       Local[1] = DST$C_BLKBEG;
+       /*
+        *      Uses CallS/CallG
+        */
+       Local[2] = 0;
+       /*
+        *      Store the data so far
+        */
+       VMS_Store_Immediate_Data(Local, 3, OBJ$C_DBG);
+       /*
+        *      Make sure we are still generating a OBJ$C_DBG record
+        */
+       if (Object_Record_Offset == 0) PUT_CHAR(OBJ$C_DBG);
+       /*
+        *      Now get the symbol address
+        */
+       PUT_CHAR(TIR$C_STA_WPL);
+       PUT_SHORT(Psect);
+       /*
+        *      Get the text psect offset
+        */
+       Offset = symbolP->sy_nlist.n_value;
+       PUT_LONG(Offset);
+       /*
+        *      Store the data reference
+        */
+       PUT_CHAR(TIR$C_STO_PIDR);
+       /*
+        *      Store the counted string as data
+        */
+       cp = Local;
+       cp1 = Name;
+       Size = strlen(cp1) + 1;
+       *cp++ = Size - 1;
+       while(*cp1) *cp++ = *cp1++;
+       VMS_Store_Immediate_Data(Local, Size, OBJ$C_DBG);
+}
+
+\f
+/*
+ *     Write the Traceback Block End record
+ */
+VMS_TBT_Block_End(int Size)
+{
+       char Local[16];
+
+       /*
+        *      End block - simulate with a phony end routine
+        */
+       Local[0] = 6;
+       Local[1] = DST$C_BLKEND;
+       *((long *)(Local+3)) = Size;
+       /*
+        *      Unused
+        */
+       Local[2] = 0;
+       VMS_Store_Immediate_Data(Local,7, OBJ$C_DBG);
+}
+
+
+\f
+/*
+ *     Write a Line number / PC correlation record
+ */
+VMS_TBT_Line_PC_Correlation(Line_Number, Offset, Psect, Do_Delta)
+int Line_Number;
+int Offset;
+int Psect;
+int Do_Delta;
+{
+       register char *cp;
+       char Local[64];
+
+       /*
+*      If not delta, set our PC/Line number correlation
+*/
+       if (Do_Delta == 0) {
+               /*
+                *      Size
+                */
+               Local[0] = 1+1+2+1+4;
+               /*
+                *      Line Number/PC correlation
+                */
+               Local[1] = DST$C_LINE_NUM;
+               /*
+                *      Set Line number
+                */
+               Local[2] = DST$C_SET_LINE_NUM;
+               *((unsigned short *)(Local+3)) = Line_Number-1;
+               /*
+                *      Set PC
+                */
+               Local[5] = DST$C_SET_ABS_PC;
+               VMS_Store_Immediate_Data(Local, 6, OBJ$C_TBT);
+               /*
+                *      Make sure we are still generating a OBJ$C_TBT record
+                */
+               if (Object_Record_Offset == 0) PUT_CHAR(OBJ$C_TBT);
+               if (Psect < 255) {
+                       PUT_CHAR(TIR$C_STA_PL);
+                       PUT_CHAR(Psect);
+               } else {
+                       PUT_CHAR(TIR$C_STA_WPL);
+                       PUT_SHORT(Psect);
+               }
+               PUT_LONG(Offset);
+               PUT_CHAR(TIR$C_STO_PIDR);
+               /*
+                *      Do a PC offset of 0 to register the line number
+                */
+               Local[0] = 2;
+               Local[1] = DST$C_LINE_NUM;
+               Local[2] = 0;   /* Increment PC by 0 and register line # */
+               VMS_Store_Immediate_Data(Local, 3, OBJ$C_TBT);
+       } else {
+               /*
+                *      If Delta is negative, terminate the line numbers
+                */
+               if (Do_Delta < 0) {
+                       Local[0] = 1+1+4;
+                       Local[1] = DST$C_LINE_NUM;
+                       Local[2] = DST$C_TERM_L;
+                       *((long *)(Local+3)) = Offset;
+                       VMS_Store_Immediate_Data(Local, 7, OBJ$C_TBT);
+                       /*
+                        *      Done
+                        */
+                       return;
+               }
+               /*
+                *      Do a PC/Line delta
+                */
+               cp = Local+1;
+               *cp++ = DST$C_LINE_NUM;
+               if (Line_Number > 1) {
+                       /*
+                        *      We need to increment the line number
+                        */
+                       if (Line_Number-1 <= 255) {
+                               *cp++ = DST$C_INCR_LINUM;
+                               *cp++ = Line_Number-1;
+                       } else {
+                               *cp++ = DST$C_INCR_LINUM_W;
+                               *(short *)cp = Line_Number-1;
+                               cp += sizeof(short);
+                       }
+               }
+               /*
+                *      Increment the PC
+                */
+               if (Offset <= 128) {
+                       *cp++ = -Offset;
+               } else {
+                       if (Offset < 0x10000) {
+                               *cp++ = DST$C_DELTA_PC_W;
+                               *(short *)cp = Offset;
+                               cp += sizeof(short);
+                       } else {
+                               *cp++ = DST$C_DELTA_PC_L;
+                               *(long *)cp = Offset;
+                               cp += sizeof(long);
+                       }
+               }
+               Local[0] = cp - (Local+1);
+               VMS_Store_Immediate_Data(Local,cp - Local, OBJ$C_TBT);
+       }
+}
+
+\f
+/*
+ *     Describe a source file to the debugger
+ */
+VMS_TBT_Source_File(Filename, ID_Number)
+char *Filename;
+int ID_Number;
+{
+       register char *cp,*cp1;
+       int Status,i;
+       char Local[512];
+       static struct FAB Fab;
+       static struct NAM Nam;
+       static struct XABDAT Date_Xab;
+       static struct XABFHC File_Header_Xab;
+       char Es_String[255],Rs_String[255];
+
+       /*
+        *      Setup the Fab
+        */
+       Fab.fab$b_bid = FAB$C_BID;
+       Fab.fab$b_bln = sizeof(Fab);
+       Fab.fab$l_nam = (&Nam);
+       Fab.fab$l_xab = (struct XAB *)&Date_Xab;
+       /*
+        *      Setup the Nam block so we can find out the FULL name
+        *      of the source file.
+        */
+       Nam.nam$b_bid = NAM$C_BID;
+       Nam.nam$b_bln = sizeof(Nam);
+       Nam.nam$l_rsa = Rs_String;
+       Nam.nam$b_rss = sizeof(Rs_String);
+       Nam.nam$l_esa = Es_String;
+       Nam.nam$b_ess = sizeof(Es_String);
+       /*
+        *      Setup the Date and File Header Xabs
+        */
+       Date_Xab.xab$b_cod = XAB$C_DAT;
+       Date_Xab.xab$b_bln = sizeof(Date_Xab);
+       Date_Xab.xab$l_nxt = (char *)&File_Header_Xab;
+       File_Header_Xab.xab$b_cod = XAB$C_FHC;
+       File_Header_Xab.xab$b_bln = sizeof(File_Header_Xab);
+/* ((struct XAB *)&Date_Xab)->xab$b_cod = XAB$C_DAT;                           */
+/* ((struct XAB *)&Date_Xab)->xab$b_bln = sizeof(Date_Xab);                    */
+/* ((struct XAB *)&Date_Xab)->xab$l_nxt = (struct XAB *)&File_Header_Xab;      */
+/* ((struct XAB *)&File_Header_Xab)->xab$b_cod = XAB$C_FHC;                    */
+/* ((struct XAB *)&File_Header_Xab)->xab$b_bln = sizeof(File_Header_Xab);      */
+       /*
+        *      Get the file information
+        */
+       Fab.fab$l_fna = Filename;
+       Fab.fab$b_fns = strlen(Filename);
+       Status = sys$open(&Fab);
+       if (!(Status & 1)) {
+               printf("gas: Couldn't find source file \"%s\", Error = %%X%x\n",
+                               Filename, Status);
+               return(0);
+       }
+       sys$close(&Fab);
+       /*
+        *      Calculate the size of the resultant string
+        */
+       i = Nam.nam$b_rsl;
+       /*
+        *      Size of record
+        */
+       Local[0] = 1+1+1+1+1+2+8+4+2+1+1+i+1;
+       /*
+        *      Source declaration
+        */
+       Local[1] = DST$C_SOURCE;
+       /*
+        *      Make formfeeds count as source records
+        */
+       Local[2] = DST$C_SRC_FORMFEED;
+       /*
+        *      Declare source file
+        */
+       Local[3] = DST$C_SRC_DECLFILE;  
+       Local[4] = 1+2+8+4+2+1+1+i+1;
+       cp = Local+5;
+       /*
+        *      Flags
+        */
+       *cp++ = 0;
+       /*
+        *      File ID
+        */
+       *(short *)cp = ID_Number;
+       cp += sizeof(short);
+       /*
+        *      Creation Date
+        */
+       *(long *)cp = ((long *) &Date_Xab.xab$q_cdt)[0];
+       cp += sizeof(long);
+       *(long *)cp = ((long *) &Date_Xab.xab$q_cdt)[1];
+       cp += sizeof(long);
+       /*
+        *      End of file block
+        */
+       *(long *)cp = File_Header_Xab.xab$l_ebk;
+       cp += sizeof(long);
+       /*
+        *      First free byte
+        */
+       *(short *)cp = File_Header_Xab.xab$w_ffb;
+       cp += sizeof(short);
+       /*
+        *      Record format
+        */
+       *cp++ = File_Header_Xab.xab$b_rfo;
+       /*
+        *      Filename
+        */
+       *cp++ = i;
+       cp1 = Rs_String;
+       while(--i >= 0) *cp++ = *cp1++;
+       /*
+        *      Library module name (none)
+        */
+       *cp++ = 0;
+       /*
+        *      Done
+        */
+       VMS_Store_Immediate_Data(Local,cp - Local, OBJ$C_TBT);
+}
+
+\f
+/*
+ *     Give the number of source lines to the debugger
+ */
+VMS_TBT_Source_Lines(ID_Number,Starting_Line_Number,Number_Of_Lines)
+int ID_Number;
+int Starting_Line_Number;
+int Number_Of_Lines;
+{
+       char *cp,*cp1;
+       char Local[16];
+
+       /*
+        *      Size of record
+        */
+       Local[0] = 1+1+2+1+4+1+2;
+       /*
+        *      Source declaration
+        */
+       Local[1] = DST$C_SOURCE;
+       /*
+        *      Set Source File
+        */
+       cp = Local+2;
+       *cp++ = DST$C_SRC_SETFILE;
+       /*
+        *      File ID Number
+        */
+       *(short *)cp = ID_Number;
+       cp += sizeof(short);
+       /*
+        *      Set record number
+        */
+       *cp++ = DST$C_SRC_SETREC_L;
+       *(long *)cp = Starting_Line_Number;
+       cp += sizeof(long);
+       /*
+        *      Define lines
+        */
+       *cp++ = DST$C_SRC_DEFLINES_W;
+       *(short *)cp = Number_Of_Lines;
+       cp += sizeof(short);
+       /*
+        *      Done
+        */
+       VMS_Store_Immediate_Data(Local, cp-Local, OBJ$C_TBT);
+}
+
+\f
+/*
+ *     Given the pointer to a symbol we calculate how big the data at the
+ *     symbol is.  We do this by looking for the next symbol (local or
+ *     global) which will indicate the start of another datum.
+ */
+int VMS_Initialized_Data_Size(sp, End_Of_Data)
+register struct symbol *sp;
+int End_Of_Data;
+{
+       register struct symbol *sp1,*Next_Symbol;
+
+       /*
+        *      Find the next symbol
+        *      it delimits this datum
+        */
+       Next_Symbol = 0;
+       for (sp1 = symbol_rootP; sp1; sp1 = symbol_next(sp1)) {
+               /*
+                *      The data type must match
+                */
+               if ((sp1->sy_nlist.n_type & ~N_EXT) != N_DATA) continue;
+               /*
+                *      The symbol must be AFTER this symbol
+                */
+               if (sp1->sy_nlist.n_value <= sp->sy_nlist.n_value) continue;
+               /*
+                *      We ignore THIS symbol
+                */
+               if (sp1 == sp) continue;
+               /*
+                *      If there is already a candidate selected for the
+                *      next symbol, see if we are a better candidate
+                */
+               if (Next_Symbol) {
+                       /*
+                        *      We are a better candidate if we are "closer"
+                        *      to the symbol
+                        */
+                       if (sp1->sy_nlist.n_value >
+                                       Next_Symbol->sy_nlist.n_value)
+                               continue;
+                       /*
+                        *      Win:  Make this the candidate
+                        */
+                       Next_Symbol = sp1;
+               } else {
+                       /*
+                        *      This is the 1st candidate
+                        */
+                       Next_Symbol = sp1;
+               }
+       }
+       /*
+        *      Calculate its size
+        */
+       return(Next_Symbol ?
+               (Next_Symbol->sy_nlist.n_value -
+                               sp->sy_nlist.n_value) :
+               (End_Of_Data - sp->sy_nlist.n_value));
+}
+
+\f
+
+/* this routine locates a file in the list of files.  If an entry does not
+ * exist, one is created.  For include files, a new entry is always created
+ * such that inline functions can be properly debugged */
+struct input_file *
+find_file(sp)
+symbolS * sp;
+{
+       struct input_file * same_file;
+       struct input_file * fpnt;
+       same_file = (struct input_file*) NULL;
+       for(fpnt = file_root; fpnt; fpnt = fpnt->next){
+         if(fpnt == (struct input_file*) NULL) break;
+         if(fpnt->spnt == sp) return fpnt;
+       };
+       for(fpnt = file_root; fpnt; fpnt = fpnt->next){
+         if(fpnt == (struct input_file*) NULL) break;
+         if (strcmp(sp->sy_nlist.n_un.n_name,fpnt->name) == 0){
+               if(fpnt->flag == 1)return fpnt;
+               same_file = fpnt;
+               break;
+               };
+       };
+       fpnt = (struct input_file*) malloc(sizeof(struct input_file));
+       if(file_root == (struct input_file*) NULL) file_root = fpnt;
+       else {
+               struct input_file * fpnt1;
+               for(fpnt1 = file_root; fpnt1->next; fpnt1 = fpnt1->next);
+               fpnt1->next = fpnt;
+       };
+       fpnt->next = (struct input_file*) NULL;
+       fpnt->name = sp->sy_nlist.n_un.n_name;
+       fpnt->min_line = 0x7fffffff;
+       fpnt->max_line = 0;
+       fpnt->offset = 0;
+       fpnt->flag = 0;
+       fpnt->file_number = 0;
+       fpnt->spnt = sp;
+       fpnt->same_file_fpnt = same_file;
+       return fpnt;
+}
+
+\f
+/*
+ *     This is a hacked _doprnt() for VAX-11 "C".  It understands that
+ *     it is ONLY called by as_fatal(Format, Args) with a pointer to the
+ *     "Args" argument.  From this we can make it all work right!
+ */
+#ifndef        eunice
+_doprnt(Format, a, f)
+char *Format;
+FILE *f;
+char **a;
+{
+       int Nargs = ((int *)a)[-2];     /* This understands as_fatal() */
+
+       switch(Nargs) {
+               default: fprintf(f,"_doprnt error on \"%s\"!!",Format); break;
+               case 1:  fprintf(f,Format); break;
+               case 2:  fprintf(f,Format,a[0]); break;
+               case 3:  fprintf(f,Format,a[0],a[1]); break;
+               case 4:  fprintf(f,Format,a[0],a[1],a[2]); break;
+               case 5:  fprintf(f,Format,a[0],a[1],a[2],a[3]); break;
+               case 6:  fprintf(f,Format,a[0],a[1],a[2],a[3],a[4]); break;
+               case 7:  fprintf(f,Format,a[0],a[1],a[2],a[3],a[4],a[5]); break;
+               case 8:  fprintf(f,Format,a[0],a[1],a[2],a[3],a[4],a[5],a[6]); break;
+               case 9:  fprintf(f,Format,a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7]); break;
+               case 10: fprintf(f,Format,a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8]); break;
+       }
+}
+
+#endif /* eunice */
+
+#endif /* VMS */
+
+char const_flag = 0;
+void s_const();
+
+void
+s_const()
+{
+       register int temp;
+
+       temp = get_absolute_expression ();
+       subseg_new (SEG_DATA, (subsegT)temp);
+       const_flag = 1;
+       demand_empty_rest_of_line();
+}
+
+obj_crawl_symbol_chain() {
+  /* JF deal with forward references first. . . */
+  for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next(symbolP)) {
+       if (symbolP->sy_forward) {
+               symbolP->sy_value += symbolP->sy_forward->sy_value + symbolP->sy_forward->sy_frag->fr_address;
+#ifdef OBJ_COFF
+               if(SF_GET_GET_SEGMENT(symbolP) &&
+                  S_GET_SEGMENT(symbolP) == SEG_UNKNOWN)
+                   S_SET_SEGMENT(symbolP, S_GET_SEGMENT(symbolP->sy_forward));
+#endif /* OBJ_COFF */
+               symbolP->sy_forward=0;
+       } /* if it has a forward reference */
+  } /* walk the symbol chain */
+
+  { /* crawl symbol table */
+         register int symbol_number = 0;
+         
+#if defined(OBJ_COFF)
+         { /* OBJ_COFF version */
+                 lineno* lineP;
+                 symbolS* symbol_externP = (symbolS*)0;
+                 symbolS* symbol_extern_lastP = (symbolS*)0;
+                 
+                 /* The symbol list should be ordered according to the following sequence
+                  * order :
+                  * . .file symbol
+                  * . debug entries for functions
+                  * . fake symbols for .text .data and .bss
+                  * . defined symbols
+                  * . undefined symbols
+                  * But this is not mandatory. The only important point is to put the
+                  * undefined symbols at the end of the list.
+                  */
+                 
+                 if (symbol_rootP == NULL
+                     || S_GET_STORAGE_CLASS(symbol_rootP) != C_FILE) {
+                         c_dot_file_symbol("fake");
+                 } /* Is there a .file symbol ? If not insert one at the beginning. */
+                 
+                 /*
+                  * Build up static symbols for .text, .data and .bss
+                  */
+                 dot_text_symbol = (symbolS*)
+                     c_section_symbol(".text",
+                                      0,
+                                      H_GET_TEXT_SIZE(&headers),
+                                      0/*text_relocation_number*/,
+                                      0/*text_lineno_number*/);
+
+                 dot_data_symbol = (symbolS*)
+                     c_section_symbol(".data",
+                                      H_GET_TEXT_SIZE(&headers),
+                                      H_GET_DATA_SIZE(&headers),
+                                      0/*data_relocation_number*/,
+                                      0); /* There are no data lineno
+                                             entries */
+
+                 dot_bss_symbol = (symbolS*)
+                     c_section_symbol(".bss",
+                                      H_GET_TEXT_SIZE(&headers) + H_GET_DATA_SIZE(&headers),
+                                      H_GET_BSS_SIZE(&headers),
+                                      0, /* No relocation for a bss section. */
+                                      0); /* There are no bss lineno entries */
+                 
+ /* FIXME late night before delivery, I don't know why the chain is
+    broken, but I can guess.  So! Let's force them to be knit properly
+    at this point. */
+
+/* as john pointed out, this wasn't right.  Instead, we'll check here to
+   make sure that the list is doubly linked. */
+
+#if defined(DEBUG) && defined(SYMBOLS_NEED_BACKPOINTERS)
+                 for (symbolP = symbol_rootP; symbol_next(symbolP); symbolP = symbol_next(symbolP)) {
+                         know(symbolP->sy_next->sy_previous == symbolP);
+                 } /* walk the symbol chain */
+#endif /* DEBUG and SYMBOLS_NEED_BACKPOINTERS */
+                 symbolP = symbol_rootP;
+                 
+                 if (symbolP) {
+                         while(symbolP) {
+                                 /* If the symbol has a tagndx entry, resolve it */
+                                 if(SF_GET_TAGGED(symbolP)) {
+                                         SA_SET_SYM_TAGNDX(symbolP,
+                                                           ((symbolS*)SA_GET_SYM_TAGNDX(symbolP))->sy_number);
+                                 }
+                                 /* Debug symbol do not need all this rubbish */
+                                 if(!SF_GET_DEBUG(symbolP)) {
+                                         symbolS* real_symbolP;
+                                         /* L* and C_EFCN symbols never merge. */
+                                         if(!SF_GET_LOCAL(symbolP) &&
+                                            (real_symbolP =
+                                             symbol_find_base(S_GET_NAME(symbolP), DO_NOT_STRIP)) &&
+                                            real_symbolP != symbolP) {
+ /* FIXME where do dups come from?  xoxorich. */
+                                                 /* Move the debug data from the debug symbol to the
+                                                    real symbol. Do NOT do the oposite (i.e. move from
+                                                    real symbol to symbol and remove real symbol from the
+                                                    list.) Because some pointers refer to the real symbol
+                                                    whereas no pointers refer to the symbol. */
+                                                 c_symbol_merge(symbolP, real_symbolP);
+                                                 /* Replace the current symbol by the real one */
+                                                 /* The symbols will never be the last or the first
+                                                    because : 1st symbol is .file and 3 last symbols are
+                                                    .text, .data, .bss */
+                                                 symbol_remove(real_symbolP, &symbol_rootP, &symbol_lastP);
+                                                 symbol_insert(real_symbolP, symbolP, &symbol_rootP, &symbol_lastP);
+                                                 symbol_remove(symbolP, &symbol_rootP, &symbol_lastP);
+                                                 symbolP = real_symbolP;
+                                         }
+                                         if(flagseen['R'] && S_IS_DATA(symbolP))
+                                             S_SET_TEXT(symbolP);
+                                         
+                                         symbolP->sy_value += symbolP->sy_frag->fr_address;
+                                         
+                                         if(!S_IS_DEFINED(symbolP))
+                                             S_SET_EXTERNAL(symbolP);
+                                         else if(S_GET_STORAGE_CLASS(symbolP) == C_NULL)
+                                             S_SET_STORAGE_CLASS(symbolP, C_STAT);
+                                         
+                                         /* Mainly to speed up if not -g */
+                                         if(SF_GET_PROCESS(symbolP)) {
+                                                 /* Handle the nested blocks auxiliary info. */
+                                                 if(S_GET_STORAGE_CLASS(symbolP) == C_BLOCK) {
+                                                         if(!strcmp(S_GET_NAME(symbolP), ".bb"))
+                                                             stack_push(block_stack, (char *) &symbolP);
+                                                         else { /* .eb */
+                                                                 register symbolS* begin_symbolP;
+                                                                 begin_symbolP = *(symbolS**)stack_pop(block_stack);
+                                                                 if(begin_symbolP == (symbolS*)0)
+                                                                     as_warn("mismatched .eb");
+                                                                 else
+                                                                     SA_SET_SYM_ENDNDX(begin_symbolP, symbol_number);
+                                                         }
+                                                 }
+                                                 /* If we are able to identify the type of a function, and we
+                                                    are out of a function (last_functionP == 0) then, the
+                                                    function symbol will be associated with an auxiliary
+                                                    entry. */
+                                                 if(last_functionP == (symbolS*)0 &&
+                                                    SF_GET_FUNCTION(symbolP)) {
+                                                         last_functionP = symbolP;
+                                                         S_SET_NUMBER_AUXILIARY(symbolP, 1);
+                                                         /* Clobber possible stale .dim information. */
+                                                         memset(&symbolP->sy_auxent[0], '\0', sizeof(union auxent));
+                                                 }
+                                                 /* The C_FCN doesn't need any additional information.
+                                                    I don't even know if this is needed for sdb. But the
+                                                    standard assembler generates it, so...
+                                                    */
+                                                 if(S_GET_STORAGE_CLASS(symbolP) == C_EFCN) {
+                                                         if(last_functionP == (symbolS*)0)
+                                                             as_fatal("C_EFCN symbol out of scope");
+                                                         SA_SET_SYM_FSIZE(last_functionP,
+                                                                          (long)(symbolP->sy_value -
+                                                                                 last_functionP->sy_value));
+                                                         SA_SET_SYM_ENDNDX(last_functionP, symbol_number);
+                                                         last_functionP = (symbolS*)0;
+                                                 }
+                                         }
+                                 } else {
+                                         /* First descriptor of a structure must point to the next
+                                            slot outside the structure description. */
+                                         if(SF_GET_TAG(symbolP))
+                                             last_tagP = symbolP;
+                                         else if(S_GET_STORAGE_CLASS(symbolP) == C_EOS)
+                                             /* +2 take in account the current symbol */
+                                             SA_SET_SYM_ENDNDX(last_tagP, symbol_number+2);
+                                 }
+                                 
+                                 /* We must put the external symbols apart. The loader
+                                    does not bomb if we do not. But the references in
+                                    the endndx field for a .bb symbol are not corrected
+                                    if an external symbol is removed between .bb and .be.
+                                    I.e in the following case :
+                                    [20] .bb endndx = 22
+                                    [21] foo external
+                                    [22] .be
+                                    ld will move the symbol 21 to the end of the list but
+                                    endndx will still be 22 instead of 21. */
+                                 {
+                                         register symbolS* thisP = symbolP;
+                                         
+                                         symbolP = symbol_next(thisP);
+                                         /* remove C_EFCN and LOCAL (L...) symbols */
+                                         if (SF_GET_LOCAL(thisP)) {
+                                                 symbol_remove(thisP, &symbol_rootP, &symbol_lastP);
+                                         } else {
+                                                 if(S_GET_STORAGE_CLASS(thisP) == C_EXT &&
+                                                    !SF_GET_FUNCTION(thisP)) {
+                                                         /* Remove from the list */
+                                                         symbol_remove(thisP, &symbol_rootP, &symbol_lastP);
+                                                         symbol_clear_list_pointers(thisP);
+                                                         /* Move at the end of the list */
+                                                         if (symbol_extern_lastP == (symbolS*)0)
+                                                             symbol_externP = thisP;
+                                                         else
+                                                             symbol_append(thisP, symbol_extern_lastP);
+                                                         symbol_extern_lastP = thisP;
+                                                 } else {
+                                                         if(SF_GET_STRING(thisP)) {
+                                                                 thisP->sy_name_offset = string_byte_count;
+                                                                 string_byte_count += strlen(S_GET_NAME(thisP)) + 1;
+                                                         } else
+                                                             thisP->sy_name_offset = 0;
+                                                         thisP->sy_number = symbol_number;
+                                                         symbol_number += 1 + S_GET_NUMBER_AUXILIARY(thisP);
+                                                 }
+                                         }
+                                 }
+                         }
+                         
+                         /* this actually appends the entire extern chain */
+                         symbol_append(symbol_externP, symbol_lastP);
+                         symbolP = symbol_externP;
+                         while(symbolP) {
+                                 if(SF_GET_STRING(symbolP)) {
+                                         symbolP->sy_name_offset = string_byte_count;
+                                         string_byte_count += strlen(S_GET_NAME(symbolP)) + 1;
+                                 } else
+                                     symbolP->sy_name_offset = 0;
+                                 symbolP->sy_number = symbol_number;
+                                 symbol_number += 1 + S_GET_NUMBER_AUXILIARY(symbolP);
+                                 symbolP = symbol_next(symbolP);
+                         }
+                 }
+                 
+ /* FIXME I'm counting line no's here so we know what to put in the section
+    headers, and I'm resolving the addresses since I'm not sure how to
+    do it later. I am NOT resolving the linno's representing functions.
+    Their symbols need a fileptr pointing to this linno when emitted.
+    Thus, I resolve them on emit.  xoxorich. */
+
+                 for (lineP = lineno_rootP; lineP; lineP = lineP->next) {
+                         if (lineP->line.l_lnno) {
+                                 lineP->line.l_addr.l_paddr += ((fragS*)lineP->frag)->fr_address;
+                         } else {
+                                 ;
+                         }
+                         text_lineno_number++;
+                 } /* for each line number */
+         } /* OBJ_COFF version */
+#elif defined(OBJ_AOUT) | defined(OBJ_BOUT)
+         { /* OBJ_AOUT version */
+                 symbolPP = & symbol_rootP;    /* -> last symbol chain link. */
+                 while ((symbolP  = *symbolPP) != NULL)
+                     {
+                             if (flagseen['R'] && S_IS_DATA(symbolP)) {
+                                     S_SET_TEXT(symbolP);
+                             } /* if pusing data into text */
+                             
+                             symbolP -> sy_value += symbolP -> sy_frag -> fr_address;
+                             
+                             /* OK, here is how we decide which symbols go out into the
+                                brave new symtab.  Symbols that do are:
+                                
+                                * symbols with no name (stabd's?)
+                                * symbols with debug info in their N_TYPE
+                                
+                                Symbols that don't are:
+                                * symbols that are registers
+                                * symbols with \1 as their 3rd character (numeric labels)
+                                * "local labels" as defined by S_LOCAL_NAME(name)
+                                if the -L switch was passed to gas.
+                                
+                                All other symbols are output.  We complain if a deleted
+                                symbol was marked external.  */
+                             
+                             
+                             if (1
+                                 && !S_IS_REGISTER(symbolP)
+#ifndef        VMS     /* Under VMS we need to keep local symbols */
+                                 && ( !S_GET_NAME(symbolP)
+                                     || S_IS_DEBUG(symbolP)
+#ifdef TC_I960
+                                     /* FIXME this ifdef seems highly dubious to me.  xoxorich. */
+                                     || !S_IS_DEFINED(symbolP)
+                                     || S_IS_EXTERNAL(symbolP)
+#endif /* TC_I960 */
+                                     || (S_GET_NAME(symbolP)[0] != '\001' && (flagseen ['L'] || ! S_LOCAL_NAME(symbolP))))
+#endif /* not VMS */
+                                 )
+                                 {
+#ifndef        VMS
+                                         symbolP->sy_number = symbol_number++;
+                                         
+                                         /* The + 1 after strlen account for the \0 at the
+                                            end of each string */
+                                         if (!S_IS_STABD(symbolP)) {
+                                                 /* Ordinary case. */
+                                                 symbolP->sy_name_offset = string_byte_count;
+                                                 string_byte_count += strlen(S_GET_NAME(symbolP)) + 1;
+                                         }
+                                         else  /* .Stabd case. */
+#endif /* not VMS */
+                                             symbolP->sy_name_offset = 0;
+                                         symbolPP = &(symbol_next(symbolP));
+                                 } else {
+                                         if (S_IS_EXTERNAL(symbolP) || !S_IS_DEFINED(symbolP)) {
+                                                 as_bad ("Local symbol %s never defined", name);
+                                         } /* oops. */
+                                         
+#ifndef VMS
+                                         /* Unhook it from the chain */
+                                         *symbolPP = symbol_next(symbolP);
+#endif /* VMS */
+                                 } /* if this symbol should be in the output */
+                     } /* for each symbol */
+         } /* OBJ_AOUT version */
+#else
+         cant_crawl_symbol_table();
+#endif
+         H_SET_STRING_SIZE(&headers,string_byte_count);
+         H_SET_SYMBOL_TABLE_SIZE(&headers, symbol_number);
+  } /* crawl symbol table */
+
+  /* JF deal with forward references first. . . */
+  for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next(symbolP)) {
+       if (symbolP->sy_forward) {
+               symbolP->sy_value += symbolP->sy_forward->sy_value + symbolP->sy_forward->sy_frag->fr_address;
+#ifdef OBJ_COFF
+               if(SF_GET_GET_SEGMENT(symbolP) &&
+                  S_GET_SEGMENT(symbolP) == SEG_UNKNOWN)
+                   S_SET_SEGMENT(symbolP, S_GET_SEGMENT(symbolP->sy_forward));
+#endif /* OBJ_COFF */
+               symbolP->sy_forward=0;
+       } /* if it has a forward reference */
+  } /* walk the symbol chain */
+
+  { /* crawl symbol table */
+         register int symbol_number = 0;
+         
+#if defined(OBJ_COFF)
+         { /* OBJ_COFF version */
+                 lineno* lineP;
+                 symbolS* symbol_externP = (symbolS*)0;
+                 symbolS* symbol_extern_lastP = (symbolS*)0;
+                 
+                 /* The symbol list should be ordered according to the following sequence
+                  * order :
+                  * . .file symbol
+                  * . debug entries for functions
+                  * . fake symbols for .text .data and .bss
+                  * . defined symbols
+                  * . undefined symbols
+                  * But this is not mandatory. The only important point is to put the
+                  * undefined symbols at the end of the list.
+                  */
+                 
+                 if (symbol_rootP == NULL
+                     || S_GET_STORAGE_CLASS(symbol_rootP) != C_FILE) {
+                         c_dot_file_symbol("fake");
+                 } /* Is there a .file symbol ? If not insert one at the beginning. */
+                 
+                 /*
+                  * Build up static symbols for .text, .data and .bss
+                  */
+                 dot_text_symbol = (symbolS*)
+                     c_section_symbol(".text",
+                                      0,
+                                      H_GET_TEXT_SIZE(&headers),
+                                      0/*text_relocation_number*/,
+                                      0/*text_lineno_number*/);
+
+                 dot_data_symbol = (symbolS*)
+                     c_section_symbol(".data",
+                                      H_GET_TEXT_SIZE(&headers),
+                                      H_GET_DATA_SIZE(&headers),
+                                      0/*data_relocation_number*/,
+                                      0); /* There are no data lineno
+                                             entries */
+
+                 dot_bss_symbol = (symbolS*)
+                     c_section_symbol(".bss",
+                                      H_GET_TEXT_SIZE(&headers) + H_GET_DATA_SIZE(&headers),
+                                      H_GET_BSS_SIZE(&headers),
+                                      0, /* No relocation for a bss section. */
+                                      0); /* There are no bss lineno entries */
+                 
+ /* FIXME late night before delivery, I don't know why the chain is
+    broken, but I can guess.  So! Let's force them to be knit properly
+    at this point. */
+
+/* as john pointed out, this wasn't right.  Instead, we'll check here to
+   make sure that the list is doubly linked. */
+
+#if defined(DEBUG) && defined(SYMBOLS_NEED_BACKPOINTERS)
+                 for (symbolP = symbol_rootP; symbol_next(symbolP); symbolP = symbol_next(symbolP)) {
+                         know(symbolP->sy_next->sy_previous == symbolP);
+                 } /* walk the symbol chain */
+#endif /* DEBUG and SYMBOLS_NEED_BACKPOINTERS */
+                 symbolP = symbol_rootP;
+                 
+                 if (symbolP) {
+                         while(symbolP) {
+                                 /* If the symbol has a tagndx entry, resolve it */
+                                 if(SF_GET_TAGGED(symbolP)) {
+                                         SA_SET_SYM_TAGNDX(symbolP,
+                                                           ((symbolS*)SA_GET_SYM_TAGNDX(symbolP))->sy_number);
+                                 }
+                                 /* Debug symbol do not need all this rubbish */
+                                 if(!SF_GET_DEBUG(symbolP)) {
+                                         symbolS* real_symbolP;
+                                         /* L* and C_EFCN symbols never merge. */
+                                         if(!SF_GET_LOCAL(symbolP) &&
+                                            (real_symbolP =
+                                             symbol_find_base(S_GET_NAME(symbolP), DO_NOT_STRIP)) &&
+                                            real_symbolP != symbolP) {
+ /* FIXME where do dups come from?  xoxorich. */
+                                                 /* Move the debug data from the debug symbol to the
+                                                    real symbol. Do NOT do the oposite (i.e. move from
+                                                    real symbol to symbol and remove real symbol from the
+                                                    list.) Because some pointers refer to the real symbol
+                                                    whereas no pointers refer to the symbol. */
+                                                 c_symbol_merge(symbolP, real_symbolP);
+                                                 /* Replace the current symbol by the real one */
+                                                 /* The symbols will never be the last or the first
+                                                    because : 1st symbol is .file and 3 last symbols are
+                                                    .text, .data, .bss */
+                                                 symbol_remove(real_symbolP, &symbol_rootP, &symbol_lastP);
+                                                 symbol_insert(real_symbolP, symbolP, &symbol_rootP, &symbol_lastP);
+                                                 symbol_remove(symbolP, &symbol_rootP, &symbol_lastP);
+                                                 symbolP = real_symbolP;
+                                         }
+                                         if(flagseen['R'] && S_IS_DATA(symbolP))
+                                             S_SET_TEXT(symbolP);
+                                         
+                                         symbolP->sy_value += symbolP->sy_frag->fr_address;
+                                         
+                                         if(!S_IS_DEFINED(symbolP))
+                                             S_SET_EXTERNAL(symbolP);
+                                         else if(S_GET_STORAGE_CLASS(symbolP) == C_NULL)
+                                             S_SET_STORAGE_CLASS(symbolP, C_STAT);
+                                         
+                                         /* Mainly to speed up if not -g */
+                                         if(SF_GET_PROCESS(symbolP)) {
+                                                 /* Handle the nested blocks auxiliary info. */
+                                                 if(S_GET_STORAGE_CLASS(symbolP) == C_BLOCK) {
+                                                         if(!strcmp(S_GET_NAME(symbolP), ".bb"))
+                                                             stack_push(block_stack, (char *) &symbolP);
+                                                         else { /* .eb */
+                                                                 register symbolS* begin_symbolP;
+                                                                 begin_symbolP = *(symbolS**)stack_pop(block_stack);
+                                                                 if(begin_symbolP == (symbolS*)0)
+                                                                     as_warn("mismatched .eb");
+                                                                 else
+                                                                     SA_SET_SYM_ENDNDX(begin_symbolP, symbol_number);
+                                                         }
+                                                 }
+                                                 /* If we are able to identify the type of a function, and we
+                                                    are out of a function (last_functionP == 0) then, the
+                                                    function symbol will be associated with an auxiliary
+                                                    entry. */
+                                                 if(last_functionP == (symbolS*)0 &&
+                                                    SF_GET_FUNCTION(symbolP)) {
+                                                         last_functionP = symbolP;
+                                                         S_SET_NUMBER_AUXILIARY(symbolP, 1);
+                                                         /* Clobber possible stale .dim information. */
+                                                         memset(&symbolP->sy_auxent[0], '\0', sizeof(union auxent));
+                                                 }
+                                                 /* The C_FCN doesn't need any additional information.
+                                                    I don't even know if this is needed for sdb. But the
+                                                    standard assembler generates it, so...
+                                                    */
+                                                 if(S_GET_STORAGE_CLASS(symbolP) == C_EFCN) {
+                                                         if(last_functionP == (symbolS*)0)
+                                                             as_fatal("C_EFCN symbol out of scope");
+                                                         SA_SET_SYM_FSIZE(last_functionP,
+                                                                          (long)(symbolP->sy_value -
+                                                                                 last_functionP->sy_value));
+                                                         SA_SET_SYM_ENDNDX(last_functionP, symbol_number);
+                                                         last_functionP = (symbolS*)0;
+                                                 }
+                                         }
+                                 } else {
+                                         /* First descriptor of a structure must point to the next
+                                            slot outside the structure description. */
+                                         if(SF_GET_TAG(symbolP))
+                                             last_tagP = symbolP;
+                                         else if(S_GET_STORAGE_CLASS(symbolP) == C_EOS)
+                                             /* +2 take in account the current symbol */
+                                             SA_SET_SYM_ENDNDX(last_tagP, symbol_number+2);
+                                 }
+                                 
+                                 /* We must put the external symbols apart. The loader
+                                    does not bomb if we do not. But the references in
+                                    the endndx field for a .bb symbol are not corrected
+                                    if an external symbol is removed between .bb and .be.
+                                    I.e in the following case :
+                                    [20] .bb endndx = 22
+                                    [21] foo external
+                                    [22] .be
+                                    ld will move the symbol 21 to the end of the list but
+                                    endndx will still be 22 instead of 21. */
+                                 {
+                                         register symbolS* thisP = symbolP;
+                                         
+                                         symbolP = symbol_next(thisP);
+                                         /* remove C_EFCN and LOCAL (L...) symbols */
+                                         if (SF_GET_LOCAL(thisP)) {
+                                                 symbol_remove(thisP, &symbol_rootP, &symbol_lastP);
+                                         } else {
+                                                 if(S_GET_STORAGE_CLASS(thisP) == C_EXT &&
+                                                    !SF_GET_FUNCTION(thisP)) {
+                                                         /* Remove from the list */
+                                                         symbol_remove(thisP, &symbol_rootP, &symbol_lastP);
+                                                         symbol_clear_list_pointers(thisP);
+                                                         /* Move at the end of the list */
+                                                         if (symbol_extern_lastP == (symbolS*)0)
+                                                             symbol_externP = thisP;
+                                                         else
+                                                             symbol_append(thisP, symbol_extern_lastP);
+                                                         symbol_extern_lastP = thisP;
+                                                 } else {
+                                                         if(SF_GET_STRING(thisP)) {
+                                                                 thisP->sy_name_offset = string_byte_count;
+                                                                 string_byte_count += strlen(S_GET_NAME(thisP)) + 1;
+                                                         } else
+                                                             thisP->sy_name_offset = 0;
+                                                         thisP->sy_number = symbol_number;
+                                                         symbol_number += 1 + S_GET_NUMBER_AUXILIARY(thisP);
+                                                 }
+                                         }
+                                 }
+                         }
+                         
+                         /* this actually appends the entire extern chain */
+                         symbol_append(symbol_externP, symbol_lastP);
+                         symbolP = symbol_externP;
+                         while(symbolP) {
+                                 if(SF_GET_STRING(symbolP)) {
+                                         symbolP->sy_name_offset = string_byte_count;
+                                         string_byte_count += strlen(S_GET_NAME(symbolP)) + 1;
+                                 } else
+                                     symbolP->sy_name_offset = 0;
+                                 symbolP->sy_number = symbol_number;
+                                 symbol_number += 1 + S_GET_NUMBER_AUXILIARY(symbolP);
+                                 symbolP = symbol_next(symbolP);
+                         }
+                 }
+                 
+ /* FIXME I'm counting line no's here so we know what to put in the section
+    headers, and I'm resolving the addresses since I'm not sure how to
+    do it later. I am NOT resolving the linno's representing functions.
+    Their symbols need a fileptr pointing to this linno when emitted.
+    Thus, I resolve them on emit.  xoxorich. */
+
+                 for (lineP = lineno_rootP; lineP; lineP = lineP->next) {
+                         if (lineP->line.l_lnno) {
+                                 lineP->line.l_addr.l_paddr += ((fragS*)lineP->frag)->fr_address;
+                         } else {
+                                 ;
+                         }
+                         text_lineno_number++;
+                 } /* for each line number */
+         } /* OBJ_COFF version */
+#elif defined(OBJ_AOUT) | defined(OBJ_BOUT)
+         { /* OBJ_AOUT version */
+                 symbolPP = & symbol_rootP;    /* -> last symbol chain link. */
+                 while ((symbolP  = *symbolPP) != NULL)
+                     {
+                             if (flagseen['R'] && S_IS_DATA(symbolP)) {
+                                     S_SET_TEXT(symbolP);
+                             } /* if pusing data into text */
+                             
+                             symbolP -> sy_value += symbolP -> sy_frag -> fr_address;
+                             
+                             /* OK, here is how we decide which symbols go out into the
+                                brave new symtab.  Symbols that do are:
+                                
+                                * symbols with no name (stabd's?)
+                                * symbols with debug info in their N_TYPE
+                                
+                                Symbols that don't are:
+                                * symbols that are registers
+                                * symbols with \1 as their 3rd character (numeric labels)
+                                * "local labels" as defined by S_LOCAL_NAME(name)
+                                if the -L switch was passed to gas.
+                                
+                                All other symbols are output.  We complain if a deleted
+                                symbol was marked external.  */
+                             
+                             
+                             if (1
+                                 && !S_IS_REGISTER(symbolP)
+#ifndef        VMS     /* Under VMS we need to keep local symbols */
+                                 && ( !S_GET_NAME(symbolP)
+                                     || S_IS_DEBUG(symbolP)
+#ifdef TC_I960
+                                     /* FIXME this ifdef seems highly dubious to me.  xoxorich. */
+                                     || !S_IS_DEFINED(symbolP)
+                                     || S_IS_EXTERNAL(symbolP)
+#endif /* TC_I960 */
+                                     || (S_GET_NAME(symbolP)[0] != '\001' && (flagseen ['L'] || ! S_LOCAL_NAME(symbolP))))
+#endif /* not VMS */
+                                 )
+                                 {
+#ifndef        VMS
+                                         symbolP->sy_number = symbol_number++;
+                                         
+                                         /* The + 1 after strlen account for the \0 at the
+                                            end of each string */
+                                         if (!S_IS_STABD(symbolP)) {
+                                                 /* Ordinary case. */
+                                                 symbolP->sy_name_offset = string_byte_count;
+                                                 string_byte_count += strlen(S_GET_NAME(symbolP)) + 1;
+                                         }
+                                         else  /* .Stabd case. */
+#endif /* not VMS */
+                                             symbolP->sy_name_offset = 0;
+                                         symbolPP = &(symbol_next(symbolP));
+                                 } else {
+                                         if (S_IS_EXTERNAL(symbolP) || !S_IS_DEFINED(symbolP)) {
+                                                 as_bad ("Local symbol %s never defined", name);
+                                         } /* oops. */
+                                         
+#ifndef VMS
+                                         /* Unhook it from the chain */
+                                         *symbolPP = symbol_next(symbolP);
+#endif /* VMS */
+                                 } /* if this symbol should be in the output */
+                     } /* for each symbol */
+         } /* OBJ_AOUT version */
+#else
+         cant_crawl_symbol_table();
+#endif
+         H_SET_STRING_SIZE(&headers,string_byte_count);
+         H_SET_SYMBOL_TABLE_SIZE(&headers, symbol_number);
+  } /* crawl symbol table */
+
+} /* obj_crawl_symbol_chain() */
+
+/* end of obj-vms.c */
diff --git a/gas/make-gas.com b/gas/make-gas.com
new file mode 100644 (file)
index 0000000..96922c4
--- /dev/null
@@ -0,0 +1,56 @@
+$! Set the def dir to proper place for use in batch. Works for interactive to.
+$flnm = f$enviroment("PROCEDURE")     ! get current procedure name
+$set default 'f$parse(flnm,,,"DEVICE")''f$parse(flnm,,,"DIRECTORY")'
+$!
+$!     Command file to build a GNU assembler on VMS
+$!
+$!     If you are using a version of GCC that supports global constants
+$!     you should remove the define="const=" from the gcc lines.
+$ if "''p1'" .eqs. "LINK" then goto Link
+$ gcc/debug/define=("VMS","const=") as.c
+$ gcc/debug/define=("VMS", "error=as_fatal","const=") xrealloc.c
+$ gcc/debug/define=("VMS", "error=as_fatal","const=") xmalloc.c
+$ gcc/debug/define=("VMS", "error=as_fatal","const=") hash.c
+$ gcc/debug/define=("VMS","const=") obstack.c
+$ gcc/debug/define=("VMS","const=") hex-value.c
+$ gcc/debug/define=("VMS","const=") atof-generic.c
+$ gcc/debug/define=("VMS","const=") append.c
+$ gcc/debug/define=("VMS","const=") messages.c
+$ gcc/debug/define=("VMS","const=") expr.c
+$ gcc/debug/define=("VMS","const=") app.c
+$ gcc/debug/define=("VMS","const=") frags.c
+$ gcc/debug/define=("VMS","const=") input-file.c
+$ gcc/debug/define=("VMS","const=") input-scrub.c
+$ gcc/debug/define=("VMS","const=") output-file.c
+$ gcc/debug/define=("VMS","const=") read.c
+$ gcc/debug/define=("VMS","const=") subsegs.c
+$ gcc/debug/define=("VMS","const=") symbols.c
+$ gcc/debug/define=("VMS","const=") write.c
+$ gcc/debug/define=("VMS","const=") version.c
+$ gcc/debug/define=("VMS","const=") flonum-const.c
+$ gcc/debug/define=("VMS","const=") flonum-copy.c
+$ gcc/debug/define=("VMS","const=") flonum-mult.c
+$ gcc/debug/define=("VMS","const=") strstr.c
+$ gcc/debug/define=("VMS","const=") bignum-copy.c
+$ gcc/debug/define=("VMS", "error=as_fatal","const=") vax.c
+$ gcc/debug/define=("VMS","const=") atof-vax.c
+$ write sys$output " If you are building gas to work with the G++ compiler"
+$ write sys$output " based upon gcc version 1.37.n or earlier, you should"
+$ write sys$output " edit make-gas.com and make the changes indicated in the"
+$ write sys$output "comments."
+$! For older versions of G++, we need the jsb hack, the HACK_DEC_C_STARTUP
+$! enables this.  Just use the compilation for vms.c that defines this instead
+$! of the other one.
+$ gcc/debug/define=("VMS", "error=as_fatal","const=") vms.c
+$! gcc/debug/define=("VMS", "error=as_fatal","HACK_DEC_C_STARTUP","const=") vms.c
+$ gcc/debug/define=("VMS","const=") vms-dbg.c
+$ Link:
+$ link/exec=gcc-as sys$input:/opt
+!
+!      Linker options file for GNU assembler
+!
+as,xrealloc,xmalloc,hash,hex-value,atof-generic,append,messages,expr,app,-
+frags,input-file,input-scrub,output-file,read,subsegs,symbols,write,-
+version,flonum-const,flonum-copy,flonum-mult,strstr,bignum-copy,-
+obstack,vax,atof-vax,vms,vms-dbg,-
+gnu_cc:[000000]gcclib/lib,sys$share:vaxcrtl/lib
diff --git a/gas/obsolete/gdb-blocks.c b/gas/obsolete/gdb-blocks.c
new file mode 100644 (file)
index 0000000..15cd347
--- /dev/null
@@ -0,0 +1,289 @@
+/* gdb_block.c - Deal with GDB blocks
+   Copyright (C) 1987 Free Software Foundation, Inc.
+
+This file is part of GAS, the GNU Assembler.
+
+GAS 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 1, or (at your option)
+any later version.
+
+GAS 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 GAS; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/*
+ * Implements .gdbblk, .gdbbeg, .gdbend concepts.
+ * No other modules need to know the details of these concepts.
+ *
+ * During assembly, note the addresses of block beginnings and ends.
+ * Each block has a begin-address, an end-address, a number, and
+ * a place in the GDB symbol file to place the 2 addresses.
+ * Block numbers are 0, 1, ... with no gaps.
+ *
+ * During assembly, we don't actually know the addresses, so they are
+ * expressed as {frag-address + offset-in-frag}.
+ *
+ * gdb_block_begin ()
+ *             Call once before using this package.
+ *
+ * gdb_block_beg  (number, frag, offset)
+ *             Note a block beginning.
+ *
+ * gdb_block_end    (number, frag, offset)
+ *             Note a block end.
+ *
+ * gdb_block_position (block_number, pos)
+ *             Remember, after assembly, to copy a structure containing
+ *             the beginning and ending addresses of block number
+ *             block_number into the gdb file, starting at position pos.
+ *
+ * gdb_block_emit  (block_number, where_in_gdb_symbol_file)
+ *             Emit a block begin/end locations to a place in the GDB symbol
+ *             file.
+ *
+ * uses:
+ *     xmalloc()
+ *     gdb_alter()
+ */
+
+
+#include "as.h"
+\f
+/*
+ * malloc() calls are considered expensive. So ...
+ *
+ * We remember blocks by making a tree, and each block number has a leaf.
+ * The tree is 3 levels, and we don't allocate interior nodes until they
+ * are needed. Both leaves and interior nodes are allocated in lumps,
+ * which should save on malloc() calls. Due to the way we break up a
+ * block number to navigate through the tree, we insist that lumps of
+ * memory contain a power of 2 items each. Powers of 2 may differ
+ * for different levels of tree.
+ */
+
+/*
+ *     A block number:
+ *
+ *     +---------------+---------------+---------------+
+ *     |               |               |               |
+ *     |  Z2-part bits |  Z1-part bits |  Z0-part bits |
+ *     |               |               |               |
+ *     +---------------+---------------+---------------+
+ *
+ *     High order                              Low order
+ *
+ * "Z" is short for "siZe".
+ */
+
+#define LOG_2_Z0 (8)           /* How many bits are in Z0 part? */
+#define LOG_2_Z1 (8)           /* How many bits are in Z1 part? */
+#define LOG_2_Z2 (8)           /* How many bits are in Z2 part? */
+
+#define BLOCK_NUMBER_LIMIT (1 << (LOG_2_Z0 + LOG_2_Z1 + LOG_2_Z2))
+                               /* What is the first block number that is */
+                               /* "too big"? */
+
+struct gdb_block
+{
+  fragS *      begin_frag;
+  fragS *        end_frag;
+  long int     begin_where_in_frag;
+  long int       end_where_in_frag;
+  long int     position;       /* In GDB symbols file. */
+};
+
+typedef struct gdb_block       node_0_T        [1 << LOG_2_Z0];
+
+typedef node_0_T *             node_1_T        [1 << LOG_2_Z1];
+
+typedef node_1_T *             node_2_T        [1 << LOG_2_Z2];
+
+
+static long int                highest_block_number_seen;
+static node_2_T *      root;   /* 3 level tree of block locations. */
+
+static node_2_T * new_2 ();
+
+
+char * xmalloc();
+void gdb_alter();
+\f
+void
+gdb_block_begin ()
+{
+  root = new_2 ();
+  highest_block_number_seen = -1;
+}
+
+static node_0_T *
+new_0 ()
+{
+  register node_0_T *  place;
+
+  place = (node_0_T *) xmalloc ((long)sizeof(node_0_T));
+  bzero ((char *)place, sizeof(node_0_T));
+  return (place);
+}
+
+static node_1_T *
+new_1 ()
+{
+  register node_1_T *  place;
+
+  place = (node_1_T *) xmalloc ((long)sizeof(node_1_T));
+  bzero ((char *)place, sizeof(node_1_T));
+  return (place);
+}
+
+static node_2_T *
+new_2 ()
+{
+  register node_2_T *  place;
+
+  place = (node_2_T *) xmalloc ((long)sizeof(node_2_T));
+  bzero ((char *)place, sizeof(node_2_T));
+  return (place);
+}
+\f
+static struct gdb_block *
+find (block_number)
+     register long int block_number;
+{
+  register node_1_T **         pp_1;
+  register node_0_T **         pp_0;
+  register struct gdb_block *  b;
+  register int                 index0;
+  register int                 index1;
+  register int                 index2;
+
+#ifdef SUSPECT
+  if (block_number >= BLOCK_NUMBER_LIMIT)
+    {
+      as_fatal ("gdb_block: Block number = %ld.", block_number);
+    }
+#endif
+
+  index2 = block_number >> (LOG_2_Z0 + LOG_2_Z1);
+  index1 = block_number >> (LOG_2_Z0) & ((1 << LOG_2_Z1) - 1);
+  index0 = block_number & ((1 << LOG_2_Z0) - 1);
+  pp_1 = * root + index2;
+  if (* pp_1 == 0)
+    {
+      * pp_1 = new_1 ();
+    }
+  pp_0 = ** pp_1 + index1;
+  if (* pp_0 == 0)
+    {
+      * pp_0 = new_0 ();
+    }
+  b = ** pp_0 + index0;
+  return (b);
+}
+
+
+static struct gdb_block *
+find_create (block_number)
+     long int  block_number;
+{
+  if (highest_block_number_seen < block_number)
+    {
+      highest_block_number_seen = block_number;
+    }
+  return (find (block_number));
+}
+\f
+void
+gdb_block_beg (block_number, frag, offset)
+     long int  block_number;
+     fragS *   frag;
+     long int  offset;
+{
+  struct gdb_block *   pointer;
+      
+  pointer = find_create (block_number);
+#ifdef SUSPECT
+  if (pointer -> begin_frag != 0)
+    {
+      as_warn( "Overwriting begin_frag for block # %ld.", block_number );
+    }
+  if (pointer -> begin_where_in_frag != 0)
+    {
+      as_warn( "Overwriting begin_where_in_frag for block # %ld.", block_number );
+    }
+#endif
+  pointer -> begin_frag         = frag;
+  pointer -> begin_where_in_frag = offset;
+}
+
+void
+gdb_block_end (block_number, frag, offset)
+     long int  block_number;
+     fragS *   frag;
+     long int  offset;
+{
+  struct gdb_block *   pointer;
+      
+  pointer = find_create (block_number);
+#ifdef SUSPECT
+  if (pointer -> end_frag != 0)
+    {
+      as_warn( "Overwriting end_frag for block # %ld.", block_number );
+    }
+  if (pointer -> end_where_in_frag != 0)
+    {
+      as_warn( "Overwriting end_where_in_frag for block # %ld.", block_number );
+    }
+#endif
+  pointer -> end_frag         = frag;
+  pointer -> end_where_in_frag = offset;
+}
+\f
+void
+gdb_block_position (block_number, pos)
+     long int  block_number;
+     long int  pos;
+{
+  struct gdb_block *   pointer;
+
+  pointer = find_create (block_number);
+  if (pointer -> position != 0)
+    {
+      as_warn( "Overwriting old position %ld. in block #%ld.",
+             pointer -> position, block_number);
+    }
+  pointer -> position = pos;
+}
+
+void
+gdb_block_emit ()
+{
+  long int             block_number;
+  struct gdb_block *   b;
+
+  for (block_number = 0;
+       block_number <= highest_block_number_seen;
+       block_number ++)
+    {
+      b = find (block_number);
+      if (b -> begin_frag)
+       {
+         gdb_alter (b -> position,
+                    (long int)
+                    (b -> begin_frag -> fr_address + b -> begin_where_in_frag));
+       }
+      if (b -> end_frag)
+       {
+         gdb_alter (b -> position + sizeof( long int ),
+                    (long int)
+                    (b -> end_frag -> fr_address + b -> end_where_in_frag));
+       }
+    }
+}
+
+/* end: gdb_block.c */
diff --git a/gas/obsolete/gdb-file.c b/gas/obsolete/gdb-file.c
new file mode 100644 (file)
index 0000000..42938ad
--- /dev/null
@@ -0,0 +1,80 @@
+/* gdb_file.c -o/s specific-
+   Copyright (C) 1987 Free Software Foundation, Inc.
+
+This file is part of GAS, the GNU Assembler.
+
+GAS 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 1, or (at your option)
+any later version.
+
+GAS 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 GAS; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+static long file_len;
+static FILE *file;
+extern long get_len();
+
+
+void
+gdb_file_begin ()
+{
+}
+
+void
+gdb_file_end()
+{
+}
+
+long int                       /* Open file, return size. 0: failed. */
+gdb_file_size (filename)
+char *filename;
+{
+  struct stat stat_buf;
+  void as_perror();
+
+  file= fopen (filename, "r");
+  if (file == (FILE *)NULL)
+    {
+      as_perror ("Can't read GDB symbolic information file", filename);
+      file_len=0;
+    } else {
+       (void)fstat (fileno(file), &stat_buf);
+       file_len=stat_buf . st_size;
+    }
+  return ((long int)file_len );
+}
+
+void                           /* Read the file, don't return if failed. */
+gdb_file_read (buffer, filename)
+     char *    buffer;
+     char *    filename;
+{
+  register off_t       size_wanted;
+  void as_perror();
+
+  size_wanted = file_len;
+  if (fread (buffer, size_wanted, 1, file) != 1)
+    {
+      as_perror ("Can't read GDB symbolic info file", filename);
+      as_fatal ("Failed to read %ld. chars of GDB symbolic information",
+               size_wanted);
+    }
+  if (fclose(file)==EOF)
+    {
+      as_perror ("Can't close GDB symbolic info file", filename);
+      as_fatal ("I quit in disgust");
+    }
+}
+
+/* end: gdb_file.c */
diff --git a/gas/obsolete/gdb-lines.c b/gas/obsolete/gdb-lines.c
new file mode 100644 (file)
index 0000000..6af0c42
--- /dev/null
@@ -0,0 +1,241 @@
+/* gdb-lines.c -- Deal with source lines for GDB format
+   Copyright (C) 1989, Free Software Foundation.
+
+This file is part of GAS, the GNU Assembler.
+
+GAS 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 1, or (at your option)
+any later version.
+
+GAS 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 GAS; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+   
+#include "as.h"
+#include "obstack.h"
+#include "frags.h"
+
+/* This is a souce file that we're storing .gdbline information about */
+/* .gdbline refers to files by numbers.  We keep a linked list of them
+   We store a list of vectors for each file.  Each element of the vector
+   contains a line-number, a frag, and an offset within the frag. */
+struct g_line_file {
+       int     gdb_line_file_file_number;              /* fnum */
+       int     gdb_line_file_number_of_vectors;        /* nv */
+       long    gdb_line_table_offset;                  /* taboff */
+       struct g_line_vector *gdb_line_file_vectors;    /* vec */
+       struct g_line_file *gdb_line_file_next_file;    /* nfile */
+};
+
+/* In order to save on space (We expect there to be LOTS of lines), we
+   store line-number/address pairs in bunches of MAX_LINES_PER_VECTOR
+   (originally fifty).  Each vector descriptor contains
+
+   gdb_line_number_of_lines    the number of line-number/address pairs
+                               actually in this vector.
+   gdb_line_lines              The actual vector.
+
+   gdb_line_next_vector                The next vector descriptor in the linked list.
+ */
+struct g_line_vector {
+       int     gdb_line_number_of_lines;               /* nlines */
+       struct g_line *gdb_line_lines;                  /* lines */
+       struct g_line_vector *gdb_line_next_vector;     /* nvec */
+};
+
+
+/* A .gdbline wants to store a line-number/address pair.  Unfortunatly, we
+   don't know addresses yet, so we store frag/offset which we can use to
+   generate the address at write-out time. */
+struct g_line {
+       int     gdb_line_line_number;                   /* lno */
+       fragS   *gdb_line_frag;                         /* lfrag */
+       int     gdb_line_offset;                        /* loff */
+};
+
+
+/* The following is stolen from (gdb's? (or is it gcc's?) symseg.h file.
+   These structures describe the format for the line# symbolic info in
+   the gdb symbolic info file.  This info is not particularly useful,
+   except to show what we're writing into. . . */
+
+/* Source-file information.
+   This describes the relation between source files and line numbers
+   and addresses in the program text.  */
+
+struct sourcevector
+{
+  int length;                  /* Number of source files described */
+  struct source *source[1];    /* Descriptions of the files */
+};
+
+/* Line number and address of one line.  */
+struct line
+{
+  int linenum;
+  int address;
+};
+
+/* All the information on one source file.  */
+
+struct source
+{
+  char *name;                  /* Name of file */
+  int nlines;                  /* Number of lines that follow */
+  struct line lines[1];        /* Information on each line */
+};
+
+/* End of text from symseg.h */
+
+struct g_line_file *first_file;
+
+struct g_line_file *add_file();
+struct g_line_vector *add_vector();
+
+#define MAX_LINES_PER_VECTOR 50                /* lpv */
+
+/* We've been told that the current address corresponds to line LINENO in
+   file FILE_NUMBER */
+void
+gdb_line(file_number,lineno)
+int file_number;
+int lineno;
+{
+       struct g_line_file *f;
+       struct g_line_vector *v;
+       struct g_line *line;
+
+       for(f=first_file;f;f=f->gdb_line_file_next_file)
+               if(f->gdb_line_file_file_number==file_number)
+                       break;
+       if(!f) f=add_file(file_number);
+       v=f->gdb_line_file_vectors;
+       if(!v || v->gdb_line_number_of_lines==MAX_LINES_PER_VECTOR)
+               v=add_vector(f);
+       line= &(v->gdb_line_lines)[v->gdb_line_number_of_lines];
+       v->gdb_line_number_of_lines++;
+       line->gdb_line_line_number=lineno;
+       line->gdb_line_frag= frag_now;
+       line->gdb_line_offset=obstack_next_free(&frags)-frag_now->fr_literal;
+}
+
+/* We've been told where to store the .line table for file FILE_NUMBER */
+void
+gdb_line_tab(file_number,offset)
+int file_number;
+int offset;
+{
+       struct g_line_file *f;
+
+       for(f=first_file;f;f=f->gdb_line_file_next_file)
+               if(f->gdb_line_file_file_number==file_number)
+                       break;
+       if(!f) f=add_file(file_number);
+       if(f->gdb_line_table_offset)
+               as_warn("Ignoring duplicate .linetab for file %d",file_number);
+       else
+               f->gdb_line_table_offset=offset;
+}
+
+/* We've got a file (FILE_NUMBER) that we haven't heard about before.  Create
+   an entry for it, etc. . . */
+struct g_line_file *
+add_file(file_number)
+{
+       struct g_line_file *f;
+
+       f=(struct g_line_file *)xmalloc(sizeof(struct g_line_file));
+       f->gdb_line_file_file_number=file_number;
+       f->gdb_line_table_offset = 0;
+       f->gdb_line_file_number_of_vectors=0;
+       f->gdb_line_file_vectors=(struct g_line_vector *)0;
+       f->gdb_line_file_next_file=first_file;
+       first_file=f;
+       return f;
+}
+
+/* The last vector for file F is full.  Allocate a new one. */
+struct g_line_vector *
+add_vector(f)
+struct g_line_file *f;
+{
+       struct g_line_vector *tmp_vec;
+
+       f->gdb_line_file_number_of_vectors++;
+       tmp_vec=(struct g_line_vector *)xmalloc(sizeof(struct g_line_vector));
+       tmp_vec->gdb_line_number_of_lines=0;
+       tmp_vec->gdb_line_lines=(struct g_line *)xmalloc(MAX_LINES_PER_VECTOR*sizeof(struct g_line));
+       tmp_vec->gdb_line_next_vector=f->gdb_line_file_vectors;
+       f->gdb_line_file_vectors=tmp_vec;
+       return tmp_vec;
+}
+
+/* All done.  Time to write the stuff out.  This should be fun. */
+void
+gdb_lines_emit()
+{
+       struct g_line_file *f;
+       struct g_line_vector *v,*old_v,*v_tmp;
+       struct g_line *current_line_pointer;    /* lp */
+       int     n;
+       int     previous_line_number;
+       long int current_gdb_segment_pos;
+       unsigned int number_of_things_in_table;
+
+       for(f=first_file;f;f=f->gdb_line_file_next_file) {
+               if(!f->gdb_line_table_offset) {
+                       as_warn("No .gdblinetab given for file %d.  Ignoring .gdbline(s) for it.");
+                       continue;
+               }
+
+               /* Reverse the linked list of vectors.  Since we built it
+                  last entry first, this puts the first entry at the start
+                  of the list.  Thus we can manage to put out low line #s
+                  at the start of the table. . .*/
+               v_tmp=0;
+               old_v=0;
+               for(v=f->gdb_line_file_vectors;v;v=v_tmp) {
+                       v_tmp=v->gdb_line_next_vector;
+                       v->gdb_line_next_vector=old_v;
+                       old_v=v;
+               }
+               f->gdb_line_file_vectors=old_v;
+
+               /* Start putting stuff at the beginning of the table */
+               current_gdb_segment_pos=f->gdb_line_table_offset+sizeof(long int);
+               previous_line_number = -2;
+               number_of_things_in_table = 0;
+
+               /* For every vector in the table: */
+               for(v=f->gdb_line_file_vectors;v;v=v->gdb_line_next_vector) {
+                       current_line_pointer=v->gdb_line_lines;
+
+                       /* For every element of every vector */
+                       for(n=v->gdb_line_number_of_lines;n;n--) {
+
+                               if(current_line_pointer->gdb_line_line_number != previous_line_number + 1) {
+                                       /* Write out the line number */
+                                       gdb_alter(current_gdb_segment_pos, -(current_line_pointer->gdb_line_line_number));
+                                       current_gdb_segment_pos+=sizeof(long int);
+                                       number_of_things_in_table++;
+                               }
+                               previous_line_number = current_line_pointer->gdb_line_line_number;
+
+                               /* And write out the address */
+                               gdb_alter(current_gdb_segment_pos,current_line_pointer->gdb_line_frag->fr_address+current_line_pointer->gdb_line_offset);
+                               current_gdb_segment_pos+=sizeof(long int);
+                               number_of_things_in_table++;
+
+                               current_line_pointer++;
+                       }
+               }
+               gdb_alter(f->gdb_line_table_offset,number_of_things_in_table);
+       }
+}
diff --git a/gas/obsolete/gdb-symbols.c b/gas/obsolete/gdb-symbols.c
new file mode 100644 (file)
index 0000000..8bd8f7d
--- /dev/null
@@ -0,0 +1,129 @@
+/* gdb_symbols.c - Deal with symbols for GDB format
+   Copyright (C) 1987 Free Software Foundation, Inc.
+
+This file is part of GAS, the GNU Assembler.
+
+GAS 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 1, or (at your option)
+any later version.
+
+GAS 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 GAS; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/*
+ * During assembly, note requests to place symbol values in the GDB
+ * symbol file. When symbol values are known and the symbol file is
+ * in memory, place the symbol values in the memory image of the file.
+ *
+ * This has static data: it is not data_sharable.
+ *
+ * gdb_symbols_begin ()
+ *             Call once before using this package.
+ *
+ * gdb_symbols_fixup (symbolP, offset_in_file)
+ *             Remember to put the value of a symbol into the GDB file.
+ *
+ * gdb_symbols_emit  ()
+ *             Perform all the symbol fixups.
+ *
+ * uses:
+ *     xmalloc()
+ *     gdb_alter()
+ */
+
+#include "as.h"
+#include "struc-symbol.h"
+
+#define SYM_GROUP (100)                /* We allocate storage in lumps this big. */
+
+
+struct gdb_symbol              /* 1 fixup request. */
+{
+  symbolS *    gs_symbol;
+  long int     gs_offset;      /* Where in GDB symbol file. */
+};
+typedef struct gdb_symbol gdb_symbolS;
+
+struct symbol_fixup_group
+{
+  struct symbol_fixup_group *  sfg_next;
+  gdb_symbolS                  sfg_item [SYM_GROUP];
+};
+typedef struct symbol_fixup_group symbol_fixup_groupS;
+
+static symbol_fixup_groupS *   root;
+static short int               used; /* # of last slot used. */
+                               /* Counts down from SYM_GROUP. */
+\f
+static symbol_fixup_groupS *   /* Make storage for some more reminders. */
+new_sfg ()
+{
+  symbol_fixup_groupS *                newP;
+  char *                       xmalloc();
+
+  newP = (symbol_fixup_groupS *) xmalloc ((long)sizeof(symbol_fixup_groupS));
+  newP -> sfg_next = root;
+  used = SYM_GROUP;
+  root = newP;
+  return (newP);
+}
+
+
+void
+gdb_symbols_begin ()
+{
+  root = 0;
+  (void)new_sfg ();
+}
+
+
+void                           /* Build a reminder to put a symbol value */
+gdb_symbols_fixup (sy, offset) /* into the GDB symbol file. */
+     symbolS * sy;             /* Which symbol. */
+     long int  offset;         /* Where in GDB symbol file. */
+{
+  register symbol_fixup_groupS *       p;
+  register gdb_symbolS *               q;
+      
+  p = root;
+  know( used >= 0 );
+  if ( used == 0)
+    {
+      p = new_sfg ();
+    }
+  q = p -> sfg_item + -- used;
+  q -> gs_symbol = sy;
+  q -> gs_offset = offset;
+}
+\f
+void
+gdb_symbols_emit ()            /* Append GDB symbols to object file. */
+{
+  symbol_fixup_groupS *        sfgP;
+  void gdb_alter();
+  
+  for (sfgP = root;  sfgP;  sfgP = sfgP -> sfg_next)
+    {
+      register gdb_symbolS *   gsP;
+      register gdb_symbolS *   limit;
+
+      limit = sfgP -> sfg_item +
+       (sfgP -> sfg_next ? 0 : used);
+      for (gsP = sfgP -> sfg_item + SYM_GROUP - 1;
+          gsP >= limit;
+          gsP --)
+       {
+         gdb_alter (gsP -> gs_offset,
+                    (long int) gsP -> gs_symbol -> sy_value);
+       }
+    }
+}
+
+/* end: gdb_symbols.c */
diff --git a/gas/obsolete/gdb.c b/gas/obsolete/gdb.c
new file mode 100644 (file)
index 0000000..4896e2e
--- /dev/null
@@ -0,0 +1,110 @@
+/* gdb.c -as supports gdb-
+   Copyright (C) 1987 Free Software Foundation, Inc.
+
+This file is part of GAS, the GNU Assembler.
+
+GAS 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 1, or (at your option)
+any later version.
+
+GAS 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 GAS; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* This code is independent of the underlying operating system. */
+
+#include "as.h"
+
+static long int                size;   /* 0 or size of GDB symbol file. */
+static char *          where;  /* Where we put symbol file in memory. */
+
+#define SUSPECT                /* JF */
+
+long int                       /* 0 means don't call gdb_... routines */
+gdb_begin (filename)           /* because we failed to establish file */
+                               /* in memory. */
+     char * filename;          /* NULL: we have nothing to do. */
+{
+  long int             gdb_file_size();
+  char *               xmalloc();
+  void                 gdb_file_begin();
+  void                 gdb_file_read();
+  void                 gdb_block_begin();
+  void                 gdb_symbols_begin();
+
+  gdb_file_begin();
+  size = 0;
+  if (filename && (size = gdb_file_size (filename)))
+    {
+      where = xmalloc( (long) size );
+      gdb_file_read (where, filename); /* Read, then close file. */
+      gdb_block_begin();
+      gdb_symbols_begin();
+    }
+  return (size);
+}
+
+void
+gdb_end()
+{
+  void gdb_file_end();
+
+  gdb_file_end();
+}
+\f
+void
+gdb_emit (filename)    /* Append GDB symbols to object file. */
+char * filename;
+{
+  void gdb_block_emit();
+  void gdb_symbols_emit();
+  void gdb_lines_emit();
+  void output_file_append();
+
+  gdb_block_emit ();
+  gdb_symbols_emit ();
+  gdb_lines_emit();
+  output_file_append (where, size, filename);
+}
+
+
+
+/*
+       Notes:  We overwrite what was there.
+               We assume all overwrites are 4-char numbers.
+*/
+
+void
+gdb_alter (offset, value)      /* put value into GDB file + offset. */
+     long int  offset;
+     long int  value;
+{
+  void md_number_to_chars();
+
+#ifdef SUSPECT
+  if (offset > size - sizeof(long int) || offset < 0)
+    {
+      as_warn( "gdb_alter: offset=%d. size=%ld.\n", offset, size );
+      return;
+    }
+#endif
+
+#ifdef B_OUT
+      /* Symbol info will be used on the host machine only (only executable
+       * code is actually downloaded to the i80960).  Therefore, leave it
+       * in host byte order.
+       */
+
+      *(long int *)(where + offset) = value;
+#else
+      md_number_to_chars (where + offset, value, 4);
+#endif
+}
+
+/* end: gdb.c */
diff --git a/gas/ver960.c b/gas/ver960.c
new file mode 100644 (file)
index 0000000..fee9000
--- /dev/null
@@ -0,0 +1 @@
+char gas960_ver[]= "gas960 1.2, Fri Nov 30 03:01:56 PST 1990";
diff --git a/gas/version.c b/gas/version.c
new file mode 100644 (file)
index 0000000..6a46f45
--- /dev/null
@@ -0,0 +1,23 @@
+#if defined(__STDC__) || defined(const)
+const
+#endif
+char version_string[] = "GNU assembler version 1.38.1 (Cygnus Support pre-release)\n";
+\f
+/* DO NOT PUT COMMENTS ABOUT CHANGES IN THIS FILE.
+
+   This file exists only to define `version_string'.
+
+   Log changes in ChangeLog.  The easiest way to do this is with
+   the Emacs command `add-change-log-entry'.  If you don't use Emacs,
+   add entries of the form:
+
+Thu Jan  1 00:00:00 1970  Dennis Ritchie  (dmr at alice)
+
+       * universe.c (temporal_reality): Began Time.
+*/
+
+#ifdef VMS
+dummy3()
+{
+}
+#endif
This page took 0.112928 seconds and 4 git commands to generate.