summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert de Bath <rdebath@poboxes.com>1999-12-17 19:06:32 +0100
committerLubomir Rintel <lkundrak@v3.sk>2013-10-23 23:43:38 +0200
commit3401185106fb312c6a7bba3d9e90d44b6df0043b (patch)
tree63bace6fae9b547cc0c939c6803185cc3ad8aa0e
parent3d4957c86ff239b24b43933924ec72a3fd288518 (diff)
downloaddev86-3401185106fb312c6a7bba3d9e90d44b6df0043b.tar.gz
Import Dev86src-0.15.0.tar.gzv0.15.0
-rw-r--r--Changes4
-rw-r--r--Libc_version2
-rw-r--r--ar/Makefile37
-rw-r--r--ar/ar.c2061
-rw-r--r--as/TODO4
-rw-r--r--as/as.doc2
-rw-r--r--as/express.c16
-rw-r--r--as/mops.c13
-rw-r--r--as/pops.c13
-rw-r--r--bcc/function.c1
-rw-r--r--bin86/Makefile19
-rw-r--r--bootblocks/Makefile4
-rw-r--r--bootblocks/README3
-rw-r--r--bootblocks/bootlist.s257
-rw-r--r--bootblocks/bzimage.c21
-rw-r--r--bootblocks/monitor.c10
-rw-r--r--bootblocks/msdos.s18
-rw-r--r--copt/Makefile3
-rw-r--r--copt/copt.c2
-rwxr-xr-xcopt/copt1bin0 -> 16528 bytes
-rw-r--r--elksemu/elks_sys.c1
-rw-r--r--ifdef.c3
-rw-r--r--ld/objdump86.c113
-rw-r--r--libc/Makefile4
-rw-r--r--libc/msdos/dirent.c8
-rw-r--r--libc/msdos/dosound.c10
-rw-r--r--makefile.in27
-rw-r--r--man/as86.13
-rw-r--r--man/elksemu.12
-rw-r--r--man/index.btbin0 -> 8192 bytes
30 files changed, 2321 insertions, 340 deletions
diff --git a/Changes b/Changes
index 6708e02..929a979 100644
--- a/Changes
+++ b/Changes
@@ -1,5 +1,9 @@
For version 0.15.0.
+> Added support for archives to nm86/objdump86 and size86.
+
+> ar86 added. Used for Linux because RedHat is broken.
+
> Bugfixes on utmpent and friends.
> A bit more in the manpages on how to use the assembler etc.
diff --git a/Libc_version b/Libc_version
index f3cc26b..a551051 100644
--- a/Libc_version
+++ b/Libc_version
@@ -1 +1 @@
-0.14.8
+0.15.0
diff --git a/ar/Makefile b/ar/Makefile
new file mode 100644
index 0000000..f3b890d
--- /dev/null
+++ b/ar/Makefile
@@ -0,0 +1,37 @@
+# Copyright (c) 1999 Greg Haerr <greg@censoft.com>
+# This file is part of the Linux-8086 Development environment and is
+# distributed under the GNU General Public License.
+
+xCC=bcc -0
+LIBDIR =/usr/bin
+CFLAGS =-O
+LDFLAGS =
+DEFS =
+OBJS= ar.o
+
+all: ar86
+
+ar86: $(OBJS)
+ $(CC) $(LDFLAGS) $(OBJS) -o $@
+
+install: ar86
+ install -d $(LIBDIR)
+ install -m 755 ar86 $(LIBDIR)
+
+clean realclean clobber:
+ rm -f *.o ar86 ar.h rel_aout.h
+
+$(OBJS): ar.h rel_aout.h
+
+ar.h:
+ [ -f ar.h ] || \
+ { rm -f ar.h ; ln -s ../libc/include/ar.h . ; } || \
+ ln ../libc/include/ar.h .
+
+rel_aout.h:
+ [ -f rel_aout.h ] || \
+ { rm -f rel_aout.h ; ln -s ../ld/rel_aout.h . ; } || \
+ ln ../ld/rel_aout.h .
+
+.c.o:
+ $(CC) $(CFLAGS) $(DEFS) -c $< -o $@
diff --git a/ar/ar.c b/ar/ar.c
new file mode 100644
index 0000000..1cc3443
--- /dev/null
+++ b/ar/ar.c
@@ -0,0 +1,2061 @@
+/* ar.c - Archive modify and extract.
+ Copyright (C) 1988, 1990 Free Software Foundation, Inc.
+ ar86 changes by Greg Haerr <greg@censoft.com>
+
+ This program 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.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "ar.h"
+#include "rel_aout.h"
+
+#ifdef __BCC__
+#define HAVE_RENAME
+#undef HAVE_FSYNC
+#define SHORT_FILENAME
+extern char **sys_errlist;
+extern int sys_nerr;
+#else
+#define HAVE_FCHMOD
+#define HAVE_RENAME
+#undef HAVE_FSYNC
+#endif
+
+extern int errno;
+
+#ifdef __GNUC__
+# ifndef alloca
+# define alloca __builtin_alloca
+# endif
+#else
+# if defined(sparc) || defined(HAVE_ALLOCA_H)
+# include <alloca.h>
+# else
+char *alloca ();
+# endif
+#endif
+
+#ifdef USG
+#define bcopy(source, dest, size) memcpy((dest), (source), (size))
+#define bcmp(a, b, size) memcmp((a), (b), (size))
+#define bzero(s, size) memset((s), 0, (size))
+#endif
+
+/* Locking is normally disabled because fcntl hangs on the Sun
+ and it isn't supported properly across NFS anyway. */
+#ifdef LOCKS
+#include <errno.h>
+#endif
+
+/* This structure is used internally to represent the info
+ on a member of an archive. This is to make it easier to change format. */
+
+struct member_desc
+ {
+ /* Name of member. */
+ char *name;
+
+ /* The following fields are stored in the member header as decimal or octal
+ numerals, but in this structure they are stored as machine numbers. */
+ int mode; /* Protection mode from member header. */
+ long int date; /* Last modify date as stored in member header. */
+ unsigned int size; /* Bytes of member's data, from member header. */
+ int uid, gid; /* UID and GID fields copied from member header. */
+ unsigned int offset;/* Offset in archive of the header of this member. */
+ unsigned int data_offset;/* Offset of first data byte of the member. */
+
+ /* The next field does not describe where the member was in the
+ old archive, but rather where it will be in the modified archive.
+ It is set up by write_archive. */
+ unsigned int new_offset; /* Offset of this member in new archive */
+
+ /* Symdef data for member. Used only for files being inserted. */
+ struct symdef *symdefs;
+ unsigned int nsymdefs; /* Number of entries of symdef data. */
+ unsigned int string_size; /* Size of strings needed by symdef data. */
+ };
+
+/* Each symbol is recorded by something like this. */
+
+struct symdef
+ {
+ union
+ {
+ unsigned long int stringoffset;
+ char *name;
+ } s;
+ unsigned long int offset;
+ };
+
+/* Nonzero means it's the name of an existing member;
+ position new or moved files with respect to this one. */
+
+char *posname;
+
+/* How to use `posname':
+ POS_BEFORE means position before that member.
+ POS_AFTER means position after that member.
+ POS_DEFAULT if position by default; then `posname' should also be zero. */
+
+enum { POS_DEFAULT, POS_BEFORE, POS_AFTER } postype;
+
+/* Nonzero means describe each action performed. */
+
+int verbose;
+
+/* Nonzero means don't warn about creating the archive file if necessary. */
+
+int silent_create;
+
+/* Nonzero means don't replace existing members whose
+ dates are more recent than the corresponding files. */
+
+int newer_only;
+
+/* Nonzero means preserve dates of members when extracting them. */
+
+int preserve_dates;
+
+/* Operation to be performed. */
+
+#define DELETE 1
+#define REPLACE 2
+#define PRINT_TABLE 3
+#define PRINT_FILES 4
+#define EXTRACT 5
+#define MOVE 6
+#define QUICK_APPEND 7
+
+int operation;
+
+/* Name of archive file. */
+
+char *archive;
+
+/* Descriptor on which we have locked the original archive file,
+ or -1 if this has not been done. */
+
+int lock_indesc;
+
+/* Pointer to tail of `argv', at first subfile name argument,
+ or zero if no such were specified. */
+
+char **files;
+
+/* Nonzero means write a __.SYMDEF member into the modified archive. */
+int symdef_flag;
+
+/* Nonzero means __.SYMDEF member exists in old archive. */
+int symdef_exists;
+
+/* Nonzero means don't update __.SYMDEF unless the flag was given. */
+int ignore_symdef;
+
+/* Total number of symdef entries we will have. */
+unsigned long int nsymdefs;
+
+/* Symdef data from old archive (set up only if we need it) */
+struct symdef *old_symdefs;
+
+/* Number of symdefs in remaining in old_symdefs. */
+unsigned int num_old_symdefs;
+
+/* Number of symdefs old_symdefs had when it was read in. */
+unsigned long int original_num_symdefs;
+
+/* String table from old __.SYMDEF member. */
+char *old_strings;
+
+/* Size of old_strings */
+unsigned long int old_strings_size;
+
+/* String table to be written into __.SYMDEF member. */
+char *new_strings;
+
+/* Size of new_strings */
+unsigned long int new_strings_size;
+
+/* An archive map is a chain of these structures.
+ Each structure describes one member of the archive.
+ The chain is in the same order as the members are. */
+
+struct mapelt
+{
+ struct member_desc info;
+ struct mapelt *next;
+};
+
+struct mapelt *maplast;
+
+/* If nonzero, this is the map-element for the __.SYMDEF member
+ and we should update the time of that member just before finishing. */
+struct mapelt *symdef_mapelt;
+
+/* Header that we wrote for the __.SYMDEF member. */
+struct ar_hdr symdef_header;
+
+/* Name this program was run with. */
+char *program_name;
+
+char *xmalloc (), *xrealloc ();
+void free ();
+
+void add_to_map (), delete_from_map ();
+int insert_in_map ();
+void print_descr ();
+char *concat ();
+void scan ();
+void extract_members ();
+void extract_member ();
+void print_contents ();
+void write_symdef_member ();
+void read_old_symdefs ();
+void two_operations ();
+void usage (), fatal (), error (), error_with_file ();
+void perror_with_name (), pfatal_with_name ();
+void write_archive ();
+void touch_symdef_member ();
+void update_symdefs ();
+void delete_members (), move_members (), replace_members ();
+void quick_append ();
+char *basename ();
+
+/* Output BYTES of data at BUF to the descriptor DESC.
+ FILE is the name of the file (for error messages). */
+
+void
+mywrite (desc, buf, bytes, file)
+ int desc;
+ char *buf;
+ int bytes;
+ char *file;
+{
+ register int val;
+
+ while (bytes > 0)
+ {
+ val = write (desc, buf, bytes);
+ if (val <= 0)
+ perror_with_name (file);
+ buf += val;
+ bytes -= val;
+ }
+}
+
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ int i;
+
+ operation = 0;
+ verbose = 0;
+ newer_only = 0;
+ silent_create = 0;
+ posname = 0;
+ postype = POS_DEFAULT;
+ preserve_dates = 0;
+ symdef_flag = 0;
+ symdef_exists = 0;
+ ignore_symdef = 0;
+ symdef_mapelt = 0;
+ files = 0;
+ lock_indesc = -1;
+
+ program_name = argv[0];
+
+ if (argc < 2)
+ usage ("too few command arguments", 0);
+
+ {
+ char *key = argv[1];
+ char *p = key;
+ char c;
+
+ if (*p == '-')
+ p++;
+ while (c = *p++)
+ {
+ switch (c)
+ {
+ case 'a':
+ postype = POS_AFTER;
+ break;
+
+ case 'b':
+ postype = POS_BEFORE;
+ break;
+
+ case 'c':
+ silent_create = 1;
+ break;
+
+ case 'd':
+ if (operation)
+ two_operations ();
+
+ operation = DELETE;
+ break;
+
+ case 'i':
+ postype = POS_BEFORE;
+ break;
+
+ case 'l':
+ break;
+
+ case 'm':
+ if (operation)
+ two_operations ();
+ operation = MOVE;
+ break;
+
+ case 'o':
+ preserve_dates = 1;
+ break;
+
+ case 'p':
+ if (operation)
+ two_operations ();
+ operation = PRINT_FILES;
+ break;
+
+ case 'q':
+ if (operation)
+ two_operations ();
+ operation = QUICK_APPEND;
+ break;
+
+ case 'r':
+ if (operation)
+ two_operations ();
+ operation = REPLACE;
+ break;
+
+ case 's':
+ symdef_flag = 1;
+ break;
+
+ case 't':
+ if (operation)
+ two_operations ();
+ operation = PRINT_TABLE;
+ break;
+
+ case 'u':
+ operation = REPLACE;
+ newer_only = 1;
+ break;
+
+ case 'v':
+ verbose = 1;
+ break;
+
+ case 'x':
+ if (operation)
+ two_operations ();
+ operation = EXTRACT;
+ break;
+ }
+ }
+
+ }
+
+ if (operation == 0 && symdef_flag)
+ operation = REPLACE;
+
+ if (operation == 0)
+ usage ("no operation specified", 0);
+
+ i = 2;
+
+ if (postype != POS_DEFAULT)
+ if (i < argc)
+ posname = argv[i++];
+ else
+ usage ("no position operand", 0);
+
+ if (i >= argc)
+ usage ("no archive specified", 0);
+ archive = argv[i++];
+
+ if (i < argc)
+ {
+ files = &argv[i];
+ while (i < argc)
+ if (!strcmp (argv[i++], "__.SYMDEF"))
+ {
+ ignore_symdef = 1;
+ break;
+ }
+ }
+
+ switch (operation)
+ {
+ case EXTRACT:
+ extract_members (extract_member);
+ break;
+
+ case PRINT_TABLE:
+ extract_members (print_descr);
+ break;
+
+ case PRINT_FILES:
+ extract_members (print_contents);
+ break;
+
+ case DELETE:
+ if (files != 0)
+ delete_members ();
+ break;
+
+ case MOVE:
+ if (files != 0)
+ move_members ();
+ break;
+
+ case REPLACE:
+ if (files != 0 || symdef_flag)
+ replace_members ();
+ break;
+
+ case QUICK_APPEND:
+ if (files != 0)
+ quick_append ();
+ break;
+
+ default:
+ usage ("invalid operation %d", operation);
+ }
+
+ exit (0);
+}
+
+void
+two_operations ()
+{
+ usage ("two different operation switches specified", 0);
+}
+
+void
+scan (function, crflag)
+ void (*function) ();
+ int crflag;
+{
+ FILE *arcstream = fopen (archive, "r");
+
+ if (arcstream == 0 && crflag)
+ /* Creation-warning, if desired, will happen later. */
+ return;
+
+ if (arcstream == 0)
+ {
+ perror_with_name (archive);
+ exit (1);
+ }
+ {
+ char buf[SARMAG];
+ int nread = fread (buf, 1, SARMAG, arcstream);
+ if (nread != SARMAG || bcmp (buf, ARMAG, SARMAG))
+ fatal ("file %s not a valid archive", archive);
+ }
+
+ /* Now find the members one by one. */
+ {
+ int member_offset = SARMAG;
+ while (1)
+ {
+ int nread;
+ struct ar_hdr member_header;
+ struct member_desc member_desc;
+ char name [1 + sizeof member_header.ar_name];
+
+ if (fseek (arcstream, member_offset, 0) < 0)
+ perror_with_name (archive);
+
+ nread = fread (&member_header, 1, sizeof (struct ar_hdr), arcstream);
+ if (nread == 0)
+ /* No data left means end of file; that is OK. */
+ break;
+
+ if (nread != sizeof (member_header)
+ || bcmp (member_header.ar_fmag, ARFMAG, 2))
+ fatal ("file %s not a valid archive", archive);
+ bcopy (member_header.ar_name, name, sizeof member_header.ar_name);
+ {
+ char *p = name + sizeof member_header.ar_name;
+ *p = '\0';
+ while (p > name && *--p == ' ')
+ *p = '\0';
+#if defined(USG) || defined(HAVE_TRAILING_SLASH_IN_NAME)
+ if (*p == '/') /* Since V.2, names are terminated with '/' */
+ *p = '\0';
+#endif
+ }
+ member_desc.name = name;
+ sscanf (member_header.ar_mode, "%o", &member_desc.mode);
+ member_desc.date = atoi (member_header.ar_date);
+ member_desc.size = atoi (member_header.ar_size);
+ member_desc.uid = atoi (member_header.ar_uid);
+ member_desc.gid = atoi (member_header.ar_gid);
+ member_desc.offset = member_offset;
+ member_desc.data_offset = member_offset + sizeof (member_header);
+
+ member_desc.new_offset = 0;
+ member_desc.symdefs = 0;
+ member_desc.nsymdefs = 0;
+ member_desc.string_size = 0;
+
+ if (!ignore_symdef && !strcmp (name, "__.SYMDEF"))
+ symdef_exists = 1;
+
+ function (member_desc, arcstream);
+
+ member_offset += sizeof (member_header) + member_desc.size;
+ if (member_offset & 1)
+ ++member_offset;
+ }
+ }
+
+
+ fclose (arcstream);
+}
+
+void print_modes ();
+
+void
+print_descr (member)
+ struct member_desc member;
+{
+ char *timestring;
+ if (!verbose)
+ {
+ puts (member.name);
+ return;
+ }
+ print_modes (member.mode);
+ timestring = ctime (&member.date);
+ printf (" %2d/%2d %6d %12.12s %4.4s %s\n",
+ member.uid, member.gid,
+ member.size, timestring + 4, timestring + 20,
+ member.name);
+}
+
+void
+print_modes (modes)
+ int modes;
+{
+ putchar (modes & 0400 ? 'r' : '-');
+ putchar (modes & 0200 ? 'w' : '-');
+ putchar (modes & 0100 ? 'x' : '-');
+ putchar (modes & 040 ? 'r' : '-');
+ putchar (modes & 020 ? 'w' : '-');
+ putchar (modes & 010 ? 'x' : '-');
+ putchar (modes & 04 ? 'r' : '-');
+ putchar (modes & 02 ? 'w' : '-');
+ putchar (modes & 01 ? 'x' : '-');
+}
+
+#define BUFSIZE 1024
+
+void
+extract_member (member, istream)
+ struct member_desc member;
+ FILE *istream;
+{
+ int ncopied = 0;
+ FILE *ostream;
+
+ fseek (istream, member.data_offset, 0);
+ ostream = fopen (member.name, "w");
+ if (!ostream)
+ {
+ perror_with_name (member.name);
+ return;
+ }
+
+ if (verbose)
+ printf ("x - %s\n", member.name);
+
+ while (ncopied < member.size)
+ {
+ char buf [BUFSIZE];
+ int tocopy = member.size - ncopied;
+ int nread;
+ if (tocopy > BUFSIZE) tocopy = BUFSIZE;
+ nread = fread (buf, 1, tocopy, istream);
+ if (nread != tocopy)
+ fatal ("error reading archive %s", archive);
+ fwrite (buf, 1, nread, ostream);
+ ncopied += tocopy;
+ }
+
+#ifdef HAVE_FCHMOD
+ fchmod (fileno (ostream), member.mode);
+#else
+ chmod (member.name, member.mode);
+#endif
+ if (ferror (ostream) || fclose (ostream) != 0)
+ error ("%s: I/O error", member.name);
+
+ if (preserve_dates)
+ {
+#if defined(USG) || defined(linux) || defined(__BCC__)
+ long tv[2];
+ tv[0] = member.date;
+ tv[1] = member.date;
+ utime (member.name, tv);
+#else
+ struct timeval tv[2];
+ tv[0].tv_sec = member.date;
+ tv[0].tv_usec = 0;
+ tv[1].tv_sec = member.date;
+ tv[1].tv_usec = 0;
+ utimes (member.name, tv);
+#endif
+ }
+}
+
+void
+print_contents (member, istream)
+ struct member_desc member;
+ FILE *istream;
+{
+ int ncopied = 0;
+
+ fseek (istream, member.data_offset, 0);
+
+ if (verbose)
+ printf ("\n<member %s>\n\n", member.name);
+
+ while (ncopied < member.size)
+ {
+ char buf [BUFSIZE];
+ int tocopy = member.size - ncopied;
+ int nread;
+ if (tocopy > BUFSIZE) tocopy = BUFSIZE;
+ nread = fread (buf, 1, tocopy, istream);
+ if (nread != tocopy)
+ fatal ("file %s not a valid archive", archive);
+ fwrite (buf, 1, nread, stdout);
+ ncopied += tocopy;
+ }
+}
+
+/* Make a map of the existing members of the archive: their names,
+ positions and sizes. */
+
+/* If `nonexistent_ok' is nonzero,
+ just return 0 for an archive that does not exist.
+ This will cause the ordinary supersede procedure to
+ create a new archive. */
+
+struct mapelt *
+make_map (nonexistent_ok)
+ int nonexistent_ok;
+{
+ struct mapelt mapstart;
+ mapstart.next = 0;
+ maplast = &mapstart;
+ scan (add_to_map, nonexistent_ok);
+ return mapstart.next;
+}
+
+void
+add_to_map (member)
+ struct member_desc member;
+{
+ struct mapelt *mapelt = (struct mapelt *) xmalloc (sizeof (struct mapelt));
+ mapelt->info = member;
+ mapelt->info.name = concat (mapelt->info.name, "", "");
+ maplast->next = mapelt;
+ mapelt->next = 0;
+ maplast = mapelt;
+}
+
+/* Return the last element of the specified map. */
+
+struct mapelt *
+last_mapelt (map)
+ struct mapelt *map;
+{
+ struct mapelt *tail = map;
+ while (tail->next) tail = tail->next;
+ return tail;
+}
+
+/* Return the element of the specified map which precedes elt. */
+
+struct mapelt *
+prev_mapelt (map, elt)
+ struct mapelt *map, *elt;
+{
+ struct mapelt *tail = map;
+ while (tail->next && tail->next != elt)
+ tail = tail->next;
+ if (tail->next) return tail;
+ return 0;
+}
+
+/* Return the element of the specified map which has the specified name. */
+
+struct mapelt *
+find_mapelt_noerror (map, name)
+ struct mapelt *map;
+ register char *name;
+{
+ register struct mapelt *tail;
+ unsigned int len;
+ int dot_o;
+
+ name = basename (name);
+ len = strlen (name);
+ dot_o = name[len - 2] == '.' && name[len - 1] == 'o';
+
+ for (tail = map; tail != 0; tail = tail->next)
+ {
+ if (tail->info.name == 0)
+ continue;
+ if (!strncmp (tail->info.name, name, 13))
+ {
+ unsigned int eltlen = strlen (tail->info.name);
+ if (len <= 13 || eltlen <= 13)
+ return tail;
+ else
+ {
+ char *p = tail->info.name + 13;
+ if (dot_o && p[0] == '.' && p[1] == 'o' && p[2] == '\0')
+ return tail;
+ else if (!strncmp (p, name + 13,
+ (len > eltlen ? len : eltlen) - 13))
+ return tail;
+ }
+ }
+ }
+
+ return 0;
+}
+
+struct mapelt *
+find_mapelt (map, name)
+ struct mapelt *map;
+ char *name;
+{
+ register struct mapelt *found = find_mapelt_noerror (map, name);
+ if (found == 0)
+ error ("no member named `%s'", name);
+ return found;
+}
+
+/* Before looking at the archive, if we are going to update it
+ based on looking at its current contents, make an exclusive lock on it.
+ The lock is released when `write_archive' is called. */
+
+void
+lock_for_update ()
+{
+ /* Open the existing archive file; if that fails, create an empty one. */
+
+ lock_indesc = open (archive, O_RDWR, 0);
+
+ if (lock_indesc < 0)
+ {
+ int outdesc;
+
+ if (!silent_create)
+ printf ("Creating archive file `%s'\n", archive);
+ outdesc = open (archive, O_WRONLY | O_APPEND | O_CREAT, 0666);
+ if (outdesc < 0)
+ pfatal_with_name (archive);
+ mywrite (outdesc, ARMAG, SARMAG, archive);
+ close (outdesc);
+
+ /* Now we had better be able to open for update! */
+
+ lock_indesc = open (archive, O_RDWR, 0);
+ if (lock_indesc < 0)
+ {
+ unlink (archive);
+ pfatal_with_name (archive);
+ }
+ }
+
+#ifdef LOCKS
+ /* Lock the old file so that it won't be updated by two programs at once.
+ This uses the fcntl locking facility found on Sun systems
+ which is also in POSIX. (Perhaps it comes from sysV.)
+
+ Note that merely reading an archive does not require a lock,
+ because we use `rename' to update the whole file atomically. */
+
+ {
+ struct flock lock;
+
+ lock.l_type = F_WRLCK;
+ lock.l_whence = 0;
+ lock.l_start = 0;
+ lock.l_len = 0;
+
+ while (1)
+ {
+ int value = fcntl (lock_indesc, F_SETLKW, &lock);
+ if (value >= 0)
+ break;
+ else if (errno == EINTR)
+ continue;
+ else
+ pfatal_with_name ("locking archive");
+ }
+ }
+#endif
+}
+
+/* Unlock archive and close the file descriptor. */
+
+void
+close_archive ()
+{
+#ifdef LOCKS
+ {
+ struct flock lock;
+
+ /* Unlock the old archive. */
+
+ lock.l_type = F_UNLCK;
+ lock.l_whence = 0;
+ lock.l_start = 0;
+ lock.l_len = 0;
+
+ fcntl (lock_indesc, F_SETLK, &lock);
+ }
+#endif
+
+ /* Close the archive. If we renamed a new one, the old one disappears. */
+ close (lock_indesc);
+}
+
+/* Write a new archive file from a given map. */
+/* When a map is used as the pattern for a new archive,
+ each element represents one member to put in it, and
+ the order of elements controls the order of writing.
+
+ Ordinarily, the element describes a member of the old
+ archive, to be copied into the new one.
+
+ If the `offset' field of the element's info is 0,
+ then the element describes a file to be copied into the
+ new archive. The `name' field is the file's name.
+
+ If the `name' field of an element is 0, the element is ignored.
+ This makes it easy to specify deletion of archive members.
+
+ Every operation that will eventually call `write_archive'
+ should call `lock_for_update' before beginning
+ to do any I/O on the archive file.
+*/
+
+char *make_tempname ();
+void copy_out_member ();
+
+void
+write_archive (map, appendflag)
+ struct mapelt *map;
+ int appendflag;
+{
+ char *tempname = make_tempname (archive);
+ int indesc = lock_indesc;
+ int outdesc;
+ char *outname;
+ struct mapelt *tail;
+
+ /* Now open the output. */
+
+ if (!appendflag)
+ {
+ /* Updating an existing archive normally.
+ Write output as TEMPNAME and rename at the end.
+ There can never be two invocations trying to do this at once,
+ because of the lock made on the old archive file. */
+
+ outdesc = open (tempname, O_WRONLY | O_CREAT, 0666);
+ if (outdesc < 0)
+ pfatal_with_name (tempname);
+ outname = tempname;
+ mywrite (outdesc, ARMAG, SARMAG, outname);
+ }
+ else
+ {
+ /* Fast-append to existing archive. */
+
+ outdesc = open (archive, O_WRONLY | O_APPEND, 0);
+ if (outdesc < 0)
+ pfatal_with_name (archive);
+ outname = archive;
+ }
+
+ /* If archive has or should have a __.SYMDEF member,
+ compute the contents for it. */
+
+ if (symdef_flag || symdef_exists)
+ {
+ if (symdef_exists)
+ read_old_symdefs (map, indesc);
+ else
+ {
+ struct mapelt *this = (struct mapelt *)
+ xmalloc (sizeof (struct mapelt));
+ this->info.name = "__.SYMDEF";
+ this->info.offset = SARMAG;
+ this->info.data_offset = SARMAG + sizeof (struct ar_hdr);
+ this->info.new_offset = 0;
+ this->info.date = 0;
+ this->info.size = 0;
+ this->info.uid = 0;
+ this->info.gid = 0;
+ this->info.mode = 0666;
+ this->info.symdefs = 0;
+ this->info.nsymdefs = 0;
+ this->info.string_size = 0;
+ this->next = map;
+ map = this;
+ original_num_symdefs = 0;
+ old_strings_size = 0;
+ }
+
+ update_symdefs (map, indesc);
+ }
+
+ /* Copy the members into the output, either from the old archive
+ or from specified files. */
+
+ for (tail = map; tail != 0; tail = tail->next)
+ {
+ if ((symdef_flag || symdef_exists) && tail->info.name
+ && !strcmp (tail->info.name, "__.SYMDEF")
+#if 0
+ && tail->info.date==0
+#endif
+ )
+ write_symdef_member (tail, map, outdesc, outname);
+ else
+ copy_out_member (tail, indesc, outdesc, outname);
+ }
+
+ if (symdef_mapelt != 0)
+ {
+ /* Check for members whose data offsets weren't
+ known when the symdef member was first written. */
+ int doneany = 0;
+ for (tail = map; tail != 0; tail = tail->next)
+ if (tail->info.offset == 0)
+ {
+ /* Fix up the symdefs. */
+ register unsigned int i;
+ for (i = 0; i < tail->info.nsymdefs; ++i)
+ tail->info.symdefs[i].offset = tail->info.new_offset;
+ doneany = 1;
+ }
+ if (doneany)
+ {
+ /* Some files had bad symdefs; rewrite the symdef member. */
+ lseek (outdesc, symdef_mapelt->info.offset, 0);
+ write_symdef_member (symdef_mapelt, map, outdesc, outname);
+ }
+ }
+
+ /* Mark the __.SYMDEF member as up to date. */
+
+ if (symdef_mapelt != 0)
+ touch_symdef_member (outdesc, outname);
+
+ /* Install the new output under the intended name. */
+
+#ifdef HAVE_FSYNC
+ fsync (outdesc);
+#endif
+ close (outdesc);
+
+ if (!appendflag)
+ if (rename (tempname, archive))
+ pfatal_with_name (tempname);
+
+ close_archive ();
+}
+
+void
+header_from_map (header, mapelt)
+ struct ar_hdr *header;
+ struct mapelt *mapelt;
+{
+ unsigned int namelen;
+ char *p;
+
+ /* Zero the header, then store in the data as text. */
+ bzero ((char *) header, sizeof (*header));
+
+ p = basename (mapelt->info.name);
+ strncpy (header->ar_name, p, sizeof (header->ar_name));
+ namelen = strlen (p);
+ if (namelen >= sizeof (header->ar_name))
+ {
+ if (mapelt->info.name[namelen - 2] == '.' &&
+ mapelt->info.name[namelen - 1] == 'o')
+ {
+ header->ar_name[sizeof (header->ar_name) - 3] = '.';
+ header->ar_name[sizeof (header->ar_name) - 2] = 'o';
+ }
+ header->ar_name[sizeof (header->ar_name) - 1] = '\0';
+ error ("member name `%s' truncated to `%s'",
+ mapelt->info.name, header->ar_name);
+ }
+#if defined(USG) || defined(HAVE_TRAILING_SLASH_IN_NAME)
+ {
+ /* System V tacks a trailing '/' onto the end of the name */
+ char *p = header->ar_name;
+ char *end = p + sizeof (header->ar_name);
+
+ while (p < end && *p)
+ p++;
+ *p = '/';
+ }
+#endif
+
+ sprintf (header->ar_date, "%ld", mapelt->info.date);
+ sprintf (header->ar_size, "%d", mapelt->info.size);
+ sprintf (header->ar_uid, "%d", mapelt->info.uid);
+ sprintf (header->ar_gid, "%d", mapelt->info.gid);
+ sprintf (header->ar_mode, "%o", mapelt->info.mode);
+ strncpy (header->ar_fmag, ARFMAG, sizeof (header->ar_fmag));
+
+ /* Change all remaining nulls in the header into spaces. */
+ {
+ char *end = (char *) &header[1];
+ register char *p;
+ for (p = (char *) header; p < end; ++p)
+ if (*p == '\0')
+ *p = ' ';
+ }
+}
+
+/* gets just the file part of name */
+
+char *
+basename (path)
+ char *path;
+{
+ char *save, *start;
+ for (start = save = path; *path; path++)
+ if (*path == '/')
+ save = path + 1;
+
+ if (save != start)
+ return save;
+ else
+ return start;
+}
+
+/* writes to file open on OUTDESC with name OUTNAME. */
+void
+copy_out_member (mapelt, archive_indesc, outdesc, outname)
+ struct mapelt *mapelt;
+ int archive_indesc;
+ int outdesc;
+ char *outname;
+{
+ struct ar_hdr header;
+ int indesc;
+
+ if (mapelt->info.name == 0)
+ /* This element was cancelled. */
+ return;
+
+ header_from_map (&header, mapelt);
+
+ if (mapelt->info.offset != 0)
+ {
+ indesc = archive_indesc;
+ lseek (indesc, mapelt->info.data_offset, 0);
+ }
+ else
+ {
+ indesc = open (mapelt->info.name, 0, 0);
+ if (indesc < 0)
+ {
+ perror_with_name (mapelt->info.name);
+ return;
+ }
+ }
+
+ mywrite (outdesc, &header, sizeof (header), outname);
+
+ if (mapelt->info.data_offset == 0)
+ mapelt->info.data_offset = lseek (outdesc, 0L, 1);
+
+ {
+ char buf[BUFSIZE];
+ int tocopy = mapelt->info.size;
+ while (tocopy > 0)
+ {
+ int thistime = tocopy;
+ if (thistime > BUFSIZE) thistime = BUFSIZE;
+ read (indesc, buf, thistime);
+ mywrite (outdesc, buf, thistime, outname);
+ tocopy -= thistime;
+ }
+ }
+
+ if (indesc != archive_indesc)
+ close (indesc);
+
+ if (mapelt->info.size & 1)
+ mywrite (outdesc, "\n", 1, outname);
+}
+
+/* Update the time of the __.SYMDEF member; done when we updated
+ that member, just before we close the new archive file.
+ It is open on OUTDESC and its name is OUTNAME. */
+
+void
+touch_symdef_member (outdesc, outname)
+ int outdesc;
+ char *outname;
+{
+ struct stat statbuf;
+ int i;
+
+ /* See what mtime the archive file has as a result of our writing it. */
+ fstat (outdesc, &statbuf);
+
+ /* Advance member's time to that time. */
+ bzero (symdef_header.ar_date, sizeof symdef_header.ar_date);
+ sprintf (symdef_header.ar_date, "%ld", statbuf.st_mtime);
+ for (i = 0; i < sizeof symdef_header.ar_date; i++)
+ if (symdef_header.ar_date[i] == 0)
+ symdef_header.ar_date[i] = ' ';
+
+ /* Write back this member's header with the new time. */
+ if (lseek (outdesc, symdef_mapelt->info.new_offset, 0) >= 0)
+ mywrite (outdesc, &symdef_header, sizeof symdef_header, outname);
+}
+
+char *
+make_tempname (name)
+ char *name;
+{
+#if defined(USG) || defined(SHORT_FILENAME)
+ /* sigh. 14 character filenames are *wonderful*, just *wonderful*. */
+ char *p = basename (name);
+ char *q, *r;
+
+ if (p != name)
+ {
+ q = concat (name, "", ""); /* get a fresh copy */
+ r = basename (q); /* r points just after last '/' */
+ *--r = '\0';
+ return concat (q, "/t_", p);
+ }
+ else if (strlen (name) >= 14)
+ return concat ("t_", name, "");
+ else
+#endif
+ return concat (name, "", "_supersede");
+}
+
+void
+delete_members ()
+{
+ struct mapelt *map = make_map (0);
+ struct mapelt mapstart;
+ char **p;
+
+ mapstart.info.name = 0;
+ mapstart.next = map;
+ map = &mapstart;
+
+ lock_for_update ();
+
+ if (files)
+ for (p = files; *p; p++)
+ {
+ /* If user says to delete the __.SYMDEF member,
+ don't make a new one to replace it. */
+ if (!strcmp (*p, "__.SYMDEF"))
+ symdef_exists = 0;
+ delete_from_map (*p, map);
+ }
+
+ write_archive (map->next, 0);
+}
+
+void
+delete_from_map (name, map)
+ char *name;
+ struct mapelt *map;
+{
+ struct mapelt *this = find_mapelt (map, name);
+
+ if (!this) return;
+ this->info.name = 0;
+ if (verbose)
+ printf ("d - %s\n", name);
+}
+
+void
+move_members ()
+{
+ struct mapelt *map = make_map (0);
+ char **p;
+ struct mapelt *after_mapelt;
+ struct mapelt mapstart;
+ struct mapelt *change_map;
+
+ mapstart.info.name = 0;
+ mapstart.next = map;
+ change_map = &mapstart;
+
+ lock_for_update ();
+
+ switch (postype)
+ {
+ case POS_DEFAULT:
+ after_mapelt = last_mapelt (change_map);
+ break;
+
+ case POS_AFTER:
+ after_mapelt = find_mapelt (map, posname);
+ break;
+
+ case POS_BEFORE:
+ after_mapelt = prev_mapelt (change_map, find_mapelt (map, posname));
+ }
+
+ /* Failure to find specified "before" or "after" member
+ is a fatal error; message has already been printed. */
+
+ if (!after_mapelt) exit (1);
+
+ if (files)
+ for (p = files; *p; p++)
+ {
+ if (move_in_map (*p, change_map, after_mapelt))
+ after_mapelt = after_mapelt->next;
+ }
+
+ write_archive (map, 0);
+}
+
+int
+move_in_map (name, map, after)
+ char *name;
+ struct mapelt *map, *after;
+{
+ struct mapelt *this = find_mapelt (map, name);
+ struct mapelt *prev;
+
+ if (!this) return 0;
+ prev = prev_mapelt (map, this);
+ prev->next = this->next;
+ this->next = after->next;
+ after->next = this;
+ return 1;
+}
+
+/* Insert files into the archive. */
+
+void
+replace_members ()
+{
+ struct mapelt *map = make_map (1);
+ struct mapelt mapstart;
+ struct mapelt *after_mapelt;
+ struct mapelt *change_map;
+ char **p;
+ int changed;
+
+ mapstart.info.name = 0;
+ mapstart.next = map;
+ change_map = &mapstart;
+
+ lock_for_update ();
+
+ switch (postype)
+ {
+ case POS_DEFAULT:
+ after_mapelt = last_mapelt (change_map);
+ break;
+
+ case POS_AFTER:
+ after_mapelt = find_mapelt (map, posname);
+ break;
+
+ case POS_BEFORE:
+ after_mapelt = prev_mapelt (change_map, find_mapelt (map, posname));
+ }
+
+ /* Failure to find specified "before" or "after" member
+ is a fatal error; the message has already been printed. */
+ if (after_mapelt == 0)
+ exit (1);
+
+ changed = 0;
+ if (files != 0)
+ for (p = files; *p != 0; ++p)
+ if (insert_in_map (*p, change_map, after_mapelt))
+ {
+ after_mapelt = after_mapelt->next;
+ changed = 1;
+ }
+
+ change_map = change_map->next;
+ if (!changed && (!symdef_flag || symdef_exists))
+ /* Nothing changed. */
+ close_archive (change_map);
+ else
+ write_archive (change_map, 0);
+}
+
+/* Handle the "quick insert" operation. */
+
+void
+quick_append ()
+{
+ struct mapelt *map;
+ struct mapelt *after;
+ struct mapelt mapstart;
+ char **p;
+
+ mapstart.info.name = 0;
+ mapstart.next = 0;
+ map = &mapstart;
+ after = map;
+
+ lock_for_update ();
+
+ /* Insert the specified files into the "map",
+ but is a map of the inserted files only,
+ and starts out empty. */
+ if (files)
+ for (p = files; *p; p++)
+ {
+ if (insert_in_map (*p, map, after))
+ after = after->next;
+ }
+
+ /* Append these files to the end of the existing archive file. */
+
+ write_archive (map->next, 1);
+}
+
+/* Insert an entry for name NAME into the map MAP after the map entry AFTER.
+ Delete an old entry for NAME.
+ MAP is assumed to start with a dummy entry, which facilitates
+ insertion at the beginning of the list.
+ Return 1 if successful, 0 if did nothing because file NAME doesn't
+ exist or (optionally) is older. */
+
+int
+insert_in_map (name, map, after)
+ char *name;
+ struct mapelt *map, *after;
+{
+ struct mapelt *old = find_mapelt_noerror (map, name);
+ struct mapelt *this;
+ struct stat status;
+
+ if (stat (name, &status))
+ {
+ perror_with_name (name);
+ return 0;
+ }
+ if (old && newer_only && status.st_mtime <= old->info.date)
+ return 0;
+ if (old)
+ /* Delete the old one. */
+ old->info.name = 0;
+ this = (struct mapelt *) xmalloc (sizeof (struct mapelt));
+ this->info.name = name;
+ this->info.offset = 0;
+ this->info.data_offset = 0;
+ this->info.date = status.st_mtime;
+ this->info.size = status.st_size;
+ this->info.uid = status.st_uid;
+ this->info.gid = status.st_gid;
+ this->info.mode = status.st_mode;
+ /* Always place a __.SYMDEF member first in the archive, regardless
+ of any position specifications. */
+ if (! strcmp (name, "__.SYMDEF"))
+ this->next = map->next, map->next = this;
+ else
+ this->next = after->next, after->next = this;
+
+ if (verbose)
+ printf ("%c - %s\n", old == 0 ? 'a' : 'r', this->info.name);
+
+ return 1;
+}
+
+/* Apply a function to each of the specified members.
+*/
+
+void
+extract_members (function)
+ void (*function) ();
+{
+ struct mapelt *map;
+ FILE *arcstream;
+ char **p;
+
+ if (!files)
+ {
+ /* Handle case where we want to operate on every member.
+ No need to make a map and search it for this. */
+ scan (function, 0);
+ return;
+ }
+
+ arcstream = fopen (archive, "r");
+ if (!arcstream)
+ fatal ("failure opening archive %s for the second time", archive);
+ map = make_map (0);
+
+ for (p = files; *p; p++)
+ {
+ struct mapelt *this = find_mapelt (map, *p);
+ if (!this) continue;
+ function (this->info, arcstream);
+ }
+
+ fclose (arcstream);
+}
+
+
+/* Write the __.SYMDEF member from data in core. OUTDESC and OUTNAME
+ are descriptor and name of file to write to. */
+
+void
+write_symdef_member (mapelt, map, outdesc, outname)
+ struct mapelt *mapelt;
+ struct mapelt *map;
+ int outdesc;
+ char *outname;
+{
+ struct ar_hdr header;
+ struct mapelt *mapptr;
+ unsigned long int symdefs_size;
+
+ if (mapelt->info.name == 0)
+ /* This element was cancelled. */
+ return;
+
+ header_from_map (&header, mapelt);
+
+ bcopy (&header, &symdef_header, sizeof header);
+
+ mywrite (outdesc, &header, sizeof (header), outname);
+
+ /* Write the number of symdefs. */
+ symdefs_size = nsymdefs * sizeof (struct symdef);
+#ifdef HOST_TARGET_ENDIANESS_DIFFERS
+ md_number_to_chars (symdefs_size, sizeof symdefs_size,
+ (unsigned char *) &symdefs_size);
+#endif
+ mywrite (outdesc, &symdefs_size, sizeof symdefs_size, outname);
+
+ /* Write symdefs surviving from old archive. */
+#ifdef HOST_TARGET_ENDIANESS_DIFFERS
+ md_symdefs_to_chars ((struct md_symdef *) old_symdefs, num_old_symdefs,
+ (unsigned char *) old_symdefs);
+#endif
+ mywrite (outdesc, old_symdefs, num_old_symdefs * sizeof (struct symdef),
+ outname);
+#ifdef HOST_TARGET_ENDIANESS_DIFFERS
+ md_chars_to_symdefs ((unsigned char *) old_symdefs,
+ (struct md_symdef *) old_symdefs, num_old_symdefs);
+#endif
+
+ /* Write symdefs for new members. */
+ for (mapptr = map; mapptr != 0; mapptr = mapptr->next)
+ if (mapptr->info.nsymdefs != 0)
+ {
+#ifdef HOST_TARGET_ENDIANESS_DIFFERS
+ md_symdefs_to_chars ((struct md_symdef *) mapptr->info.symdefs,
+ mapptr->info.nsymdefs,
+ (unsigned char *) mapptr->info.symdefs);
+#endif
+ write (outdesc, mapptr->info.symdefs,
+ mapptr->info.nsymdefs * sizeof (struct symdef));
+#ifdef HOST_TARGET_ENDIANESS_DIFFERS
+ md_chars_to_symdefs ((unsigned char *) mapptr->info.symdefs,
+ (struct md_symdef *) mapptr->info.symdefs,
+ mapptr->info.nsymdefs);
+#endif
+ }
+
+ /* Write the string table size. */
+#ifdef HOST_TARGET_ENDIANESS_DIFFERS
+ md_number_to_chars (new_strings_size, sizeof new_strings_size,
+ (unsigned char *) &new_strings_size);
+#endif
+ mywrite (outdesc, &new_strings_size, sizeof new_strings_size, outname);
+#ifdef HOST_TARGET_ENDIANESS_DIFFERS
+ new_strings_size = md_chars_to_number ((unsigned char *) &new_strings_size,
+ sizeof new_strings_size);
+#endif
+
+ /* Write the string table. */
+ mywrite (outdesc, new_strings, new_strings_size, outname);
+
+ if (mapelt->info.size & 1)
+ mywrite (outdesc, "", 1, outname);
+}
+
+void
+read_old_symdefs (map, archive_indesc)
+ struct mapelt *map;
+ int archive_indesc;
+{
+ struct mapelt *mapelt;
+ char *data;
+ int val;
+ int symdefs_size;
+
+ mapelt = find_mapelt_noerror (map, "__.SYMDEF");
+ if (!mapelt)
+ abort (); /* Only call here if an old one exists */
+
+ data = (char *) xmalloc (mapelt->info.size);
+ lseek (archive_indesc, mapelt->info.data_offset, 0);
+ val = read (archive_indesc, data, mapelt->info.size);
+
+#ifdef HOST_TARGET_ENDIANESS_DIFFERS
+ symdefs_size = md_chars_to_number ((unsigned char *) data,
+ sizeof symdefs_size);
+#else
+ symdefs_size = *(unsigned long int *) data;
+#endif
+ original_num_symdefs = symdefs_size / sizeof (struct symdef);
+ old_symdefs = (struct symdef *) (data + sizeof (symdefs_size));
+#ifdef HOST_TARGET_ENDIANESS_DIFFERS
+ md_chars_to_symdefs ((unsigned char *) old_symdefs,
+ (struct md_symdef *) old_symdefs, original_num_symdefs);
+#endif
+ old_strings = ((char *) (old_symdefs + original_num_symdefs)
+ + sizeof (symdefs_size));
+#ifdef HOST_TARGET_ENDIANESS_DIFFERS
+ old_strings_size
+ = md_chars_to_number ((unsigned char *) (old_symdefs
+ + original_num_symdefs),
+ sizeof old_strings_size);
+#else
+ old_strings_size
+ = *(unsigned long int *) (old_symdefs + original_num_symdefs);
+#endif
+}
+
+/* Read various information from the header of an object file.
+ Return 0 for failure or 1 for success. */
+
+int
+read_header_info (mapelt, desc, offset, syms_offset, syms_size, strs_offset, strs_size)
+ struct mapelt *mapelt;
+ int desc;
+ long int offset;
+ long int *syms_offset;
+ unsigned int *syms_size;
+ long int *strs_offset;
+ unsigned int *strs_size;
+{
+ struct exec hdr;
+ int len;
+
+ lseek (desc, offset, 0);
+#ifdef HEADER_SEEK_FD
+ HEADER_SEEK_FD (desc);
+#endif
+
+ len = read (desc, (char *) &hdr, sizeof hdr);
+#ifdef HOST_TARGET_ENDIANESS_DIFFERS
+ md_chars_to_hdr ((unsigned char *) &hdr, &hdr);
+#endif
+ if (len == sizeof hdr && !N_BADMAG(hdr))
+ {
+ *syms_offset = N_SYMOFF (hdr);
+ *syms_size = hdr.a_syms;
+ *strs_offset = N_STROFF (hdr);
+ lseek (desc, N_STROFF (hdr) + offset, 0);
+ if (read (desc, (char *) strs_size, sizeof *strs_size) != sizeof *strs_size)
+ {
+ error_with_file ("failure reading string table size in ", mapelt);
+ return 0;
+ }
+#ifdef HOST_TARGET_ENDIANESS_DIFFERS
+ *strs_size = md_chars_to_number ((unsigned char *) strs_size,
+ sizeof *strs_size);
+#endif
+ return 1;
+ }
+
+ error_with_file ("bad format (not an object file) in ", mapelt);
+ return 0;
+}
+
+/* Create the info.symdefs for a new member
+ by reading the file it is coming from. */
+
+void
+make_new_symdefs (mapelt, archive_indesc)
+ struct mapelt *mapelt;
+ int archive_indesc;
+{
+ int indesc;
+ char *name = mapelt->info.name;
+ long int syms_offset, strs_offset;
+ unsigned int syms_size, strs_size;
+ struct nlist *symbols;
+ int symcount;
+ char *strings;
+ register unsigned int i;
+ unsigned long int offset;
+
+ if (name == 0)
+ /* Deleted member. */
+ abort ();
+
+ if (mapelt->info.offset != 0)
+ {
+ indesc = archive_indesc;
+ lseek (indesc, mapelt->info.data_offset, 0);
+ offset = mapelt->info.data_offset;
+ }
+ else
+ {
+ indesc = open (mapelt->info.name, 0, 0);
+ if (indesc < 0)
+ {
+ perror_with_name (mapelt->info.name);
+ return;
+ }
+ offset = 0;
+ }
+
+ if (!read_header_info (mapelt, indesc, offset, &syms_offset, &syms_size, &strs_offset, &strs_size))
+ {
+ if (mapelt->info.offset == 0)
+ close (indesc);
+ return;
+ }
+
+ /* Number of symbol entries in the file. */
+ symcount = syms_size / sizeof (struct nlist);
+ /* Allocate temporary space for the symbol entries. */
+ symbols = (struct nlist *) alloca (syms_size);
+ /* Read in the symbols. */
+ lseek (indesc, syms_offset + offset, 0);
+ if (read (indesc, (char *) symbols, syms_size) != syms_size)
+ {
+ error_with_file ("premature end of file in symbols of ", mapelt);
+ if (mapelt->info.offset == 0)
+ (void) close (indesc);
+ return;
+ }
+#ifdef HOST_TARGET_ENDIANESS_DIFFERS
+ md_chars_to_nlist ((unsigned char *) symbols, symbols, symcount);
+#endif
+
+ /* The string table size includes the size word. */
+ if (strs_size < sizeof (strs_size))
+ {
+ error_with_file ("bad string table size in ", mapelt);
+ if (mapelt->info.offset == 0)
+ (void) close (indesc);
+ return;
+ }
+ strs_size -= sizeof (strs_size);
+
+ /* Allocate permanent space for the string table. */
+ strings = (char *) xmalloc (strs_size);
+
+ /* Read in the strings. */
+ lseek (indesc, offset + strs_offset + sizeof strs_size, 0);
+ if (read (indesc, strings, strs_size) != strs_size)
+ {
+ error_with_file ("premature end of file in strings of ", mapelt);
+ if (mapelt->info.offset == 0)
+ (void) close (indesc);
+ return;
+ }
+
+ if (indesc != archive_indesc)
+ (void) close (indesc);
+
+ /* Discard the symbols we don't want to mention; compact the rest down. */
+ symcount = filter_symbols (symbols, symcount);
+
+ mapelt->info.symdefs = (struct symdef *)
+ xmalloc (symcount * sizeof (struct symdef));
+ mapelt->info.nsymdefs = symcount;
+ mapelt->info.string_size = 0;
+
+ for (i = 0; i < symcount; ++i)
+ {
+ unsigned long int stroff = symbols[i].n_un.n_strx - sizeof (strs_size);
+ char *symname = strings + stroff;
+ if (stroff > strs_size)
+ {
+ char buf[100];
+ sprintf (buf, "ridiculous string offset %lu in symbol %u of ",
+ stroff + sizeof (strs_size), i);
+ error_with_file (buf, mapelt);
+ return;
+ }
+ mapelt->info.symdefs[i].s.name = symname;
+ mapelt->info.string_size += strlen (symname) + 1;
+ }
+}
+
+/* Choose which symbol entries to mention in __.SYMDEF;
+ compact them downward to get rid of the rest.
+ Return the number of symbols left. */
+
+int
+filter_symbols (syms, symcount)
+ struct nlist *syms;
+ unsigned int symcount;
+{
+ struct nlist *from, *to;
+ struct nlist *end = syms + symcount;
+
+ for (to = from = syms; from < end; ++from)
+ if ((from->n_type & N_EXT)
+ && (from->n_type != N_EXT || from->n_value != 0))
+ *to++ = *from;
+
+ return to - syms;
+}
+
+
+/* Update the __.SYMDEF data before writing a new archive. */
+
+void
+update_symdefs (map, archive_indesc)
+ struct mapelt *map;
+ int archive_indesc;
+{
+ struct mapelt *tail;
+ int pos;
+ register unsigned int i;
+ unsigned int len;
+ struct symdef *s;
+ unsigned long int deleted_strings_size = 0;
+
+ nsymdefs = original_num_symdefs;
+ num_old_symdefs = original_num_symdefs;
+ new_strings_size = old_strings_size;
+
+ if (nsymdefs != 0)
+ {
+ /* We already had a __.SYMDEF member, so just update it. */
+
+ /* Mark as canceled any old symdefs for members being deleted. */
+
+ for (tail = map; tail != 0; tail = tail->next)
+ {
+ if (tail->info.name == 0)
+ {
+ /* Old member being deleted. Delete its symdef entries too. */
+ for (i = 0; i < original_num_symdefs; i++)
+ if (old_symdefs[i].offset == tail->info.offset)
+ {
+ old_symdefs[i].offset = 0;
+ --nsymdefs;
+ deleted_strings_size
+ += strlen (old_strings
+ + old_symdefs[i].s.stringoffset) + 1;
+ }
+ }
+ }
+
+ /* Compactify old symdefs. */
+ {
+ register unsigned int j = 0;
+ for (i = 0; i < num_old_symdefs; ++i)
+ {
+ if (j != i)
+ old_symdefs[j] = old_symdefs[i];
+ if (old_symdefs[i].offset != 0)
+ ++j;
+ }
+ num_old_symdefs -= i - j;
+ }
+
+ /* Create symdef data for any new members. */
+ for (tail = map; tail != 0; tail = tail->next)
+ {
+ if (tail->info.offset != 0
+ || tail->info.name == 0
+ || !strcmp (tail->info.name, "__.SYMDEF"))
+ continue;
+ make_new_symdefs (tail, archive_indesc);
+ nsymdefs += tail->info.nsymdefs;
+ new_strings_size += tail->info.string_size;
+ }
+ }
+ else
+ {
+ /* Create symdef data for all existing members. */
+
+ for (tail = map; tail != 0; tail = tail->next)
+ {
+ if (tail->info.name == 0
+ || !strcmp (tail->info.name, "__.SYMDEF"))
+ continue;
+ make_new_symdefs (tail, archive_indesc);
+ nsymdefs += tail->info.nsymdefs;
+ new_strings_size += tail->info.string_size;
+ }
+ }
+
+ new_strings_size -= deleted_strings_size;
+ old_strings_size -= deleted_strings_size;
+
+ /* Now we know the size of __.SYMDEF,
+ so assign the positions of all the members. */
+
+ tail = find_mapelt_noerror (map, "__.SYMDEF");
+ tail->info.size = (sizeof (nsymdefs) + (nsymdefs * sizeof (struct symdef))
+ + sizeof (new_strings_size) + new_strings_size);
+ symdef_mapelt = tail;
+
+ pos = SARMAG;
+ for (tail = map; tail != 0; tail = tail->next)
+ {
+ if (tail->info.name == 0)
+ /* Ignore deleted members. */
+ continue;
+ tail->info.new_offset = pos;
+ pos += sizeof (struct ar_hdr) + tail->info.size;
+ if (tail->info.size & 1)
+ ++pos;
+ }
+
+ /* Now update the offsets in the symdef data
+ to be the new offsets rather than the old ones. */
+
+ for (tail = map; tail != 0; tail = tail->next)
+ {
+ if (tail->info.name == 0)
+ continue;
+ if (tail->info.symdefs == 0)
+ /* Member without new symdef data.
+ Check the old symdef data; it may be included there. */
+ for (i = 0; i < num_old_symdefs; i++)
+ {
+ if (old_symdefs[i].offset == tail->info.offset)
+ old_symdefs[i].offset = tail->info.new_offset;
+ }
+ else
+ for (i = 0; i < tail->info.nsymdefs; i++)
+ tail->info.symdefs[i].offset = tail->info.new_offset;
+ }
+
+ /* Generate new, combined string table and put each string's offset into the
+ symdef that refers to it. Note that old symdefs ref their strings by
+ offsets into old_strings but new symdefs contain addresses of strings. */
+
+ new_strings = (char *) xmalloc (new_strings_size);
+ pos = 0;
+
+ /* Write the strings of the old symdefs and update the structures
+ to contain indices into the string table instead of strings. */
+ for (i = 0; i < num_old_symdefs; i++)
+ {
+ strcpy (new_strings + pos, old_strings + old_symdefs[i].s.stringoffset);
+ old_symdefs[i].s.stringoffset = pos;
+ pos += strlen (new_strings + pos) + 1;
+ }
+ if (pos < old_strings_size)
+ {
+ unsigned int d = old_strings_size - pos;
+ /* Correct the string table size. */
+ new_strings_size -= d;
+ /* Correct the size of the `__.SYMDEF' member,
+ since it contains the string table. */
+ symdef_mapelt->info.size -= d;
+ }
+ else if (pos > old_strings_size)
+ fatal ("Old archive's string size was %u too small.",
+ pos - old_strings_size);
+
+ for (tail = map; tail != 0; tail = tail->next)
+ if (tail->info.symdefs)
+ {
+ len = tail->info.nsymdefs;
+ s = tail->info.symdefs;
+
+ for (i = 0; i < len; i++)
+ {
+ strcpy (new_strings + pos, s[i].s.name);
+ s[i].s.stringoffset = pos;
+ pos += strlen (new_strings + pos) + 1;
+ }
+ }
+ if (pos != new_strings_size)
+ fatal ("internal error: inconsistency in new_strings_size", 0);
+}
+
+
+/* Print error message and usage message, and exit. */
+
+void
+usage (s1, s2)
+ char *s1, *s2;
+{
+ error (s1, s2);
+ fprintf (stderr, "\
+Usage: %s [d|m|p|q|r|t|x [[abi [position-name] [cilouv]] archive file...\n",
+ program_name);
+ exit (1);
+}
+
+/* Print error message and exit. */
+
+void
+fatal (s1, s2)
+ char *s1, *s2;
+{
+ error (s1, s2);
+ exit (1);
+}
+
+/* Print error message. `s1' is printf control string, the rest are args. */
+
+void
+error (s1, s2, s3, s4, s5)
+ char *s1, *s2, *s3, *s4, *s5;
+{
+ fprintf (stderr, "%s: ", program_name);
+ fprintf (stderr, s1, s2, s3, s4, s5);
+ fprintf (stderr, "\n");
+}
+
+void
+error_with_file (string, mapelt)
+ char *string;
+ struct mapelt *mapelt;
+{
+ fprintf (stderr, "%s: ", program_name);
+ fprintf (stderr, string);
+ if (mapelt->info.offset != 0)
+ fprintf (stderr, "%s(%s)", archive, mapelt->info.name);
+ else
+ fprintf (stderr, "%s", mapelt->info.name);
+ fprintf (stderr, "\n");
+}
+
+void
+perror_with_name (name)
+ char *name;
+{
+ char *s;
+
+ if (errno < sys_nerr)
+ s = concat ("", sys_errlist[errno], " for %s");
+ else
+ s = "unknown error for %s";
+ error (s, name);
+}
+
+void
+pfatal_with_name (name)
+ char *name;
+{
+ char *s;
+
+ if (errno < sys_nerr)
+ s = concat ("", sys_errlist[errno], " for %s");
+ else
+ s = "cannot open %s";
+ fatal (s, name);
+}
+
+/* Return a newly-allocated string whose contents
+ concatenate those of S1, S2, and S3. */
+
+char *
+concat (s1, s2, s3)
+ char *s1, *s2, *s3;
+{
+ int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
+ char *result = (char *) xmalloc (len1 + len2 + len3 + 1);
+
+ strcpy (result, s1);
+ strcpy (result + len1, s2);
+ strcpy (result + len1 + len2, s3);
+ *(result + len1 + len2 + len3) = 0;
+
+ return result;
+}
+
+/* Like malloc but get fatal error if memory is exhausted. */
+
+char *
+xmalloc (size)
+ unsigned int size;
+{
+#ifdef MALLOC_0_RETURNS_NULL
+ char *result = malloc (size ? size : 1);
+#else
+ char *result = malloc (size);
+#endif
+ if (result == 0)
+ fatal ("virtual memory exhausted", 0);
+ return result;
+}
+
+char *
+xrealloc (ptr, size)
+ char *ptr;
+ unsigned int size;
+{
+ char *result = realloc (ptr, size);
+ if (result == 0)
+ fatal ("virtual memory exhausted");
+ return result;
+}
+
+
+#ifndef HAVE_RENAME
+int
+rename (from, to)
+ char *from, *to;
+{
+ (void)unlink (to);
+ if (link (from, to) < 0
+ || unlink (from) < 0)
+ return -1;
+ else
+ return 0;
+}
+#else
+#ifdef ATT
+int Error;
+#endif
+#endif
diff --git a/as/TODO b/as/TODO
index c7ff1e1..4cf413d 100644
--- a/as/TODO
+++ b/as/TODO
@@ -1,4 +1,3 @@
-
Update 6809/const.h.
Produce bsd symbol tables.
@@ -9,3 +8,6 @@ Decide how to choose between 8-bit and 32-bit branches. 16-bit branches in
32-bit mode are unusable because top 16 bits of PC are messed up.
Buffer for printing of listing.
+
+Need to make assembler remember the code it generated in the penultimate
+pass and regenerate code of exactly the same length in the last pass.
diff --git a/as/as.doc b/as/as.doc
index 99273ef..cb6a649 100644
--- a/as/as.doc
+++ b/as/as.doc
@@ -31,7 +31,7 @@ cc1 output and Minix's make does the wrong thing with .s files left around.
However, all assembler code not written by compilers should assemble with
them turned off.
-The -b flag now produces a 'raw' binary file with no header, if there's no
+The -b flag produces a 'raw' binary file with no header, if there's no
-s flag the file starts at location 0. The -s generates an ASCII symbol
table, if a binary file doesn't start at location zero the first two items
are the start and end addresses of the binary file.
diff --git a/as/express.c b/as/express.c
index 023e2dd..65923b5 100644
--- a/as/express.c
+++ b/as/express.c
@@ -42,7 +42,10 @@ error_pt errnum;
PRIVATE void expundefined()
{
- lastexp.data = FORBIT | UNDBIT;
+ if( last_pass == 1 )
+ lastexp.data = FORBIT | UNDBIT;
+ else
+ lastexp.data = UNDBIT;
}
PUBLIC void nonimpexpres()
@@ -278,13 +281,18 @@ PUBLIC void factor()
{
if (!(symptr->type & (LABIT | VARBIT)))
{
- symptr->data |= FORBIT;
+ if( last_pass == 1 )
+ symptr->data |= FORBIT;
lastexp.sym = symptr;
}
if (pass != last_pass)
{
- lastexp.data = symptr->data &
- (FORBIT | RELBIT | UNDBIT | SEGM);
+ if( last_pass == 1 )
+ lastexp.data = symptr->data &
+ (FORBIT | RELBIT | UNDBIT | SEGM);
+ else
+ lastexp.data = symptr->data &
+ (RELBIT | UNDBIT | SEGM);
/* possible flags for pass 1 */
lastexp.offset = symptr->value_reg_or_op.value;
}
diff --git a/as/mops.c b/as/mops.c
index dd00f3a..2ccf0c7 100644
--- a/as/mops.c
+++ b/as/mops.c
@@ -853,8 +853,9 @@ register struct ea_s *eap;
}
}
}
- if (!(symptr->type & (LABIT | MACBIT | MNREGBIT | VARBIT)))
- symptr->data |= FORBIT; /* show seen in advance */
+ if( last_pass == 1 )
+ if (!(symptr->type & (LABIT | MACBIT | MNREGBIT | VARBIT)))
+ symptr->data |= FORBIT; /* show seen in advance */
}
if ((eap->base = regchk()) != NOREG)
{
@@ -1216,7 +1217,7 @@ PUBLIC void mcall()
if (lastexp.data & IMPBIT)
{
error(NONIMPREQ);
- lastexp.data = FORBIT | UNDBIT;
+ lastexp.data = FORBIT | UNDBIT;
}
mshort2();
}
@@ -2905,8 +2906,10 @@ PRIVATE reg_pt regchk()
return regno;
}
}
- else if (!(symptr->type & (LABIT | MACBIT | VARBIT)))
- symptr->data |= FORBIT; /* show seen in advance */
+ else
+ if( last_pass == 1 )
+ if (!(symptr->type & (LABIT | MACBIT | VARBIT)))
+ symptr->data |= FORBIT; /* show seen in advance */
}
return NOREG;
}
diff --git a/as/pops.c b/as/pops.c
index 64e2268..70efaf5 100644
--- a/as/pops.c
+++ b/as/pops.c
@@ -145,7 +145,10 @@ PRIVATE void docomm()
labptr->type |= COMMBIT;
if (lcommflag)
labptr->type |= REDBIT; /* kludge - COMMBIT | REDBIT => SA */
- labptr->data = (lcdata & SEGM) | (FORBIT | IMPBIT | RELBIT);
+ if( last_pass == 1 )
+ labptr->data = (lcdata & SEGM) | (FORBIT | IMPBIT | RELBIT);
+ else
+ labptr->data = (lcdata & SEGM) | (IMPBIT | RELBIT);
showlabel();
}
}
@@ -531,8 +534,10 @@ PUBLIC void pcomm1()
/* Like import. */
if (label->type & (EXPBIT | LABIT))
error(ALREADY);
- else
+ else if( last_pass == 1 )
label->data = lcdata | (FORBIT | IMPBIT | RELBIT);
+ else
+ label->data = lcdata | (IMPBIT | RELBIT);
getsym();
getcomma();
if (label->type & (EXPBIT | LABIT))
@@ -819,9 +824,11 @@ PUBLIC void pimport()
if (symptr->type & (COMMBIT | EXPBIT | LABIT))
/* IMPORT is null if label (to be) declared */
error(ALREADY);
- else
+ else if( last_pass == 1 )
/* get current segment from lcdata, no need to mask rest */
symptr->data = lcdata | (FORBIT | IMPBIT | RELBIT);
+ else
+ symptr->data = lcdata | (IMPBIT | RELBIT);
}
getsym();
if (sym != COMMA)
diff --git a/bcc/function.c b/bcc/function.c
index 0407028..6c84975 100644
--- a/bcc/function.c
+++ b/bcc/function.c
@@ -11,6 +11,7 @@
#include "sc.h"
#include "table.h"
#include "type.h"
+#include "scan.h"
#ifdef I8088
# define ADJUSTLONGRETURN
diff --git a/bin86/Makefile b/bin86/Makefile
index f5889c9..615d915 100644
--- a/bin86/Makefile
+++ b/bin86/Makefile
@@ -9,8 +9,8 @@ LIBDIR=$(PREFIX)/lib
MANDIR=$(PREFIX)/man/man1
SUF=86
-INSTALL_OPT=-m 755 -s
-MAN_OPTS =-m 644
+INSTALL_OPTS=-m 755 -s
+MAN_OPTS =-m 644
MFLAGS= "LIBS=$(LIBS)" \
"CFLAGS=$(CFLAGS)" \
@@ -20,8 +20,8 @@ MFLAGS= "LIBS=$(LIBS)" \
"CC=$(CC)"
all:
- for d in $(DIRS); do \
- (cd $$d; $(MAKE) $(MFLAGS) $@;); \
+ set -e ; for d in $(DIRS); do \
+ (cd $$d && $(MAKE) $(MFLAGS) $@;); \
done
install: all
@@ -30,19 +30,20 @@ install: all
install $(INSTALL_OPTS) ld/ld86 $(BINDIR)/ld$(SUF)
install $(INSTALL_OPTS) ld/objdump86 $(BINDIR)/objdump$(SUF)
install $(MAN_OPTS) man/*.1 $(MANDIR)
- ln -s objdump$(SUF) $(BINDIR)/nm$(SUF)
- ln -s objdump$(SUF) $(BINDIR)/size$(SUF)
+ ln -sf objdump$(SUF) $(BINDIR)/nm$(SUF)
+ ln -sf objdump$(SUF) $(BINDIR)/size$(SUF)
+ ln -sf as86.1 $(MANDIR)/as86_encap.1
depend clean clobber:
- for d in $(DIRS); do \
- (cd $$d; $(MAKE) $(MFLAGS) $@;); \
+ set -e ; for d in $(DIRS); do \
+ (cd $$d && $(MAKE) $(MFLAGS) $@;); \
done
ungrab: ../as/as.c
rm -rf as ld man
grab:
cp -a ../as ../ld .
- rm -f ld/ar.h ; cp -p ../libc/include/ar.h ld/ar.h
+ rm -f ld/ar.h && cp -p ../libc/include/ar.h ld/ar.h
mkdir man
cp -p ../man/ld86.1 man
cp -p ../man/as86.1 man
diff --git a/bootblocks/Makefile b/bootblocks/Makefile
index bf081ba..96dfadf 100644
--- a/bootblocks/Makefile
+++ b/bootblocks/Makefile
@@ -17,9 +17,7 @@ default: makeboot makeboot.com monitor.out minix_elks.bin
all: default tgz bin minix_elks.bin
CSRC=minix.c
-SSRC=sysboot.s \
- tarboot.s skip.s com_bcc.s tich.s \
- bootlist.s mbr.s msdos.s noboot.s
+SSRC=sysboot.s tarboot.s skip.s com_bcc.s tich.s mbr.s msdos.s noboot.s
encap: $(SSRC:s=v) $(CSRC:c=v) minixhd.v msdos16.v
bin: $(SSRC:s=bin) $(CSRC:c=bin) minixhd.bin msdos16.bin
diff --git a/bootblocks/README b/bootblocks/README
index f51bcd3..80a447e 100644
--- a/bootblocks/README
+++ b/bootblocks/README
@@ -120,7 +120,8 @@ Contents
None of the boot blocks can _directly_ boot a Linux-i386 kernel the
program 'monitor.out' must loaded by the boot sector and this can
- load a zimage or bzimage from an MSDOS, Minix or Tar floppy.
+ load a zimage or bzimage from an MSDOS, Minix or Tar floppy. It can
+ also load the image from a minix hard disk filesystem.
This example is for and MSDOS floppy, Tar is very similar except that
'monitor.out' must be the first file in the tar and can have any name.
diff --git a/bootblocks/bootlist.s b/bootblocks/bootlist.s
deleted file mode 100644
index a9c603c..0000000
--- a/bootblocks/bootlist.s
+++ /dev/null
@@ -1,257 +0,0 @@
-! This bootsector is modified by the installer to have a list of sectors at
-! offset 256.
-
-! Table format is a list of dwords. Each dword has a partition offest in
-! the low 24 bits and a count in the high.
-!
-! Prob better to make it: HH DD MM LL rather than DD HH MM LL
-! as this matches the BIOS better
-!
-! Note:
-! Stack top is at abs location 64k.
-!
-
-! PS: This hasn't been tested much ... make that at all!
-
-BOOTSEG = 0x07c0
-LOADSEG = 0x07e0 ! Just after boot sector.
-
-public linear
-linear = 1 ! Is linear processing done ? (0 doesn't work)
-public floppy
-floppy = 0 *linear ! Allow for floppy drive ? (don't work)
-public reloc
-reloc = 1 *linear ! Auto configure of bootpart.
-
-macro locn
- if *-start>?1
- fail! ?1
- endif
- .blkb ?1 + start-*
-mend
-
-use16
-entry start
-
-org $7b00
-
-! temporary space
-
-n_cyl: .blkw 1
-n_secs: .blkw 1
-t_drive: .blkb 1
-t_sector: .blkb 1
-t_secs: .blkw 1
-
-org $7c00
-start:
- j code
-
-runit:
- jmpi 0,0 ! This instruction is altered by the installer
-
-public execaddr ! Via this label.
-execaddr = *-4
-
-public bootpart
-bootpart:
- .data4 0x80000011
-code:
-
- if reloc
- mov cx,[si+8] ! Fetch the linear address of part from DS:SI
- mov dh,[si+10] ! DL is drive number
- xchg dl,dh ! Into normal form.
- endif
-
- xor ax,ax
- mov ds,ax
- mov ss,ax
- mov sp,ax
-
- if reloc
- mov [bootpart],cx
- mov [bootpart+2],dx
- endif
-
-! ASSUME ds=ss= 0 (cs should also be zero)
-
- mov ax,#LOADSEG
- mov es,ax
-
- mov si,#table
-load_addrs:
- cld
-
- if linear
- lodsw
- mov cx,ax
- add cx,[bootpart]
- lodsw
- mov dx,[bootpart+2]
- adc dl,al
- mov al,ah
- else
- lodsw ; XXX Broken, doesn't set AL correctly.
- mov cx,ax
- lodsw
- mov dx,ax
- lodsb
- endif
-
- test al,al
- jz runit
-
-loadem:
- xor bx,bx
- push ax
- call cread
- jc failed
- pop ax
- mov cl,#5
- sal ax,cl
- mov bx,es
- add ax,bx
- mov es,ax
- j load_addrs
-
-! Humm, something goes wrong, not much we can do ...
-! Let`s squeak then try again
-failed:
- mov ax,#$0E45
- mov bx,#7
- int $10
- pop ax
-
- j loadem
-
-cread:
- ! This function is like BIOS 1302 but it`s linear.
- ! It's taken, almost, intact from LILO.
-
- ! DH is drive, DL:CX is linear address, AL is count.
- ! ES:BX is load address, beware of DMA limitations
-
- ! All registers except AX and flags are preserved.
-
- mov t_secs,al ! save number of sectors
-lnread: push cx ! keep linear address
- push dx
- xchg dl,dh
-
- if linear
- if floppy
- test dl,#0x80 ! Floppy is physical only.
- jz lrd
- endif
-
- push bx ! BX is used as scratch
- push cx ! LSW
- push dx ! MSW with drive
- mov ah,#8 ! get drive geometry (do not clobber ES:DI)
- push es
- push di
- int 0x13
- pop di
- pop es
- mov bl,dh ! BL <- #heads
- pop dx ! get MSW
-
- jnc int_ok ! error -> quit
-
- pop cx ! discard stack contents
- pop bx
- pop dx
- pop cx
- ret ! (carry is already set)
-int_ok:
- mov t_drive,dl ! save drive
- mov dl,dh ! linear address into DX:AX
- xor dh,dh
- mov bh,dh ! (clear BH too)
- pop ax
- push cx ! compute #cyls-1
- xchg ch,cl
- rol ch,1
- rol ch,1
- and ch,#3
- mov n_cyl,cx ! save #cyls-1
- pop cx
- and cx,#0x3f ! CX <- #secs
- mov n_secs,cx
- div cx ! AX <- track, DX <- sector
- inc dl
- mov t_sector,dl
- xor dx,dx ! divide by #heads
- inc bx
- div bx ! AX <- cylinder, DX <- head
- mov dh,dl ! set up DX (head:drive)
- mov dl,t_drive
- cmp ax,n_cyl ! valid cylinder number ?
- ja linerr3 ! no -> error
- xchg ah,al ! build cylinder number
- ror al,1
- ror al,1
- or al,t_sector
- mov cx,ax
- pop bx ! restore BX
- and ax,#0x3f ! read beyond end of track ?
- add ax,t_secs
- cmp ax,n_secs
- jna intrk ! no -> go on
- mov al,n_secs ! read to end of track
- sub al,t_sector
- inc al
- jmp lrd ! read it
-intrk: mov al,t_secs ! read all sectors
-
- endif
-
-lrd: push ax ! save AX and BX
- push bx
-
- mov ah,#2 !
- int 0x13 ! read sectors
-
- pop bx ! restore AX and BX and the linear address
- pop ax
- pop dx
- pop cx
-
- if linear
-
- jc linerr ! error -> quit
- sub t_secs,al ! adjust sector count
- jz lindone ! zero -> done
- xor ah,ah ! increase linear address
- add cx,ax
- adc dh,#0
- xchg ah,al ! move BX
- add ah,ah
- add bx,ax
- jc interr ! crossing segment boundaries -> error
- br lnread ! process remaining sectors
-
-linerr3:pop bx ! pop BX and linear address
- pop dx
- pop cx
-interr: xor ax,ax ! zero indicates internal error
-
- else
- jnc lindone
- endif
-
-linerr: stc ! error
- ret
-lindone:clc ! no error
- ret ! done
-
-
-!-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-
-public table
-table:
-! .long 0x80000012
-! .byte 1
-! .long 0x07e00000
-! .byte 0
diff --git a/bootblocks/bzimage.c b/bootblocks/bzimage.c
index 89d5ef1..7711f41 100644
--- a/bootblocks/bzimage.c
+++ b/bootblocks/bzimage.c
@@ -480,15 +480,15 @@ char * iname;
return strdup(buffer);
}
-build_linuxarg(image, cmd)
-char *image, *cmd;
+build_linuxarg(image, inp)
+char *image, *inp;
{
static char * auto_str = "auto";
static char * image_str = "BOOT_IMAGE=";
int len = 0;
char * ptr, *s, *d;
- char * free_cmd = 0;
- char * free_inp = 0, * inp = 0;
+ char * free_cmd = 0, * cmd = 0;
+ char * free_inp = 0;
image_name = strdup(image);
@@ -498,12 +498,7 @@ static char * image_str = "BOOT_IMAGE=";
if( cmd == 0 )
cmd = free_cmd = read_cmdfile(image);
- if( cmd == 0 )
- {
- if( auto_flag ) return 0;
- printf("No such command file\n");
- return -1;
- }
+ if( cmd == 0 && auto_flag ) return 0;
if( auto_flag )
{
@@ -515,6 +510,8 @@ static char * image_str = "BOOT_IMAGE=";
}
free(ptr);
}
+ else if( inp == 0 )
+ inp = free_inp = input_cmd(image);
if( auto_flag ) len += strlen(auto_str) + 1;
if( image ) len += strlen(image_str) + strlen(image) + 1;
@@ -645,8 +642,8 @@ unsigned int k_top;
char buf[2];
fname++;
close_file();
- printf("Insert root floppy and press return:"); fflush(stdout);
- read(0, buf, 2);
+ printf("Insert root disk and press return:"); fflush(stdout);
+ if( read(0, buf, 2) <=0 ) return -1;
}
if( open_file(fname) < 0 )
diff --git a/bootblocks/monitor.c b/bootblocks/monitor.c
index 1ba93ec..2e47da8 100644
--- a/bootblocks/monitor.c
+++ b/bootblocks/monitor.c
@@ -47,16 +47,14 @@ static char minibuf[2] = " ";
}
#endif
- if( (__argr.x.dx & 0xFF) == 0 )
+ disk_drive = __argr.h.dl;
#endif
- {
#ifdef NOCOMMAND
- cmd_type("help.txt");
+ cmd_type("help.txt");
#else
- display_help(0);
+ display_help(0);
#endif
- cmd_bzimage((void*)0);
- }
+ cmd_bzimage((void*)0);
#ifdef NOCOMMAND
printf("Unable to boot, sorry\nreboot:");
diff --git a/bootblocks/msdos.s b/bootblocks/msdos.s
index 7f691ff..f291b6b 100644
--- a/bootblocks/msdos.s
+++ b/bootblocks/msdos.s
@@ -18,6 +18,12 @@
! 3) The value of the hidden sectors field must be zero
!
! All these are true for mtools created floppies on normal PC drives.
+!
+! In addition this now has a compile time option for 16 bit FAT floppies
+! TODO: Hard partition (dos_hidden != 0)
+! Zip disks (floppy with dos_hidden != 0)
+! Auto detect disk type
+!
!---------------------------------------------------------------------------
ORGADDR=$0500
@@ -29,12 +35,7 @@ export fatbits
fatbits=12 ! Set to 12 or 16 (16 for LS-120 disks)
export heads
-
-if fatbits =12
-heads=2 ! This can be 0,1 or 2. 0 is dynamic.
-else
heads=0 ! This can be 0,1 or 2. 0 is dynamic.
-endif
!---------------------------------------------------------------------------
! Absolute position macro, fails if code before it is too big.
@@ -90,7 +91,6 @@ cont:
xor dh,dh
mul dx
add ax,[dos_resv]
- ! Assume: dos_hidden == 0
mov di,ax
! DI is sector number of first root dir sector.
@@ -160,10 +160,12 @@ linsect:
linsect1:
xor dx,dx
linsect2:
+ ! Add partition offset in.
if fatbits =16
- add ax,[dos_hidden]
- adc dx,[dos_hidden+2]
+ add ax,[dos_hidden]
+ adc dx,[dos_hidden+2]
endif
+
div [dos_spt]
inc dx
mov cl,dl ! Sector num
diff --git a/copt/Makefile b/copt/Makefile
index 7a7d653..329557b 100644
--- a/copt/Makefile
+++ b/copt/Makefile
@@ -1,8 +1,9 @@
copt: copt.c
- $(CC) $(ANSI) $(CFLAGS) $(LDFLAGS) -o copt copt.c
+ $(CC) $(CFLAGS) $(LDFLAGS) -o copt copt.c
realclean clean:
rm -f *.o copt
+# $(CC) $(ANSI) $(CFLAGS) $(LDFLAGS) -o copt copt.c
diff --git a/copt/copt.c b/copt/copt.c
index 24577ae..e440f31 100644
--- a/copt/copt.c
+++ b/copt/copt.c
@@ -872,5 +872,7 @@ void main(int argc, char **argv)
clearpattern();
}
writeoutf(outfile, headstr);
+
+ exit(0);
}
diff --git a/copt/copt1 b/copt/copt1
new file mode 100755
index 0000000..2883aba
--- /dev/null
+++ b/copt/copt1
Binary files differ
diff --git a/elksemu/elks_sys.c b/elksemu/elks_sys.c
index 4b8187f..75ee3da 100644
--- a/elksemu/elks_sys.c
+++ b/elksemu/elks_sys.c
@@ -21,6 +21,7 @@
#include <sys/wait.h>
#include <sys/ioctl.h>
#include <dirent.h>
+#include <sys/time.h>
#include "elks.h"
#ifdef DEBUG
diff --git a/ifdef.c b/ifdef.c
index 424ea50..869b4be 100644
--- a/ifdef.c
+++ b/ifdef.c
@@ -429,6 +429,9 @@ manifest_constant()
/* Linux/unix */
#ifdef __linux__
save_name("__linux__", 'D');
+#ifdef __i386__
+ save_name("XX__linux_i386__", 'D');
+#endif
#endif
#ifdef __unix__
save_name("__unix__", 'D');
diff --git a/ld/objdump86.c b/ld/objdump86.c
index f9f32a3..71e5e62 100644
--- a/ld/objdump86.c
+++ b/ld/objdump86.c
@@ -8,13 +8,21 @@
* size86: Summary sizes of the data in a binary file.
* nm86: The symbol table of the binary file.
*
- * None of these programs have any options, neither can they currently deal
- * with archive files. This may be a minor problem with nm86.
+ * None of these programs have any options.
+ * This may be a minor problem with nm86.
+ *
+ * Copyright (c) 1999 by Greg Haerr <greg@censoft.com>
+ * Added archive file reading capabilties
*/
#include <stdio.h>
#include <malloc.h>
#include <string.h>
+#ifdef __STDC__
+#include <stdlib.h>
+#endif
+#include "ar.h"
+#include "obj.h"
FILE * ifd;
char * ifname;
@@ -30,6 +38,8 @@ long get_sized _((int sz));
unsigned int get_word _((void));
int main _((int argc, char**argv));
void do_file _((char * fname));
+long read_arheader _((char *archentry));
+void do_module _((char * fname, char *archive));
int error _((char * str));
int read_objheader _((void));
int read_sectheader _((void));
@@ -45,6 +55,7 @@ int sections;
long segsizes[16];
long textoff, textlen;
long str_off, str_len;
+long filepos;
char ** symnames;
char * symtab;
@@ -100,19 +111,82 @@ void
do_file(fname)
char * fname;
{
+ unsigned int magic;
+ long filelength;
+ char archentry[sizeof(struct ar_hdr)]; /* sizeof ar_hdr.ar_name*/
+ char filemagic[SARMAG];
+
+ ifname = fname;
+ if( (ifd=fopen(fname, "rb")) == 0 )
+ {
+ error("Cannot open file");
+ return;
+ }
+ filepos = 0L;
+
+ /* check if file is an archive*/
+ if(fread(filemagic, sizeof(filemagic), 1, ifd) == 1
+ && strncmp(filemagic, ARMAG, sizeof filemagic) == 0)
+ {
+ filepos = SARMAG;
+ while((filelength = read_arheader(archentry)) > 0)
+ {
+ filepos += sizeof(struct ar_hdr);
+ magic = get_word();
+ if(magic == 0x86A3)
+ { /* OMAGIC*/
+ fseek(ifd, filepos, 0);
+ do_module(archentry, fname);
+ }
+ else if(magic == 0x3C21 ) /* "!<" */
+ filelength = SARMAG;
+ filepos += ld_roundup(filelength, 2, long);
+ fseek(ifd, filepos, 0);
+ }
+ }
+ else
+ {
+ fseek(ifd, 0L, 0);
+ do_module(fname, NULL);
+ }
+ fclose(ifd);
+}
+
+/* read archive header and return length */
+long
+read_arheader(archentry)
+char *archentry;
+{
+ char * endptr;
+ struct ar_hdr arheader;
+
+ if(fread((char *)&arheader, sizeof(arheader), 1, ifd) != 1)
+ return 0;
+ strncpy(archentry, arheader.ar_name, sizeof(arheader.ar_name));
+ archentry[sizeof(arheader.ar_name)] = 0;
+ endptr = archentry + sizeof(arheader.ar_name);
+ do
+ {
+ *endptr-- = 0;
+ } while(endptr > archentry && (*endptr == ' ' || *endptr == '/'));
+ return strtoul(arheader.ar_size, (char **)NULL, 0);
+}
+
+void
+do_module(fname, archive)
+char * fname;
+char * archive;
+{
int modno, i, ch;
size_text = size_data = size_bss = 0;
byte_order = 0;
if( !display_mode )
- printf("OBJECTFILE '%s'\n", fname);
-
- ifname = fname;
- if( (ifd=fopen(fname, "rb")) == 0 )
{
- error("Cannot open file");
- return;
+ if(archive)
+ printf("ARCHIVEFILE '%s'\n", archive);
+ printf("OBJECTFILE '%s'\n", fname);
}
switch( read_objheader() )
@@ -125,10 +199,12 @@ char * fname;
printf("OBJECTSECTION %d\n", modno);
if( read_sectheader() < 0 ) break;
+ /* segments 0, 4-E are text, 1-3 are data*/
for(i=0; i<16; i++)
{
- if( i<3 ) size_text += segsizes[i];
- else size_data += segsizes[i];
+ if(i < 1 || i > 4)
+ size_text += segsizes[i];
+ else size_data += segsizes[i];
}
if( read_syms() < 0 ) break;
@@ -136,18 +212,22 @@ char * fname;
if( display_mode == 0 )
printf("text\tdata\tbss\tdec\thex\tfilename\n");
if( display_mode != 2 )
- printf("%ld\t%ld\t%ld\t%ld\t%lx\t%s\n",
+ {
+ printf("%ld\t%ld\t%ld\t%ld\t%lx\t",
size_text, size_data, size_bss,
size_text+ size_data+ size_bss,
- size_text+ size_data+ size_bss,
- ifname);
+ size_text+ size_data+ size_bss);
+
+ if(archive) printf("%s(%s)\n", archive, fname);
+ else printf("%s\n", fname);
+ }
if( sections == 1 && display_mode != 0 )
break;
read_databytes();
}
- if( !display_mode )
+ if( !archive && !display_mode )
{
i=0;
while( (ch=getc(ifd)) != EOF )
@@ -175,7 +255,6 @@ char * fname;
}
break;
}
- fclose(ifd);
if( symtab ) free(symtab);
if( symnames ) free(symnames);
@@ -238,7 +317,7 @@ read_sectheader()
if( symtab == 0 ) return error("Out of memory");
cpos = ftell(ifd);
- fseek(ifd, str_off, 0);
+ fseek(ifd, filepos+str_off, 0);
fread(symtab, 1, (int)str_len, ifd);
fseek(ifd, cpos, 0);
@@ -357,7 +436,7 @@ static char * relstr[] = {"ERR", "DB", "DW", "DD"};
int ch, i;
int curseg = 0;
int relsize = 0;
- fseek(ifd, textoff, 0);
+ fseek(ifd, filepos+textoff, 0);
printf("\nBYTECODE\n");
for(;;)
diff --git a/libc/Makefile b/libc/Makefile
index 0b18d17..da891d3 100644
--- a/libc/Makefile
+++ b/libc/Makefile
@@ -10,8 +10,8 @@ TOP=$(TOPDIR)/libc
endif
VERMAJOR=0
-VERMINOR=14
-VERPATCH=8
+VERMINOR=15
+VERPATCH=0
VER=$(VERMAJOR).$(VERMINOR).$(VERPATCH)
CC=bcc
diff --git a/libc/msdos/dirent.c b/libc/msdos/dirent.c
new file mode 100644
index 0000000..00d774e
--- /dev/null
+++ b/libc/msdos/dirent.c
@@ -0,0 +1,8 @@
+
+opendir
+
+closedir
+
+readdir
+
+rewinddir
diff --git a/libc/msdos/dosound.c b/libc/msdos/dosound.c
new file mode 100644
index 0000000..80f49d6
--- /dev/null
+++ b/libc/msdos/dosound.c
@@ -0,0 +1,10 @@
+
+
+nosound()
+{
+}
+
+sound(freq)
+int freq
+{
+}
diff --git a/makefile.in b/makefile.in
index d4ebbc2..d7440b1 100644
--- a/makefile.in
+++ b/makefile.in
@@ -21,6 +21,13 @@ MAKEARG =CC='$(CC)' CFLAGS='$(CFLAGS)' LDFLAGS='$(LDFLAGS)' PREFIX=$(PREFIX) \
MAKEC=$(MAKE) -C
MAKEX=
+# This is only allowed on Linux because make needs to know how to look
+# inside an archive to get the last modified times of the component .o
+# files. This should be fine for Linux, but it won't be for AIX.
+#ifdef __linux__
+AR=ar86
+#endif
+
#ifdef __GNUC__
# unproto is yukky, I've included '-w' in the local makefile.
@@ -69,10 +76,10 @@ INEXE=-o root -g root -m 755 -s
INSCR=-o root -g root -m 755
#ifdef GNUMAKE
-all: check_config bcc unproto copt as86 ld86 objdump86 \
+all: check_config bcc unproto copt as86 ar86 ld86 objdump86 \
library lib-bsd alt-libs elksemu
#else
-all: check_config bcc unproto copt as86 ld86 objdump86
+all: check_config bcc unproto copt as86 ar86 ld86 objdump86
@echo
@echo 'NOTE: To build the libraries you need GNU-Make.'
@echo ' They are available precompiled in the Dev86clb-X.X.X.zip file.'
@@ -85,7 +92,7 @@ install-all: install install-other
##############################################################################
-LIBARGS= CC=ncc CCFLAGS= ARFLAGS=$(ARFLAGS)
+LIBARGS= CC=ncc CCFLAGS= AR=$(AR) ARFLAGS=$(ARFLAGS)
# Season in the top makefile
ELKSSRC= %ELKSSRC%
@@ -105,7 +112,7 @@ DISTPRE= $(DIST)$(LIBPRE)
# Others to install
OTHERS= tests dis88 doselks bootblocks
-CLEANLIST= bcc as ld unproto copt libc elksemu libbsd $(OTHERS)
+CLEANLIST= bcc as ar ld unproto copt libc elksemu libbsd $(OTHERS)
##############################################################################
@@ -141,6 +148,10 @@ as86: bindir
cp -p as/as86 bin/as86
cp -p as/as86_encap bin/as86_encap
+ar86: bindir
+ $(MAKEC) ar $(MAKEARG) all
+ cp -p ar/ar86 bin/ar86
+
ld86: bindir
$(MAKEC) ld $(MAKEARG) ld86
cp -p ld/ld86 bin/ld86
@@ -155,7 +166,7 @@ objdump86: bindir
elksemu: bindir
#ifndef __AS386_16__
-#ifdef __i386__
+#ifdef __linux_i386__
$(MAKEC) elksemu \
CC='$(CC)' PREFIX=$(PREFIX) LIBPRE='$(LIBPRE)' LIBDIR='$(LIBDIR)' BINDIR='$(BINDIR)' \
elksemu
@@ -165,11 +176,12 @@ elksemu: bindir
cp -p elksemu/elksemu bin/elksemu
#endif
-install-ln: bcc unproto copt as86 ld86 elksemu
+install-ln: bcc unproto copt as86 ar86 ld86 elksemu
install -d $(DISTBIN)
ln -fs `pwd`/bin/ncc $(DISTBIN)/bcc
ln -fs `pwd`/bin/as86_encap $(DISTBIN)/as86_encap
ln -fs `pwd`/bin/as86 $(DISTBIN)/as86
+ ln -fs `pwd`/bin/ar86 $(DISTBIN)/ar86
ln -fs `pwd`/bin/ld86 $(DISTBIN)/ld86
#ifndef __AS386_16__
ln -fs `pwd`/bin/elksemu $(DIST)/lib/elksemu
@@ -177,11 +189,12 @@ install-ln: bcc unproto copt as86 ld86 elksemu
-install -d $(DIST)/usr/lib
-install $(INDAT) libc/error/liberror.txt $(DIST)/usr/lib/liberror.txt
-install-bcc: bcc unproto copt as86 ld86 objdump86
+install-bcc: bcc unproto copt as86 ar86 ld86 objdump86
install -d $(DISTBIN) $(DISTLIB) $(DISTLIB)/i86
install $(INEXE) bin/Bcc $(DISTBIN)/bcc
install $(INSCR) bin/as86_encap $(DISTBIN)/as86_encap
install $(INEXE) bin/as86 $(DISTBIN)/as86
+ install $(INEXE) bin/ar86 $(DISTBIN)/ar86
install $(INEXE) bin/ld86 $(DISTBIN)/ld86
install $(INEXE) bin/objdump86 $(DISTBIN)/objdump86
install $(INEXE) bin/objdump86 $(DISTBIN)/nm86
diff --git a/man/as86.1 b/man/as86.1
index f03ce27..edb6408 100644
--- a/man/as86.1
+++ b/man/as86.1
@@ -76,7 +76,8 @@ start with 32-bit code segment, don't warn for any instructions. (not even
.B -a
enable partial compatibility with Minix asld. This swaps the interpretation
of round brackets and square brackets as well as making alterations to the
-code generation for 16bit jumps and calls.
+code generation and syntax for 16bit jumps and calls. ("jmp @(bx)" is then
+a valid instruction)
.TP
.B -g
only put global symbols in object or symbol file
diff --git a/man/elksemu.1 b/man/elksemu.1
index 5f00a44..6686040 100644
--- a/man/elksemu.1
+++ b/man/elksemu.1
@@ -2,7 +2,7 @@
.BY Me!
.nh
.SH NAME
-elksemu \- Embedded Linux Kernel Environment emulator
+elksemu \- Embedded Linux Kernel Subset emulator
.SH SYNOPSIS
.B /lib/elksemu
.B program
diff --git a/man/index.bt b/man/index.bt
new file mode 100644
index 0000000..e295941
--- /dev/null
+++ b/man/index.bt
Binary files differ