aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorK. Richard Pixley <rich@cygnus>1991-04-04 18:19:56 +0000
committerK. Richard Pixley <rich@cygnus>1991-04-04 18:19:56 +0000
commit0e39a8bbfe9e77100c9f0672415b2ae32df54d29 (patch)
tree50d89163c44d492bf99d7db29f54cd141c08a233
parent3c0c9328b9c299580bcf8cb6fdb3b71d5a0525ff (diff)
downloadfsf-binutils-gdb-0e39a8bbfe9e77100c9f0672415b2ae32df54d29.zip
fsf-binutils-gdb-0e39a8bbfe9e77100c9f0672415b2ae32df54d29.tar.gz
fsf-binutils-gdb-0e39a8bbfe9e77100c9f0672415b2ae32df54d29.tar.bz2
new gas main line
-rw-r--r--gas/.gdbinit4
-rwxr-xr-xgas/GNUmakefile-host6
-rwxr-xr-xgas/Makefile.loic203
-rw-r--r--gas/Makefile.old434
-rw-r--r--gas/NOTES19
-rw-r--r--gas/NOTES.config52
-rw-r--r--gas/README-vms-dbg127
-rw-r--r--gas/README.coff79
-rw-r--r--gas/README.rich143
-rwxr-xr-xgas/VERSION1
-rw-r--r--gas/config/ho-ansi.h5
-rwxr-xr-xgas/config/ho-cygnus.h5
-rw-r--r--gas/config/ho-decstation.h25
-rw-r--r--gas/config/ho-generic.h5
-rw-r--r--gas/config/ho-rs6000.h22
-rw-r--r--gas/config/ho-vax.h29
-rwxr-xr-xgas/config/mh-cygnus8
-rw-r--r--gas/config/mh-i3861
-rw-r--r--gas/config/obj-bfd-sunos.c51
-rw-r--r--gas/config/obj-bfd-sunos.h50
-rwxr-xr-xgas/config/te-motor.h4
-rw-r--r--gas/config/te-sco386.h8
-rwxr-xr-xgas/config/te-sparc.h52
-rwxr-xr-xgas/config/te-unisoft.h4
-rwxr-xr-xgas/config/tmake-sun31
-rw-r--r--gas/config/vms/objrecdef.h255
-rw-r--r--gas/config/vms/vms-dbg.c1125
-rw-r--r--gas/config/vms/vms.c3741
-rw-r--r--gas/make-gas.com56
-rw-r--r--gas/obsolete/gdb-blocks.c289
-rw-r--r--gas/obsolete/gdb-file.c80
-rw-r--r--gas/obsolete/gdb-lines.c241
-rw-r--r--gas/obsolete/gdb-symbols.c129
-rw-r--r--gas/obsolete/gdb.c110
-rw-r--r--gas/ver960.c1
-rw-r--r--gas/version.c23
36 files changed, 7385 insertions, 3 deletions
diff --git a/gas/.gdbinit b/gas/.gdbinit
new file mode 100644
index 0000000..2044214
--- /dev/null
+++ b/gas/.gdbinit
@@ -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
index 0000000..386c869
--- /dev/null
+++ b/gas/GNUmakefile-host
@@ -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
index 0000000..4de7da1
--- /dev/null
+++ b/gas/Makefile.loic
@@ -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
index 0000000..9cbb532
--- /dev/null
+++ b/gas/Makefile.old
@@ -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
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
index 0000000..e12797d
--- /dev/null
+++ b/gas/NOTES.config
@@ -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
index 0000000..61ab6dd
--- /dev/null
+++ b/gas/README-vms-dbg
@@ -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
index 0000000..46c61cd
--- /dev/null
+++ b/gas/README.coff
@@ -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
index 0000000..1ac53c7
--- /dev/null
+++ b/gas/README.rich
@@ -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
index 0000000..5625e59
--- /dev/null
+++ b/gas/VERSION
@@ -0,0 +1 @@
+1.2
diff --git a/gas/config/ho-ansi.h b/gas/config/ho-ansi.h
index b7fc587..977808f 100644
--- a/gas/config/ho-ansi.h
+++ b/gas/config/ho-ansi.h
@@ -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
*
*
diff --git a/gas/config/ho-cygnus.h b/gas/config/ho-cygnus.h
index 9b39153..e2667a0 100755
--- a/gas/config/ho-cygnus.h
+++ b/gas/config/ho-cygnus.h
@@ -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
index 0000000..f307e20
--- /dev/null
+++ b/gas/config/ho-decstation.h
@@ -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 */
diff --git a/gas/config/ho-generic.h b/gas/config/ho-generic.h
index 40c49e9..c474665 100644
--- a/gas/config/ho-generic.h
+++ b/gas/config/ho-generic.h
@@ -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
index 0000000..8f624f4
--- /dev/null
+++ b/gas/config/ho-rs6000.h
@@ -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
index 0000000..735a215
--- /dev/null
+++ b/gas/config/ho-vax.h
@@ -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
index 0000000..774d205
--- /dev/null
+++ b/gas/config/mh-cygnus
@@ -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
index 0000000..3375d42
--- /dev/null
+++ b/gas/config/mh-i386
@@ -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
index 0000000..0bbc600
--- /dev/null
+++ b/gas/config/obj-bfd-sunos.c
@@ -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
index 0000000..0d32758
--- /dev/null
+++ b/gas/config/obj-bfd-sunos.h
@@ -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
index 0000000..2254841
--- /dev/null
+++ b/gas/config/te-motor.h
@@ -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
index 0000000..8bcb688
--- /dev/null
+++ b/gas/config/te-sco386.h
@@ -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
index 0000000..fcd3535
--- /dev/null
+++ b/gas/config/te-sparc.h
@@ -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
index 0000000..2254841
--- /dev/null
+++ b/gas/config/te-unisoft.h
@@ -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
index 0000000..9681e6d
--- /dev/null
+++ b/gas/config/tmake-sun3
@@ -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
index 0000000..fca8af4
--- /dev/null
+++ b/gas/config/vms/objrecdef.h
@@ -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];
+ };
+
+#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
+
+#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
+
+#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
+
+#define GSY$M_WEAK 1
+#define GSY$M_DEF 2
+#define GSY$M_UNI 4
+#define GSY$M_REL 8
+
+#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
+
+#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
+
+/*
+ * 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
index 0000000..19c6c93
--- /dev/null
+++ b/gas/config/vms/vms-dbg.c
@@ -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
index 0000000..cd3bb59
--- /dev/null
+++ b/gas/config/vms/vms.c
@@ -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 *);
+
+
+/*
+ * 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 */
+ }
+}
+
+/*
+ * 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();
+
+ /*
+ * 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;
+ }
+ }
+ }
+
+ /******* 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;
+ }
+
+ }
+ }
+
+ /*
+ * 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();
+
+ /*
+ * 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);
+
+ /*
+ * All done, close the object file
+ */
+ Close_VMS_Object_File();
+}
+
+
+ /****** 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)
+
+
+/*
+ * 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;
+}
+
+
+/*
+ * 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;
+}
+
+
+/*
+ * 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;
+}
+
+
+/*
+ * Close the VMS Object file
+ */
+Close_VMS_Object_File()
+{
+ close(VMS_Object_File_FD);
+}
+
+
+/*
+ * 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();
+}
+
+
+/*
+ * 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();
+}
+
+
+/* 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);
+}
+
+
+/*
+ * 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;
+}
+
+
+/*
+ * 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();
+}
+
+
+/*
+ * 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();
+}
+
+
+/*
+ * 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();
+}
+
+
+/*
+ * 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();
+}
+
+/*
+ * 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();
+ }
+}
+
+
+/*
+ * 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();
+}
+
+
+/*
+ * 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();
+}
+
+
+/*
+ * 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);
+ }
+}
+
+
+/*
+ * 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);
+}
+
+
+/*
+ * 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);
+}
+
+
+/*
+ * 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);
+}
+
+
+/*
+ * 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);
+}
+
+
+/*
+ * 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);
+}
+
+
+
+/*
+ * 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);
+ }
+}
+
+
+/*
+ * 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);
+}
+
+
+/*
+ * 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);
+}
+
+
+/*
+ * 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));
+}
+
+
+
+/* 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;
+}
+
+
+/*
+ * 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
index 0000000..96922c4
--- /dev/null
+++ b/gas/make-gas.com
@@ -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
index 0000000..15cd347
--- /dev/null
+++ b/gas/obsolete/gdb-blocks.c
@@ -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"
+
+/*
+ * 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();
+
+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);
+}
+
+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));
+}
+
+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;
+}
+
+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
index 0000000..42938ad
--- /dev/null
+++ b/gas/obsolete/gdb-file.c
@@ -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
index 0000000..6af0c42
--- /dev/null
+++ b/gas/obsolete/gdb-lines.c
@@ -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
index 0000000..8bd8f7d
--- /dev/null
+++ b/gas/obsolete/gdb-symbols.c
@@ -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. */
+
+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;
+}
+
+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
index 0000000..4896e2e
--- /dev/null
+++ b/gas/obsolete/gdb.c
@@ -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();
+}
+
+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
index 0000000..fee9000
--- /dev/null
+++ b/gas/ver960.c
@@ -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
index 0000000..6a46f45
--- /dev/null
+++ b/gas/version.c
@@ -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";
+
+/* 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