Full switch to clang/ELF. Drop ack. Simplify.

There is important information about booting non-ack images in
docs/UPDATING. ack/aout-format images can't be built any more, and
booting clang/ELF-format ones is a little different. Updating to the
new boot monitor is recommended.

Changes in this commit:

	. drop boot monitor -> allowing dropping ack support
	. facility to copy ELF boot files to /boot so that old boot monitor
	  can still boot fairly easily, see UPDATING
	. no more ack-format libraries -> single-case libraries
	. some cleanup of OBJECT_FMT, COMPILER_TYPE, etc cases
	. drop several ack toolchain commands, but not all support
	  commands (e.g. aal is gone but acksize is not yet).
	. a few libc files moved to netbsd libc dir
	. new /bin/date as minix date used code in libc/
	. test compile fix
	. harmonize includes
	. /usr/lib is no longer special: without ack, /usr/lib plays no
	  kind of special bootstrapping role any more and bootstrapping
	  is done exclusively through packages, so releases depend even
	  less on the state of the machine making them now.
	. rename nbsd_lib* to lib*
	. reduce mtree
This commit is contained in:
Ben Gras 2012-02-11 19:31:25 +01:00
parent 2487445f5f
commit 2fe8fb192f
5056 changed files with 16216 additions and 133169 deletions

6
.gitignore vendored
View File

@ -14,11 +14,6 @@ cscope.*
*.d
.depend
nbsdsrc/*
obj-ack
obj-gnu
obj-elf-base
obj-elfbase-nbsd
obj-gnu-nbsd
tools/revision
TAGS
tags
@ -41,3 +36,4 @@ etc/spwd.db
tools/image
tools/kernel
share/zoneinfo/builddir
lib/libc/compat__*

View File

@ -12,8 +12,7 @@ usage:
@echo "Usage:"
@echo " make world # Compile everything (libraries & commands)"
@echo " make includes # Install include files from src/"
@echo " make libraries # Compile and install libraries (ack)"
@echo " make elf-libraries # Compile and install gcc/clang elf libs"
@echo " make libraries # Compile and install libraries"
@echo " make commands # Compile all, commands, but don't install"
@echo " make install # Compile and install commands"
@echo " make gnu-includes # Install include files for GCC"
@ -30,32 +29,21 @@ usage:
# 'make install' target.
#
# etcfiles has to be done first.
.if ${COMPILER_TYPE} == "ack"
world: mkfiles etcfiles includes libraries elf-libraries dep-all install etcforce
.else
world: mkfiles etcfiles includes elf-libraries dep-all install etcforce
.endif
world: mkfiles etcfiles includes libraries dep-all install etcforce
mkfiles:
make -C share/mk install
includes:
$(MAKE) -C nbsd_include includes
$(MAKE) -C include includes
$(MAKE) -C lib includes NBSD_LIBC=yes
.if ${COMPILER_TYPE} == "ack"
$(MAKE) -C lib includes NBSD_LIBC=no
.endif
libraries: includes
$(MAKE) -C lib build_ack
MKHEADERSS=/usr/pkg/gcc*/libexec/gcc/*/*/install-tools/mkheaders
gnu-includes: includes
SHELL=/bin/sh; for d in $(MKHEADERSS); do if [ -f $$d ] ; then sh -e $$d ; fi; done
elf-libraries: includes
$(MAKE) -C lib build_elf
libraries: includes
$(MAKE) -C lib dependall install
commands: includes libraries
$(MAKE) -C commands all
@ -66,8 +54,7 @@ commands: includes libraries
$(MAKE) -C usr.sbin all
dep-all:
$(MAKE) CC=cc -C boot dependall
$(MAKE) CC=clang -C sys dependall
$(MAKE) -C sys dependall
$(MAKE) -C commands dependall
$(MAKE) -C bin dependall
$(MAKE) -C sbin dependall
@ -85,8 +72,7 @@ etcforce:
$(MAKE) -C etc installforce
all:
$(MAKE) CC=cc -C boot all
$(MAKE) CC=clang -C sys all
$(MAKE) -C sys all
$(MAKE) -C commands all
$(MAKE) -C bin all
$(MAKE) -C sbin all
@ -96,8 +82,7 @@ all:
$(MAKE) -C tools all
install:
$(MAKE) CC=cc -C boot install
$(MAKE) CC=clang -C sys install
$(MAKE) -C sys install
$(MAKE) -C libexec install
$(MAKE) -C man install makedb
$(MAKE) -C commands install
@ -110,7 +95,6 @@ install:
$(MAKE) -C tools install
clean: mkfiles
$(MAKE) -C boot clean
$(MAKE) -C sys clean
$(MAKE) -C commands clean
$(MAKE) -C bin clean
@ -120,12 +104,11 @@ clean: mkfiles
$(MAKE) -C usr.sbin clean
$(MAKE) -C share clean
$(MAKE) -C tools clean
$(MAKE) -C lib clean_all
$(MAKE) -C lib clean
$(MAKE) -C test clean
cleandepend: mkfiles
$(MAKE) -C lib cleandepend_all
$(MAKE) -C boot cleandepend
$(MAKE) -C lib cleandepend
$(MAKE) -C sys cleandepend
$(MAKE) -C commands cleandepend
$(MAKE) -C bin cleandepend
@ -134,3 +117,8 @@ cleandepend: mkfiles
$(MAKE) -C libexec cleandepend
$(MAKE) -C usr.sbin cleandepend
$(MAKE) -C tools cleandepend
# Warn usage change
elf-libraries:
echo "That target is just libraries now."
false

View File

@ -2,6 +2,6 @@
.include <bsd.own.mk>
SUBDIR= mkdir rm rmdir
SUBDIR= mkdir rm rmdir date
.include <bsd.subdir.mk>

View File

@ -1,5 +1,3 @@
.include <minix.newlibc.mk>
CPPFLAGS+= -D_NETBSD_SOURCE
BINDIR?=/bin

15
bin/date/Makefile Normal file
View File

@ -0,0 +1,15 @@
# $NetBSD: Makefile,v 1.15 2011/08/14 10:53:16 christos Exp $
# @(#)Makefile 8.1 (Berkeley) 5/31/93
PROG= date
SRCS= date.c netdate.c
DPADD+= ${LIBUTIL}
LDADD+= -lutil
CPPFLAGS+=-I${.CURDIR}
TZDIR= /usr/share/zoneinfo
CPPFLAGS+= -DHAVE_ADJTIME=0 -DTZDIR=\"$(TZDIR)\"
COPTS.date.c = -Wno-format-nonliteral
.include <bsd.prog.mk>

244
bin/date/date.1 Normal file
View File

@ -0,0 +1,244 @@
.\" $NetBSD: date.1,v 1.41 2010/02/04 22:56:11 wiz Exp $
.\"
.\" Copyright (c) 1980, 1990, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
.\" This code is derived from software contributed to Berkeley by
.\" the Institute of Electrical and Electronics Engineers, Inc.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" @(#)date.1 8.3 (Berkeley) 4/28/95
.\"
.Dd November 15, 2006
.Dt DATE 1
.Os
.Sh NAME
.Nm date
.Nd display or set date and time
.Sh SYNOPSIS
.Nm
.Op Fl ajnu
.Op Fl d Ar date
.Op Fl r Ar seconds
.Op Cm + Ns Ar format
.Sm off
.Oo Oo Oo Oo Oo Oo
.Ar CC Oc
.Ar yy Oc
.Ar mm Oc
.Ar dd Oc
.Ar HH Oc Ar MM Oo
.Li \&. Ar SS Oc Oc
.Sm on
.Sh DESCRIPTION
.Nm
displays the current date and time when invoked without arguments.
Providing arguments will format the date and time in a user-defined
way or set the date.
Only the superuser may set the date.
.Pp
The options are as follows:
.Bl -tag -width Ds
.It Fl a
Use
.Xr adjtime 2
to change the local system time slowly,
maintaining it as a monotonically increasing function.
.Fl a
implies
.Fl n .
.It Fl d Ar date
Parse the provided human-described date and time and display the result without
actually changing the system clock.
(See
.Xr parsedate 3
for examples.)
.It Fl j
Parse the provided canonical representation of date and time (described below)
and display the result without actually changing the system clock.
.It Fl n
The utility
.Xr timed 8
is used to synchronize the clocks on groups of machines.
By default, if
timed
is running,
.Nm
will set the time on all of the machines in the local group.
The
.Fl n
option stops
.Nm
from setting the time for other than the current machine.
.It Fl r Ar seconds
Print out the date and time that is
.Ar seconds
from the Epoch.
.It Fl u
Display or set the date in
.Tn UTC
(universal) time.
.El
.Pp
An operand with a leading plus
.Pq Cm +
sign signals a user-defined format
string which specifies the format in which to display the date and time.
The format string may contain any of the conversion specifications described
in the
.Xr strftime 3
manual page, as well as any arbitrary text.
A \*[Lt]newline\*[Gt] character is always output after the characters
specified by the format string.
The format string for the default display is:
.Bd -literal -offset indent
%a %b %e %H:%M:%S %Z %Y
.Ed
.Pp
If an operand does not have a leading plus sign, it is interpreted as
a value for setting the system's notion of the current date and time.
The canonical representation for setting the date and time is:
.Pp
.Bl -tag -width Ds -compact -offset indent
.It Ar CC
The first two digits of the year (the century).
.It Ar yy
The second two digits of the year.
If
.Ar yy
is specified, but
.Ar CC
is not, a value for
.Ar yy
between 69 and 99 results in a
.Ar CC
value of 19.
Otherwise, a
.Ar CC
value of 20 is used.
.It Ar mm
The month of the year, from 01 to 12.
.It Ar dd
The day of the month, from 01 to 31.
.It Ar HH
The hour of the day, from 00 to 23.
.It Ar MM
The minute of the hour, from 00 to 59.
.It Ar SS
The second of the minute, from 00 to 61.
.El
.Pp
Everything but the minutes is optional.
.Pp
Time changes for Daylight Saving and Standard time and leap seconds
and years are handled automatically.
.Sh ENVIRONMENT
The following environment variables affect the execution of
.Nm :
.Bl -tag -width iTZ
.It Ev TZ
The timezone to use when displaying dates.
See
.Xr environ 7
for more information.
.El
.Sh FILES
.Bl -tag -width /var/log/messages -compact
.It Pa /etc/localtime
Symlink pointing to system's default timezone information file in
.Pa /usr/share/zoneinfo
directory.
.It Pa /var/log/wtmp
A record of date resets and time changes.
.It Pa /var/log/messages
A record of the user setting the time.
.El
.Sh EXAMPLES
The command:
.Bd -literal -offset indent
date '+DATE: %m/%d/%y%nTIME: %H:%M:%S'
.Ed
.Pp
will display:
.Bd -literal -offset indent
DATE: 11/21/87
TIME: 13:36:16
.Ed
.Pp
The command:
.Bd -literal -offset indent
date 8506131627
.Ed
.Pp
sets the date to
.Dq Li "June 13, 1985, 4:27 PM" .
.Pp
The command:
.Bd -literal -offset indent
date 1432
.Ed
.Pp
sets the time to
.Li "2:32 PM" ,
without modifying the date.
.Sh DIAGNOSTICS
Exit status is 0 on success, 1 if unable to set the date, and 2
if able to set the local date, but unable to set it globally.
.Pp
Occasionally, when
.Xr timed 8
synchronizes the time on many hosts, the setting of a new time value may
require more than a few seconds.
On these occasions,
.Nm
prints:
.Ql Network time being set .
The message
.Ql Communication error with timed
occurs when the communication
between
.Nm
and
timed
fails.
.Sh SEE ALSO
.Xr adjtime 2 ,
.Xr gettimeofday 2 ,
.Xr settimeofday 2 ,
.Xr parsedate 3 ,
.Xr strftime 3 ,
.Xr utmp 5 ,
.Xr timed 8
.Rs
.%T "TSP: The Time Synchronization Protocol for UNIX 4.3BSD"
.%A R. Gusella
.%A S. Zatti
.Re
.Sh STANDARDS
The
.Nm
utility is expected to be compatible with
.St -p1003.2 .

350
bin/date/date.c Normal file
View File

@ -0,0 +1,350 @@
/* $NetBSD: date.c,v 1.60 2011/08/27 12:55:09 joerg Exp $ */
/*
* Copyright (c) 1985, 1987, 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
__COPYRIGHT(
"@(#) Copyright (c) 1985, 1987, 1988, 1993\
The Regents of the University of California. All rights reserved.");
#endif /* not lint */
#ifndef lint
#if 0
static char sccsid[] = "@(#)date.c 8.2 (Berkeley) 4/28/95";
#else
__RCSID("$NetBSD: date.c,v 1.60 2011/08/27 12:55:09 joerg Exp $");
#endif
#endif /* not lint */
#include <sys/param.h>
#include <sys/time.h>
#include <ctype.h>
#include <err.h>
#include <fcntl.h>
#include <errno.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <time.h>
#include <tzfile.h>
#include <unistd.h>
#include <util.h>
#include "extern.h"
static time_t tval;
static int aflag, jflag, rflag, nflag;
__dead static void badformat(void);
__dead static void badtime(void);
__dead static void badvalue(const char *);
static void setthetime(const char *);
__dead static void usage(void);
int
main(int argc, char *argv[])
{
char *buf;
size_t bufsiz;
const char *format;
int ch;
long long val;
struct tm *tm;
setprogname(argv[0]);
(void)setlocale(LC_ALL, "");
while ((ch = getopt(argc, argv, "ad:jnr:u")) != -1) {
switch (ch) {
case 'a': /* adjust time slowly */
aflag = 1;
nflag = 1;
break;
case 'd':
#ifndef __minix
rflag = 1;
tval = parsedate(optarg, NULL, NULL);
if (tval == -1)
#endif
badarg: errx(EXIT_FAILURE,
"Cannot parse `%s'", optarg);
break;
case 'j': /* don't set time */
jflag = 1;
break;
case 'n': /* don't set network */
nflag = 1;
break;
case 'r': /* user specified seconds */
errno = 0;
val = strtoll(optarg, &buf, 0);
if (optarg[0] == '\0' || *buf != '\0')
goto badarg;
if (errno == ERANGE && (val == LLONG_MAX ||
val == LLONG_MIN))
err(EXIT_FAILURE, "Bad number `%s'", optarg);
rflag = 1;
tval = (time_t)val;
break;
case 'u': /* do everything in UTC */
(void)setenv("TZ", "UTC0", 1);
break;
default:
usage();
}
}
argc -= optind;
argv += optind;
if (!rflag && time(&tval) == -1)
err(EXIT_FAILURE, "time");
/* allow the operands in any order */
if (*argv && **argv == '+') {
format = *argv;
++argv;
} else
format = "+%a %b %e %H:%M:%S %Z %Y";
if (*argv) {
setthetime(*argv);
++argv;
}
if (*argv && **argv == '+')
format = *argv;
if ((buf = malloc(bufsiz = 1024)) == NULL)
goto bad;
if ((tm = localtime(&tval)) == NULL)
err(EXIT_FAILURE, "localtime %lld failed", (long long)tval);
while (strftime(buf, bufsiz, format, tm) == 0)
if ((buf = realloc(buf, bufsiz <<= 1)) == NULL)
goto bad;
(void)printf("%s\n", buf + 1);
free(buf);
return 0;
bad:
err(EXIT_FAILURE, "Cannot allocate format buffer");
}
static void
badformat(void)
{
warnx("illegal time format");
usage();
}
static void
badtime(void)
{
errx(EXIT_FAILURE, "illegal time");
/* NOTREACHED */
}
static void
badvalue(const char *param)
{
warnx("invalid %s supplied", param);
usage();
}
#define ATOI2(s) ((s) += 2, ((s)[-2] - '0') * 10 + ((s)[-1] - '0'))
static void
setthetime(const char *p)
{
struct timeval tv;
time_t new_time;
struct tm *lt;
const char *dot, *t;
size_t len;
int yearset;
for (t = p, dot = NULL; *t; ++t) {
if (isdigit((unsigned char)*t))
continue;
if (*t == '.' && dot == NULL) {
dot = t;
continue;
}
badformat();
}
if ((lt = localtime(&tval)) == NULL)
err(EXIT_FAILURE, "localtime %lld failed", (long long)tval);
lt->tm_isdst = -1; /* Divine correct DST */
if (dot != NULL) { /* .ss */
len = strlen(dot);
if (len != 3)
badformat();
++dot;
lt->tm_sec = ATOI2(dot);
if (lt->tm_sec > 61)
badvalue("seconds");
} else {
len = 0;
lt->tm_sec = 0;
}
yearset = 0;
switch (strlen(p) - len) {
case 12: /* cc */
lt->tm_year = ATOI2(p) * 100 - TM_YEAR_BASE;
if (lt->tm_year < 0)
badtime();
yearset = 1;
/* FALLTHROUGH */
case 10: /* yy */
if (yearset) {
lt->tm_year += ATOI2(p);
} else {
yearset = ATOI2(p);
if (yearset < 69)
lt->tm_year = yearset + 2000 - TM_YEAR_BASE;
else
lt->tm_year = yearset + 1900 - TM_YEAR_BASE;
}
/* FALLTHROUGH */
case 8: /* mm */
lt->tm_mon = ATOI2(p);
if (lt->tm_mon > 12 || lt->tm_mon == 0)
badvalue("month");
--lt->tm_mon; /* time struct is 0 - 11 */
/* FALLTHROUGH */
case 6: /* dd */
lt->tm_mday = ATOI2(p);
switch (lt->tm_mon) {
case 0:
case 2:
case 4:
case 6:
case 7:
case 9:
case 11:
if (lt->tm_mday > 31 || lt->tm_mday == 0)
badvalue("day of month");
break;
case 3:
case 5:
case 8:
case 10:
if (lt->tm_mday > 30 || lt->tm_mday == 0)
badvalue("day of month");
break;
case 1:
if (lt->tm_mday > 29 || lt->tm_mday == 0 ||
(lt->tm_mday == 29 &&
!isleap(lt->tm_year + TM_YEAR_BASE)))
badvalue("day of month");
break;
default:
badvalue("month");
break;
}
/* FALLTHROUGH */
case 4: /* hh */
lt->tm_hour = ATOI2(p);
if (lt->tm_hour > 23)
badvalue("hour");
/* FALLTHROUGH */
case 2: /* mm */
lt->tm_min = ATOI2(p);
if (lt->tm_min > 59)
badvalue("minute");
break;
case 0: /* was just .sss */
if (len != 0)
break;
/* FALLTHROUGH */
default:
badformat();
}
/* convert broken-down time to UTC clock time */
if ((new_time = mktime(lt)) == -1)
badtime();
/* if jflag is set, don't actually change the time, just return */
if (jflag) {
tval = new_time;
return;
}
/* set the time */
if (nflag || netsettime(new_time)) {
logwtmp("|", "date", "");
#if HAVE_ADJTIME
if (aflag) {
tv.tv_sec = new_time - tval;
tv.tv_usec = 0;
if (adjtime(&tv, NULL))
err(EXIT_FAILURE, "adjtime");
}
#else
if (aflag) {
err(EXIT_FAILURE, "no adjtime");
}
#endif
else {
tval = new_time;
tv.tv_sec = tval;
tv.tv_usec = 0;
if (settimeofday(&tv, NULL))
err(EXIT_FAILURE, "settimeofday");
}
logwtmp("{", "date", "");
}
if ((p = getlogin()) == NULL)
p = "???";
syslog(LOG_AUTH | LOG_NOTICE, "date set by %s", p);
}
static void
usage(void)
{
(void)fprintf(stderr,
"Usage: %s [-ajnu] [-d date] [-r seconds] [+format]",
getprogname());
(void)fprintf(stderr, " [[[[[[CC]yy]mm]dd]HH]MM[.SS]]\n");
exit(EXIT_FAILURE);
/* NOTREACHED */
}

View File

@ -1,7 +1,7 @@
/* $NetBSD: memory.h,v 1.5 2003/08/07 09:44:10 agc Exp $ */
/* $NetBSD: extern.h,v 1.8 2006/11/17 22:11:28 christos Exp $ */
/*
* Copyright (c) 1988, 1993
/*-
* Copyright (c) 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -28,7 +28,12 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)memory.h 8.1 (Berkeley) 6/2/93
* @(#)extern.h 8.1 (Berkeley) 5/31/93
*/
#include <string.h>
#ifndef _EXTERN_H_
#define _EXTERN_H_
int netsettime(time_t);
#endif /* !_EXTERN_H_ */

200
bin/date/netdate.c Normal file
View File

@ -0,0 +1,200 @@
/* $NetBSD: netdate.c,v 1.30 2011/01/29 02:16:52 christos Exp $ */
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)netdate.c 8.2 (Berkeley) 4/28/95";
#else
__RCSID("$NetBSD: netdate.c,v 1.30 2011/01/29 02:16:52 christos Exp $");
#endif
#endif /* not lint */
#include <sys/param.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define TSPTYPES
#include <protocols/timed.h>
#include <err.h>
#include <errno.h>
#include <poll.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "extern.h"
#define WAITACK 2000 /* milliseconds */
#define WAITDATEACK 5000 /* milliseconds */
static const char *
tsp_type_to_string(const struct tsp *msg)
{
unsigned i;
i = msg->tsp_type;
return i < TSPTYPENUMBER ? tsptype[i] : "unknown";
}
/*
* Set the date in the machines controlled by timedaemons by communicating the
* new date to the local timedaemon. If the timedaemon is in the master state,
* it performs the correction on all slaves. If it is in the slave state, it
* notifies the master that a correction is needed.
* Returns 0 on success. Returns > 0 on failure.
*/
int
netsettime(time_t tval)
{
struct sockaddr_in dest;
struct tsp msg;
char hostname[MAXHOSTNAMELEN];
struct servent *sp;
struct pollfd ready;
int found, s, timed_ack, waittime;
if ((sp = getservbyname("timed", "udp")) == NULL) {
warnx("udp/timed: unknown service");
return 2;
}
(void)memset(&dest, 0, sizeof(dest));
#ifdef BSD4_4
dest.sin_len = sizeof(dest);
#endif
dest.sin_family = AF_INET;
dest.sin_port = sp->s_port;
dest.sin_addr.s_addr = htonl(INADDR_ANY);
s = socket(AF_INET, SOCK_DGRAM, 0);
if (s == -1) {
if (errno != EAFNOSUPPORT)
warn("timed");
return 2;
}
#ifdef IP_PORTRANGE
{
static const int on = IP_PORTRANGE_LOW;
if (setsockopt(s, IPPROTO_IP, IP_PORTRANGE, &on,
sizeof(on)) == -1) {
warn("setsockopt");
goto bad;
}
}
#endif
msg.tsp_type = TSP_SETDATE;
msg.tsp_vers = TSPVERSION;
if (gethostname(hostname, sizeof(hostname)) == -1) {
warn("gethostname");
goto bad;
}
(void)strlcpy(msg.tsp_name, hostname, sizeof(msg.tsp_name));
msg.tsp_seq = htons((in_port_t)0);
msg.tsp_time.tv_sec = htonl((in_addr_t)tval); /* XXX: y2038 */
msg.tsp_time.tv_usec = htonl((in_addr_t)0);
if (connect(s, (const void *)&dest, sizeof(dest)) == -1) {
warn("connect");
goto bad;
}
if (send(s, &msg, sizeof(msg), 0) == -1) {
if (errno != ECONNREFUSED)
warn("send");
goto bad;
}
timed_ack = -1;
waittime = WAITACK;
ready.fd = s;
ready.events = POLLIN;
loop:
found = poll(&ready, 1, waittime);
{
socklen_t len;
int error;
len = sizeof(error);
if (getsockopt(s, SOL_SOCKET, SO_ERROR, &error, &len) == -1) {
warn("getsockopt");
goto bad;
}
if (error) {
if (error != ECONNREFUSED) {
errno = error;
warn("send (delayed error)");
}
goto bad;
}
}
if (found > 0 && ready.revents & POLLIN) {
ssize_t ret;
if ((ret = recv(s, &msg, sizeof(msg), 0)) == -1) {
if (errno != ECONNREFUSED)
warn("recv");
goto bad;
} else if ((size_t)ret < sizeof(msg)) {
warnx("recv: incomplete packet");
goto bad;
}
msg.tsp_seq = ntohs(msg.tsp_seq);
msg.tsp_time.tv_sec = ntohl(msg.tsp_time.tv_sec);
msg.tsp_time.tv_usec = ntohl(msg.tsp_time.tv_usec);
switch (msg.tsp_type) {
case TSP_ACK:
timed_ack = TSP_ACK;
waittime = WAITDATEACK;
goto loop;
case TSP_DATEACK:
(void)close(s);
return 0;
default:
warnx("wrong ack received from timed: %s",
tsp_type_to_string(&msg));
timed_ack = -1;
break;
}
}
if (timed_ack == -1)
warnx("can't reach time daemon, time set locally");
bad:
(void)close(s);
return 2;
}

View File

@ -1,17 +0,0 @@
# Makefile for the boot monitor package.
.include <bsd.own.mk>
# 16-bit code; various boot blocks
SUBDIR= masterboot bootblock cdbootblock
# Supplementary MBR code (alternate to masterboot)
SUBDIR+= jumpboot
# 16-bit code; needs the i86 ACK library
SUBDIR+= boot
# Userland MINIX code
SUBDIR+= installboot edparams
.include <bsd.subdir.mk>

View File

@ -1,220 +0,0 @@
/* boot.h - Info between different parts of boot. Author: Kees J. Bot
*/
#ifndef DEBUG
#define DEBUG 0
#endif
/* Constants describing the metal: */
#define SECTOR_SIZE 512
#define SECTOR_SHIFT 9
#define RATIO(b) ((b) / SECTOR_SIZE)
#define PARAMSEC 1 /* Sector containing boot parameters. */
#define DSKBASE 0x1E /* Floppy disk parameter vector. */
#define DSKPARSIZE 11 /* There are this many bytes of parameters. */
#define ESC '\33' /* Escape key. */
#define HEADERPOS 0x00600L /* Place for an array of struct exec's. */
#define FREEPOS 0x08000L /* Memory from FREEPOS to caddr is free to
* play with.
*/
#if BIOS
#define MSEC_PER_TICK 55 /* Clock does 18.2 ticks per second. */
#define TICKS_PER_DAY 0x1800B0L /* After 24 hours it wraps. */
#endif
#if UNIX
#define MSEC_PER_TICK 1000 /* Clock does 18.2 ticks per second. */
#define TICKS_PER_DAY 86400L /* Doesn't wrap, but that doesn't matter. */
#endif
#define BOOTPOS 0x07C00L /* Bootstraps are loaded here. */
#define SIGNATURE 0xAA55 /* Proper bootstraps have this signature. */
#define SIGNATOFF 510 /* Offset within bootblock. */
/* BIOS video modes. */
#define MONO_MODE 0x07 /* 80x25 monochrome. */
#define COLOR_MODE 0x03 /* 80x25 color. */
/* Variables shared with boothead.s: */
#ifndef EXTERN
#define EXTERN extern
#endif
typedef struct vector { /* 8086 vector */
u16_t offset;
u16_t segment;
} vector;
EXTERN vector rem_part; /* Boot partition table entry. */
EXTERN u32_t caddr, daddr; /* Code and data address of the boot program. */
EXTERN u32_t runsize; /* Size of this program. */
EXTERN u16_t device; /* Drive being booted from. */
EXTERN u16_t cddevice; /* Drive that is CD if known. */
#define CDNAME "cd" /* Name of the CD device. */
EXTERN int mon_return; /* Monitor stays in memory? */
EXTERN int cdbooted; /* Did we boot from CD? (Set by boothead.s.) */
typedef struct bios_env
{
u16_t ax;
u16_t bx;
u16_t cx;
u16_t flags;
} bios_env_t;
#define FL_CARRY 0x0001 /* carry flag */
/* Functions defined by boothead.s: */
void exit(int code);
/* Exit the monitor. */
u32_t mon2abs(void *ptr);
/* Local monitor address to absolute address. */
u32_t vec2abs(vector *vec);
/* Vector to absolute address. */
void raw_copy(u32_t dstaddr, u32_t srcaddr, u32_t count);
/* Copy bytes from anywhere to anywhere. */
u16_t get_word(u32_t addr);
/* Get a word from anywhere. */
void put_word(u32_t addr, u16_t word);
/* Put a word anywhere. */
void relocate(void);
/* Switch to a copy of this program. */
int dev_open(void), dev_close(void);
/* Open device and determine params / close device. */
int dev_boundary(u32_t sector);
/* True if sector is on a track boundary. */
int readsectors(u32_t bufaddr, u32_t sector, u8_t count);
/* Read 1 or more sectors from "device". */
int writesectors(u32_t bufaddr, u32_t sector, u8_t count);
/* Write 1 or more sectors to "device". */
int biosreadsectors(u32_t bufaddr, u32_t sector, u8_t count);
int getch(void);
/* Read a keypress. */
void scan_keyboard(void);
/* Read keypress directly from kb controller. */
void ungetch(int c);
/* Undo a keypress. */
int escape(void);
/* True if escape typed. */
void putch(int c);
/* Send a character to the screen. */
#if BIOS
void pause(void);
/* Wait for an interrupt. */
void serial_init(int line);
#endif /* Enable copying console I/O to a serial line. */
void set_mode(unsigned mode);
void clear_screen(void);
/* Set video mode / clear the screen. */
u16_t get_bus(void);
/* System bus type, XT, AT, or MCA. */
u16_t get_video(void);
/* Display type, MDA to VGA. */
u32_t get_tick(void);
/* Current value of the clock tick counter. */
void bootstrap(int device, struct part_entry *entry);
/* Execute a bootstrap routine for a different O.S. */
void minix(u32_t koff, u32_t kcs, u32_t kds,
char *bootparams, size_t paramsize, u32_t aout);
/* Start Minix. */
void int15(bios_env_t *);
/* Do an "INT 15" call, primarily for APM. */
void scan_keyboard(void);
/* Read keyboard character.
* Needs to be done in case one is waiting. */
void reset(void);
/* */
/* Shared between boot.c and bootimage.c: */
/* Sticky attributes. */
#define E_SPECIAL 0x01 /* These are known to the program. */
#define E_DEV 0x02 /* The value is a device name. */
#define E_RESERVED 0x04 /* May not be set by user, e.g. 'boot' */
#define E_STICKY 0x07 /* Don't go once set. */
/* Volatile attributes. */
#define E_VAR 0x08 /* Variable */
#define E_FUNCTION 0x10 /* Function definition. */
/* Variables, functions, and commands. */
typedef struct environment {
struct environment *next;
char flags;
char *name; /* name = value */
char *arg; /* name(arg) {value} */
char *value;
char *defval; /* Safehouse for default values. */
} environment;
EXTERN environment *env; /* Lists the environment. */
char *b_value(const char *name); /* Get/set the value of a variable. */
int b_setvar(int flags, char *name, char *value);
void b_unset(const char *name);
void parse_code(char *code); /* Parse boot monitor commands. */
extern int fsok; /* True if the boot device contains an FS. */
EXTERN u32_t lowsec; /* Offset to the file system on the boot device. */
/* Called by boot.c: */
void bootminix(void); /* Load and start a Minix image. */
/* Called by bootimage.c: */
void readerr(off_t sec, int err);
/* Report a read error. */
char *ul2a(u32_t n, unsigned b), *ul2a10(u32_t n);
/* Transform u32_t to ASCII at base b or base 10. */
long a2l(const char *a);
/* Cheap atol(). */
unsigned a2x(const char *a);
/* ASCII to hex. */
dev_t name2dev(char *name);
/* Translate a device name to a device number. */
int numprefix(char *s, char **ps);
/* True for a numeric prefix. */
int numeric(char *s);
/* True for a numeric string. */
char *unix_err(int err);
/* Give a descriptive text for some UNIX errors. */
int run_trailer(void);
/* Run the trailer function. */
#if DOS
/* The monitor runs under MS-DOS. */
extern char PSP[256]; /* Program Segment Prefix. */
EXTERN char *vdisk; /* Name of the virtual disk. */
EXTERN char *drun; /* Initial command from DOS command line. */
#else
/* The monitor uses only the BIOS. */
#define DOS 0
#endif
void readblock(off_t, char *, int);
void delay(const char *);
/*
* $PchId: boot.h,v 1.12 2002/02/27 19:42:45 philip Exp $
*/

View File

@ -1,30 +0,0 @@
# boot monitor: runs in 16-bit mode
.include <bsd.own.mk>
# XXX: Can only be built with ACK currently
MINIXID= -sep
.include "${.CURDIR}/../minix.ack16.mk"
AFLAGS+= -Was-ncc
STRIPFLAG= -s
LIBDIR?= /usr/lib/i86
PROG= boot
SRCS= boothead.s boot.c bootimage.c rawfs.c
# Need exec_elf.c from libexec
SRCS+= exec_elf.c
.PATH: ${.CURDIR}/.. ${MINIXSRCDIR}/lib/libexec
CPPFLAGS+= -I${MINIXSRCDIR} -I${.CURDIR} -I${.CURDIR}/..
DPADD+= ${LIBSYS} # for kprintf, kmalloc
LDADD+= -lsys
BINDIR= /usr/mdec
MAN=
.include <bsd.prog.mk>
realall: .PHONY bootsize
bootsize: boot
${INSTALL} -S 12kb boot

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,26 +0,0 @@
#define EMEM_ENTRIES 16
#define EMEM_SIZE 24 /* size in bytes of e820_memory struct */
#define MEM_ENTRIES 3
#ifndef __ASSEMBLY__
typedef struct { /* One chunk of free memory. */
u32_t base; /* Start byte. */
u32_t size; /* Number of bytes. */
} memory;
EXTERN memory mem[MEM_ENTRIES]; /* List of available memory. */
typedef struct { /* One chunk of free memory. */
u32_t base_lo; /* Start byte. */
u32_t base_hi;
u32_t size_lo; /* Number of bytes. */
u32_t size_hi; /* Number of bytes. */
u32_t type;
u32_t acpi_attrs;
} e820_memory;
EXTERN e820_memory emem[EMEM_ENTRIES]; /* List of available memory. */
EXTERN int emem_entries;
#endif

View File

@ -1,19 +0,0 @@
# bootblock: secondary boot code, still 16-bit mode
.include <bsd.own.mk>
# XXX: Can only be built with ACK currently
.include "${MINIXSRCDIR}/boot/minix.ack16.mk"
AFLAGS+= -Was-ncc
STRIPFLAG= -s
PROG= bootblock
SRCS= bootblock.s
BINDIR= /usr/mdec
MAN=
LIBC= # defined, to silence bsd.*.mk
.include <bsd.prog.mk>

View File

@ -1,256 +0,0 @@
#
! Bootblock 1.5 - Minix boot block. Author: Kees J. Bot
! 21 Dec 1991
!
! When the PC is powered on, it will try to read the first sector of floppy
! disk 0 at address 0x7C00. If this fails due to the absence of flexible
! magnetic media, it will read the master boot record from the first sector
! of the hard disk. This sector not only contains executable code, but also
! the partition table of the hard disk. When executed, it will select the
! active partition and load the first sector of that at address 0x7C00.
! This file contains the code that is eventually read from either the floppy
! disk, or the hard disk partition. It is just smart enough to load /boot
! from the boot device into memory at address 0x10000 and execute that. The
! disk addresses for /boot are patched into this code by installboot as 24-bit
! sector numbers and 8-bit sector counts above enddata upwards. /boot is in
! turn smart enough to load the different parts of the Minix kernel into
! memory and execute them to finally get Minix started.
!
LOADOFF = 0x7C00 ! 0x0000:LOADOFF is where this code is loaded
BOOTSEG = 0x1000 ! Secondary boot code segment.
#ifdef CDBOOT
BOOTOFF = 0x0050 ! Offset into /boot above header
#else
BOOTOFF = 0x0030 ! Offset into /boot above header
#endif
BUFFER = 0x0600 ! First free memory
#ifndef CDBOOT /* just constants, but make no sense for CDs */
LOWSEC = 8 ! Offset of logical first sector in partition
! table
! Variables addressed using bp register
lowsec = 2 ! Offset of boot partition within drive
secpcyl = 6 ! Sectors per cylinder = heads * sectors
#endif
device = 0 ! The boot device
.text
! Start boot procedure.
boot:
xor ax, ax ! ax = 0x0000, the vector segment
mov ds, ax
cli ! Ignore interrupts while setting stack
mov ss, ax ! ss = ds = vector segment
mov sp, #LOADOFF ! Usual place for a bootstrap stack
sti
push ax
push ax ! Push a zero lowsec(bp)
push dx ! Boot device in dl will be device(bp)
mov bp, sp ! Using var(bp) is one byte cheaper then var.
push es
push si ! es:si = partition table entry if hard disk
mov di, #LOADOFF+sectors ! char *di = sectors;
#ifndef CDBOOT
testb dl, dl ! Winchester disks if dl >= 0x80
jge floppy
#endif
winchester:
#ifndef CDBOOT
! Get the offset of the first sector of the boot partition from the partition
! table. The table is found at es:si, the lowsec parameter at offset LOWSEC.
eseg
les ax, LOWSEC(si) ! es:ax = LOWSEC+2(si):LOWSEC(si)
mov lowsec+0(bp), ax ! Low 16 bits of partitions first sector
mov lowsec+2(bp), es ! High 16 bits of partitions first sector
! Get the drive parameters, the number of sectors is bluntly written into the
! floppy disk sectors/track array.
movb ah, #0x08 ! Code for drive parameters
int 0x13 ! dl still contains drive
andb cl, #0x3F ! cl = max sector number (1-origin)
movb (di), cl ! Number of sectors per track
incb dh ! dh = 1 + max head number (0-origin)
#endif
jmp loadboot
#ifndef CDBOOT
! Floppy:
! Execute three read tests to determine the drive type. Test for each floppy
! type by reading the last sector on the first track. If it fails, try a type
! that has less sectors. Therefore we start with 1.44M (18 sectors) then 1.2M
! (15 sectors) ending with 720K/360K (both 9 sectors).
next: inc di ! Next number of sectors per track
floppy: xorb ah, ah ! Reset drive
int 0x13
movb cl, (di) ! cl = number of last sector on track
cmpb cl, #9 ! No need to do the last 720K/360K test
je success
! Try to read the last sector on track 0
mov es, lowsec(bp) ! es = vector segment (lowsec = 0)
mov bx, #BUFFER ! es:bx buffer = 0x0000:0x0600
mov ax, #0x0201 ! Read sector, #sectors = 1
xorb ch, ch ! Track 0, last sector
xorb dh, dh ! Drive dl, head 0
int 0x13
jc next ! Error, try the next floppy type
success:movb dh, #2 ! Load number of heads for multiply
#endif
loadboot:
! Load /boot from the boot device
#ifndef CDBOOT
movb al, (di) ! al = (di) = sectors per track
mulb dh ! dh = heads, ax = heads * sectors
mov secpcyl(bp), ax ! Sectors per cylinder = heads * sectors
#endif
mov ax, #BOOTSEG ! Segment to load /boot into
mov es, ax
xor bx, bx ! Load first sector at es:bx = BOOTSEG:0x0000
mov si, #LOADOFF+addresses ! Start of the boot code addresses
load:
mov ax, 1(si) ! Get next sector number: low 16 bits
movb dl, 3(si) ! Bits 16-23 for your up to 8GB partition
xorb dh, dh ! dx:ax = sector within partition
#ifndef CDBOOT
add ax, lowsec+0(bp)
adc dx, lowsec+2(bp)! dx:ax = sector within drive
cmp dx, #[1024*255*63-255]>>16 ! Near 8G limit?
jae bigdisk
div secpcyl(bp) ! ax = cylinder, dx = sector within cylinder
xchg ax, dx ! ax = sector within cylinder, dx = cylinder
movb ch, dl ! ch = low 8 bits of cylinder
divb (di) ! al = head, ah = sector (0-origin)
xorb dl, dl ! About to shift bits 8-9 of cylinder into dl
shr dx, #1
shr dx, #1 ! dl[6..7] = high cylinder
orb dl, ah ! dl[0..5] = sector (0-origin)
movb cl, dl ! cl[0..5] = sector, cl[6..7] = high cyl
incb cl ! cl[0..5] = sector (1-origin)
movb dh, al ! dh = al = head
movb dl, device(bp) ! dl = device to read
movb al, (di) ! Sectors per track - Sector number (0-origin)
subb al, ah ! = Sectors left on this track
cmpb al, (si) ! Compare with # sectors to read
jbe read ! Cant read past the end of a cylinder?
movb al, (si) ! (si) < sectors left on this track
read: push ax ! Save al = sectors to read
movb ah, #0x02 ! Code for disk read (all registers in use now!)
int 0x13 ! Call the BIOS for a read
pop cx ! Restore al in cl
jmp rdeval
#endif
bigdisk:
movb cl, (si) ! Number of sectors to read
push si ! Save si
mov si, #LOADOFF+ext_rw ! si = extended read/write parameter packet
movb 2(si), cl ! Fill in # blocks to transfer
mov 4(si), bx ! Buffer address
mov 8(si), ax ! Starting block number = dx:ax
mov 10(si), dx
movb dl, device(bp) ! dl = device to read
movb ah, #0x42 ! Extended read
int 0x13
pop si ! Restore si to point to the addresses array
!jmp rdeval
rdeval:
jc error ! Jump on disk read error
movb al, cl ! Restore al = sectors read
addb bh, al ! bx += 2 * al * 256 (add bytes read)
addb bh, al ! es:bx = where next sector must be read
#ifdef CDBOOT
addb bh, al ! For CDs, a sector is 2048 bytes, so
addb bh, al ! do this 6 more times to get byte count.
addb bh, al
addb bh, al
addb bh, al
addb bh, al
#endif
add 1(si), ax ! Update address by sectors read
adcb 3(si), ah ! Don't forget bits 16-23 (add ah = 0)
subb (si), al ! Decrement sector count by sectors read
jnz load ! Not all sectors have been read
add si, #4 ! Next (address, count) pair
cmpb ah, (si) ! Done when no sectors to read
jnz load ! Read next chunk of /boot
done:
! Call /boot, assuming a long a.out header (48 bytes). The a.out header is
! usually short (32 bytes), but to be sure /boot has two entry points:
! One at offset 0 for the long, and one at offset 16 for the short header.
! Parameters passed in registers are:
!
! dl = Boot-device.
! es:si = Partition table entry if hard disk.
!
pop si ! Restore es:si = partition table entry
pop es ! dl is still loaded
jmpf BOOTOFF, BOOTSEG ! jmp to sec. boot (skipping header).
! Read error: print message, hang forever
error:
mov si, #LOADOFF+errno+1
prnum: movb al, ah ! Error number in ah
andb al, #0x0F ! Low 4 bits
cmpb al, #10 ! A-F?
jb digit ! 0-9!
addb al, #7 ! 'A' - ':'
digit: addb (si), al ! Modify '0' in string
dec si
movb cl, #4 ! Next 4 bits
shrb ah, cl
jnz prnum ! Again if digit > 0
mov si, #LOADOFF+rderr ! String to print
print: lodsb ! al = *si++ is char to be printed
testb al, al ! Null byte marks end
hang: jz hang ! Hang forever waiting for CTRL-ALT-DEL
movb ah, #0x0E ! Print character in teletype mode
mov bx, #0x0001 ! Page 0, foreground color
int 0x10 ! Call BIOS VIDEO_IO
jmp print
.data
rderr: .ascii "Read error "
errno: .ascii "00 \0"
errend:
! Floppy disk sectors per track for the 1.44M, 1.2M and 360K/720K types:
sectors:
.data1 18, 15, 9
! Extended read/write commands require a parameter packet.
ext_rw:
.data1 0x10 ! Length of extended r/w packet
.data1 0 ! Reserved
.data2 0 ! Blocks to transfer (to be filled in)
.data2 0 ! Buffer address offset (tbfi)
.data2 BOOTSEG ! Buffer address segment
.data4 0 ! Starting block number low 32 bits (tbfi)
.data4 0 ! Starting block number high 32 bits
.align 2
addresses:
! The space below this is for disk addresses for a 38K /boot program (worst
! case, i.e. file is completely fragmented). It should be enough.

View File

@ -1,21 +0,0 @@
# cdbootblock: secondary boot code, when booting from cd-rom
.include <bsd.own.mk>
# XXX: Can only be built with ACK currently
.include "${MINIXSRCDIR}/boot/minix.ack16.mk"
AFLAGS+= -Was-ncc
STRIPFLAG= -s
PROG= cdbootblock
SRCS= bootblock.s
.PATH: ${.CURDIR}/../bootblock
AFLAGS+= -DCDBOOT
BINDIR= /usr/mdec
MAN=
LIBC= # defined, to silence bsd.*.mk
.include <bsd.prog.mk>

View File

@ -1,12 +0,0 @@
# edparams: customize boot; runs on both installer's and user's machines
PROG= edparams
BINDIR= /usr/bin
SRCS= boot.c rawfs.c
.PATH: ${.CURDIR}/../boot ${.CURDIR}/..
CPPFLAGS= -DUNIX -I${MINIXSRCDIR} -I${.CURDIR}/..
MAN= # monitor.8
.include <bsd.prog.mk>

View File

@ -1,13 +0,0 @@
/* image.h - Info between installboot and boot. Author: Kees J. Bot
*/
#define IM_NAME_MAX 63
struct image_header {
char name[IM_NAME_MAX + 1]; /* Null terminated. */
struct exec process;
};
/*
* $PchId: image.h,v 1.4 1995/11/27 22:23:12 philip Exp $
*/

View File

@ -1,12 +0,0 @@
# installboot: install the boot package; runs on the installer's machine
PROG= installboot_minix
BINDIR= /usr/bin
SRCS= installboot.c rawfs.c
.PATH: ${.CURDIR}/..
CPPFLAGS= -I${MINIXSRCDIR} -I${.CURDIR}/..
MAN= # installboot.8
.include <bsd.prog.mk>

View File

@ -1,832 +0,0 @@
/* installboot 3.0 - Make a device bootable Author: Kees J. Bot
* 21 Dec 1991
*
* Either make a device bootable or make an image from kernel, mm, fs, etc.
*/
#define _POSIX_SOURCE 1
#define _MINIX 1
#include <stdio.h>
#include <stddef.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <dirent.h>
#include <a.out.h>
#include <minix/config.h>
#include <minix/const.h>
#include <minix/partition.h>
#include <minix/u64.h>
#include "rawfs.h"
#include "image.h"
#define BOOTBLOCK 0 /* Of course */
#define SECTOR_SIZE 512 /* Disk sector size. */
#define RATIO(b) ((b)/SECTOR_SIZE)
#define SIGNATURE 0xAA55 /* Boot block signature. */
#define BOOT_MAX 64 /* Absolute maximum size of secondary boot */
#define SIGPOS 510 /* Where to put signature word. */
#define PARTPOS 446 /* Offset to the partition table in a master
* boot block.
*/
#define between(a, c, z) ((unsigned) ((c) - (a)) <= ((z) - (a)))
#define control(c) between('\0', (c), '\37')
#define BOOT_BLOCK_SIZE 1024
static void report(const char *label)
/* installboot: label: No such file or directory */
{
fprintf(stderr, "installboot: %s: %s\n", label, strerror(errno));
}
static void fatal(const char *label)
{
report(label);
exit(1);
}
char *basename(char *name)
/* Return the last component of name, stripping trailing slashes from name.
* Precondition: name != "/". If name is prefixed by a label, then the
* label is copied to the basename too.
*/
{
static char base[IM_NAME_MAX];
char *p, *bp= base;
if ((p= strchr(name, ':')) != NULL) {
while (name <= p && bp < base + IM_NAME_MAX - 1)
*bp++ = *name++;
}
for (;;) {
if ((p= strrchr(name, '/')) == NULL) { p= name; break; }
if (*++p != 0) break;
*--p= 0;
}
while (*p != 0 && bp < base + IM_NAME_MAX - 1) *bp++ = *p++;
*bp= 0;
return base;
}
static void bread(FILE *f, char *name, void *buf, size_t len)
/* Read len bytes. Don't dare return without them. */
{
if (len > 0 && fread(buf, len, 1, f) != 1) {
if (ferror(f)) fatal(name);
fprintf(stderr, "installboot: Unexpected EOF on %s\n", name);
exit(1);
}
}
static void bwrite(FILE *f, const char *name, const void *buf, size_t len)
{
if (len > 0 && fwrite(buf, len, 1, f) != 1) fatal(name);
}
long total_text= 0, total_data= 0, total_bss= 0;
int making_image= 0;
void read_header(int talk, char *proc, FILE *procf, struct image_header *ihdr)
/* Read the a.out header of a program and check it. If procf happens to be
* NULL then the header is already in *image_hdr and need only be checked.
*/
{
int n, big= 0;
static int banner= 0;
struct exec *phdr= &ihdr->process;
if (procf == NULL) {
/* Header already present. */
n= phdr->a_hdrlen;
} else {
memset(ihdr, 0, sizeof(*ihdr));
/* Put the basename of proc in the header. */
strncpy(ihdr->name, basename(proc), IM_NAME_MAX);
/* Read the header. */
n= fread(phdr, sizeof(char), A_MINHDR, procf);
if (ferror(procf)) fatal(proc);
}
if (n < A_MINHDR || BADMAG(*phdr)) {
fprintf(stderr, "installboot: %s is not an executable\n", proc);
exit(1);
}
/* Get the rest of the exec header. */
if (procf != NULL) {
bread(procf, proc, ((char *) phdr) + A_MINHDR,
phdr->a_hdrlen - A_MINHDR);
}
if (talk && !banner) {
printf(" text data bss size\n");
banner= 1;
}
if (talk) {
printf(" %8ld %8ld %8ld %9ld %s\n",
phdr->a_text, phdr->a_data, phdr->a_bss,
phdr->a_text + phdr->a_data + phdr->a_bss, proc);
}
total_text+= phdr->a_text;
total_data+= phdr->a_data;
total_bss+= phdr->a_bss;
if (phdr->a_cpu == A_I8086) {
long data= phdr->a_data + phdr->a_bss;
if (!(phdr->a_flags & A_SEP)) data+= phdr->a_text;
if (phdr->a_text >= 65536) big|= 1;
if (data >= 65536) big|= 2;
}
if (big) {
fprintf(stderr,
"%s will crash, %s%s%s segment%s larger then 64K\n",
proc,
big & 1 ? "text" : "",
big == 3 ? " and " : "",
big & 2 ? "data" : "",
big == 3 ? "s are" : " is");
}
}
void padimage(const char *image, FILE *imagef, int n)
/* Add n zeros to image to pad it to a sector boundary. */
{
while (n > 0) {
if (putc(0, imagef) == EOF) fatal(image);
n--;
}
}
#define align(n) (((n) + ((SECTOR_SIZE) - 1)) & ~((SECTOR_SIZE) - 1))
void copyexec(char *proc, FILE *procf, char *image, FILE *imagef, long n)
/* Copy n bytes from proc to image padded to fill a sector. */
{
int pad, c;
/* Compute number of padding bytes. */
pad= align(n) - n;
while (n > 0) {
if ((c= getc(procf)) == EOF) {
if (ferror(procf)) fatal(proc);
fprintf(stderr, "installboot: premature EOF on %s\n",
proc);
exit(1);
}
if (putc(c, imagef) == EOF) fatal(image);
n--;
}
padimage(image, imagef, pad);
}
void make_image(char *image, char **procv)
/* Collect a set of files in an image, each "segment" is nicely padded out
* to SECTOR_SIZE, so it may be read from disk into memory without trickery.
*/
{
FILE *imagef, *procf;
char *proc, *file;
int procn;
struct image_header ihdr;
struct exec phdr;
struct stat st;
making_image= 1;
if ((imagef= fopen(image, "w")) == NULL) fatal(image);
for (procn= 0; (proc= *procv++) != NULL; procn++) {
/* Remove the label from the file name. */
if ((file= strchr(proc, ':')) != NULL) file++; else file= proc;
/* Real files please, may need to seek. */
if (stat(file, &st) < 0
|| (errno= EISDIR, !S_ISREG(st.st_mode))
|| (procf= fopen(file, "r")) == NULL
) fatal(proc);
/* Read a.out header. */
read_header(1, proc, procf, &ihdr);
/* Scratch. */
phdr= ihdr.process;
/* The symbol table is always stripped off. */
ihdr.process.a_syms= 0;
ihdr.process.a_flags &= ~A_NSYM;
/* Write header padded to fill a sector */
bwrite(imagef, image, &ihdr, sizeof(ihdr));
padimage(image, imagef, SECTOR_SIZE - sizeof(ihdr));
/* A page aligned executable needs the header in text. */
if (phdr.a_flags & A_PAL) {
rewind(procf);
phdr.a_text+= phdr.a_hdrlen;
}
/* Copy text and data of proc to image. */
if (phdr.a_flags & A_SEP) {
/* Separate I&D: pad text & data separately. */
copyexec(proc, procf, image, imagef, phdr.a_text);
copyexec(proc, procf, image, imagef, phdr.a_data);
} else {
/* Common I&D: keep text and data together. */
copyexec(proc, procf, image, imagef,
phdr.a_text + phdr.a_data);
}
/* Done with proc. */
(void) fclose(procf);
}
/* Done with image. */
if (fclose(imagef) == EOF) fatal(image);
printf(" ------ ------ ------ -------\n");
printf(" %8ld %8ld %8ld %9ld total\n",
total_text, total_data, total_bss,
total_text + total_data + total_bss);
}
void extractexec(FILE *imagef, char *image, FILE *procf, char *proc,
long count, off_t *alen)
/* Copy a segment of an executable. It is padded to a sector in image. */
{
char buf[SECTOR_SIZE];
while (count > 0) {
bread(imagef, image, buf, sizeof(buf));
*alen-= sizeof(buf);
bwrite(procf, proc, buf,
count < sizeof(buf) ? (size_t) count : sizeof(buf));
count-= sizeof(buf);
}
}
void extract_image(char *image)
/* Extract the executables from an image. */
{
FILE *imagef, *procf;
off_t len;
struct stat st;
struct image_header ihdr;
struct exec phdr;
char buf[SECTOR_SIZE];
if (stat(image, &st) < 0) fatal(image);
/* Size of the image. */
len= S_ISREG(st.st_mode) ? st.st_size : -1;
if ((imagef= fopen(image, "r")) == NULL) fatal(image);
while (len != 0) {
/* Extract a program, first sector is an extended header. */
bread(imagef, image, buf, sizeof(buf));
len-= sizeof(buf);
memcpy(&ihdr, buf, sizeof(ihdr));
phdr= ihdr.process;
/* Check header. */
read_header(1, ihdr.name, NULL, &ihdr);
if ((procf= fopen(ihdr.name, "w")) == NULL) fatal(ihdr.name);
if (phdr.a_flags & A_PAL) {
/* A page aligned process contains a header in text. */
phdr.a_text+= phdr.a_hdrlen;
} else {
bwrite(procf, ihdr.name, &ihdr.process, phdr.a_hdrlen);
}
/* Extract text and data segments. */
if (phdr.a_flags & A_SEP) {
extractexec(imagef, image, procf, ihdr.name,
phdr.a_text, &len);
extractexec(imagef, image, procf, ihdr.name,
phdr.a_data, &len);
} else {
extractexec(imagef, image, procf, ihdr.name,
phdr.a_text + phdr.a_data, &len);
}
if (fclose(procf) == EOF) fatal(ihdr.name);
}
}
static int rawfd; /* File descriptor to open device. */
static const char *rawdev; /* Name of device. */
void readblock(off_t blk, char *buf, int block_size)
/* For rawfs, so that it can read blocks. */
{
int n;
if (lseek(rawfd, blk * block_size, SEEK_SET) < 0
|| (n= read(rawfd, buf, block_size)) < 0
) fatal(rawdev);
if (n < block_size) {
fprintf(stderr, "installboot: Unexpected EOF on %s\n", rawdev);
exit(1);
}
}
void writeblock(off_t blk, const char *buf, int block_size)
/* Add a function to write blocks for local use. */
{
if (lseek(rawfd, blk * block_size, SEEK_SET) < 0
|| write(rawfd, buf, block_size) < 0
) fatal(rawdev);
}
int raw_install(char *file, off_t *start, off_t *len, int block_size)
/* Copy bootcode or an image to the boot device at the given absolute disk
* block number. This "raw" installation is used to place bootcode and
* image on a disk without a filesystem to make a simple boot disk. Useful
* in automated scripts for J. Random User.
* Note: *len == 0 when an image is read. It is set right afterwards.
*/
{
static char buf[_MAX_BLOCK_SIZE]; /* Nonvolatile block buffer. */
FILE *f;
off_t sec;
unsigned long devsize;
static int banner= 0;
struct partition entry;
/* See if the device has a maximum size. */
devsize= -1;
if (ioctl(rawfd, DIOCGETP, &entry) == 0) devsize= cv64ul(entry.size);
if ((f= fopen(file, "r")) == NULL) fatal(file);
/* Copy sectors from file onto the boot device. */
sec= *start;
do {
int off= sec % RATIO(BOOT_BLOCK_SIZE);
if (fread(buf + off * SECTOR_SIZE, 1, SECTOR_SIZE, f) == 0)
break;
if (sec >= devsize) {
fprintf(stderr,
"installboot: %s can't be attached to %s\n",
file, rawdev);
return 0;
}
if (off == RATIO(BOOT_BLOCK_SIZE) - 1) writeblock(sec / RATIO(BOOT_BLOCK_SIZE), buf, BOOT_BLOCK_SIZE);
} while (++sec != *start + *len);
if (ferror(f)) fatal(file);
(void) fclose(f);
/* Write a partial block, this may be the last image. */
if (sec % RATIO(BOOT_BLOCK_SIZE) != 0) writeblock(sec / RATIO(BOOT_BLOCK_SIZE), buf, BOOT_BLOCK_SIZE);
if (!banner) {
printf(" sector length\n");
banner= 1;
}
*len= sec - *start;
printf("%8ld%8ld %s\n", *start, *len, file);
*start= sec;
return 1;
}
enum howto { FS, BOOT };
void make_bootable(enum howto how, char *device, char *bootblock,
char *bootcode, char **imagev)
/* Install bootblock on the bootsector of device with the disk addresses to
* bootcode patched into the data segment of bootblock. "How" tells if there
* should or shoudn't be a file system on the disk. The images in the imagev
* vector are added to the end of the device.
*/
{
char buf[_MAX_BLOCK_SIZE + 256], *adrp, *parmp;
struct fileaddr {
off_t address;
int count;
} bootaddr[BOOT_MAX + 1], *bap= bootaddr;
struct exec boothdr;
struct image_header dummy;
struct stat st;
ino_t ino;
off_t sector, max_sector;
FILE *bootf;
off_t addr, fssize, pos, len;
char *labels, *label, *image;
int nolabel;
int block_size = 0;
/* Open device and set variables for readblock. */
if ((rawfd= open(rawdev= device, O_RDWR)) < 0) fatal(device);
/* Read and check the superblock. */
fssize= r_super(&block_size);
switch (how) {
case FS:
if (fssize == 0) {
fprintf(stderr,
"installboot: %s is not a Minix file system\n",
device);
exit(1);
}
break;
case BOOT:
if (fssize != 0) {
int s;
printf("%s contains a file system!\n", device);
printf("Scribbling in 10 seconds");
for (s= 0; s < 10; s++) {
fputc('.', stdout);
fflush(stdout);
sleep(1);
}
fputc('\n', stdout);
}
fssize= 1; /* Just a boot block. */
}
if (how == FS) {
/* See if the boot code can be found on the file system. */
if ((ino= r_lookup(ROOT_INO, bootcode)) == 0) {
if (errno != ENOENT) fatal(bootcode);
}
} else {
/* Boot code must be attached at the end. */
ino= 0;
}
if (ino == 0) {
/* For a raw installation, we need to copy the boot code onto
* the device, so we need to look at the file to be copied.
*/
if (stat(bootcode, &st) < 0) fatal(bootcode);
if ((bootf= fopen(bootcode, "r")) == NULL) fatal(bootcode);
} else {
/* Boot code is present in the file system. */
r_stat(ino, &st);
/* Get the header from the first block. */
if ((addr= r_vir2abs((off_t) 0)) == 0) {
boothdr.a_magic[0]= !A_MAGIC0;
} else {
readblock(addr, buf, block_size);
memcpy(&boothdr, buf, sizeof(struct exec));
}
bootf= NULL;
dummy.process= boothdr;
}
/* See if it is an executable (read_header does the check). */
read_header(0, bootcode, bootf, &dummy);
boothdr= dummy.process;
if (bootf != NULL) fclose(bootf);
/* Get all the sector addresses of the secondary boot code. */
max_sector= (boothdr.a_hdrlen + boothdr.a_text
+ boothdr.a_data + SECTOR_SIZE - 1) / SECTOR_SIZE;
if (max_sector > BOOT_MAX * RATIO(block_size)) {
fprintf(stderr, "installboot: %s is way too big\n", bootcode);
exit(0);
}
/* Determine the addresses to the boot code to be patched into the
* boot block.
*/
bap->count= 0; /* Trick to get the address recording going. */
for (sector= 0; sector < max_sector; sector++) {
if (ino == 0) {
addr= fssize + (sector / RATIO(block_size));
} else
if ((addr= r_vir2abs(sector / RATIO(block_size))) == 0) {
fprintf(stderr, "installboot: %s has holes!\n",
bootcode);
exit(1);
}
addr= (addr * RATIO(block_size)) + (sector % RATIO(block_size));
/* First address of the addresses array? */
if (bap->count == 0) bap->address= addr;
/* Paste sectors together in a multisector read. */
if (bap->address + bap->count == addr)
bap->count++;
else {
/* New address. */
bap++;
bap->address= addr;
bap->count= 1;
}
}
(++bap)->count= 0; /* No more. */
/* Get the boot block and patch the pieces in. */
readblock(BOOTBLOCK, buf, BOOT_BLOCK_SIZE);
if ((bootf= fopen(bootblock, "r")) == NULL) fatal(bootblock);
read_header(0, bootblock, bootf, &dummy);
boothdr= dummy.process;
if (boothdr.a_text + boothdr.a_data +
4 * (bap - bootaddr) + 1 > PARTPOS) {
fprintf(stderr,
"installboot: %s + addresses to %s don't fit in the boot sector\n",
bootblock, bootcode);
fprintf(stderr,
"You can try copying/reinstalling %s to defragment it\n",
bootcode);
exit(1);
}
/* All checks out right. Read bootblock into the boot block! */
bread(bootf, bootblock, buf, boothdr.a_text + boothdr.a_data);
(void) fclose(bootf);
/* Patch the addresses in. */
adrp= buf + (int) (boothdr.a_text + boothdr.a_data);
for (bap= bootaddr; bap->count != 0; bap++) {
*adrp++= bap->count;
*adrp++= (bap->address >> 0) & 0xFF;
*adrp++= (bap->address >> 8) & 0xFF;
*adrp++= (bap->address >> 16) & 0xFF;
}
/* Zero count stops bootblock's reading loop. */
*adrp++= 0;
if (bap > bootaddr+1) {
printf("%s and %d addresses to %s patched into %s\n",
bootblock, (int)(bap - bootaddr), bootcode, device);
}
/* Boot block signature. */
buf[SIGPOS+0]= (SIGNATURE >> 0) & 0xFF;
buf[SIGPOS+1]= (SIGNATURE >> 8) & 0xFF;
/* Sector 2 of the boot block is used for boot parameters, initially
* filled with null commands (newlines). Initialize it only if
* necessary.
*/
for (parmp= buf + SECTOR_SIZE; parmp < buf + 2*SECTOR_SIZE; parmp++) {
if (*imagev != NULL || (control(*parmp) && *parmp != '\n')) {
/* Param sector must be initialized. */
memset(buf + SECTOR_SIZE, '\n', SECTOR_SIZE);
break;
}
}
/* Offset to the end of the file system to add boot code and images. */
pos= fssize * RATIO(block_size);
if (ino == 0) {
/* Place the boot code onto the boot device. */
len= max_sector;
if (!raw_install(bootcode, &pos, &len, block_size)) {
if (how == FS) {
fprintf(stderr,
"\t(Isn't there a copy of %s on %s that can be used?)\n",
bootcode, device);
}
exit(1);
}
}
parmp= buf + SECTOR_SIZE;
nolabel= 0;
if (how == BOOT) {
/* A boot only disk needs to have floppies swapped. */
strcpy(parmp,
"trailer()echo \\nInsert the root diskette then hit RETURN\\n\\w\\c\n");
parmp+= strlen(parmp);
}
while ((labels= *imagev++) != NULL) {
/* Place each kernel image on the boot device. */
if ((image= strchr(labels, ':')) != NULL)
*image++= 0;
else {
if (nolabel) {
fprintf(stderr,
"installboot: Only one image can be the default\n");
exit(1);
}
nolabel= 1;
image= labels;
labels= NULL;
}
len= 0;
if (!raw_install(image, &pos, &len, block_size)) exit(1);
if (labels == NULL) {
/* Let this image be the default. */
sprintf(parmp, "image=%ld:%ld\n", pos-len, len);
parmp+= strlen(parmp);
}
while (labels != NULL) {
/* Image is prefixed by a comma separated list of
* labels. Define functions to select label and image.
*/
label= labels;
if ((labels= strchr(labels, ',')) != NULL) *labels++ = 0;
sprintf(parmp,
"%s(%c){label=%s;image=%ld:%ld;echo %s kernel selected;menu}\n",
label,
between('A', label[0], 'Z')
? label[0]-'A'+'a' : label[0],
label, pos-len, len, label);
parmp+= strlen(parmp);
}
if (parmp > buf + block_size) {
fprintf(stderr,
"installboot: Out of parameter space, too many images\n");
exit(1);
}
}
/* Install boot block. */
writeblock((off_t) BOOTBLOCK, buf, 1024);
if (pos > fssize * RATIO(block_size)) {
/* Tell the total size of the data on the device. */
printf("%16ld (%ld kb) total\n", pos,
(pos + RATIO(block_size) - 1) / RATIO(block_size));
}
}
static void install_master(const char *device, char *masterboot, char **guide)
/* Booting a hard disk is a two stage process: The master bootstrap in sector
* 0 loads the bootstrap from sector 0 of the active partition which in turn
* starts the operating system. This code installs such a master bootstrap
* on a hard disk. If guide[0] is non-null then the master bootstrap is
* guided into booting a certain device.
*/
{
FILE *masf;
unsigned long size;
struct stat st;
static char buf[_MAX_BLOCK_SIZE];
/* Open device. */
if ((rawfd= open(rawdev= device, O_RDWR)) < 0) fatal(device);
/* Open the master boot code. */
if ((masf= fopen(masterboot, "r")) == NULL) fatal(masterboot);
/* See if the user is cloning a device. */
if (fstat(fileno(masf), &st) >=0 && S_ISBLK(st.st_mode))
size= PARTPOS;
else {
/* Read and check header otherwise. */
struct image_header ihdr;
read_header(1, masterboot, masf, &ihdr);
size= ihdr.process.a_text + ihdr.process.a_data;
}
if (size > PARTPOS) {
fprintf(stderr, "installboot: %s is too big\n", masterboot);
exit(1);
}
/* Read the master boot block, patch it, write. */
readblock(BOOTBLOCK, buf, BOOT_BLOCK_SIZE);
memset(buf, 0, PARTPOS);
(void) bread(masf, masterboot, buf, size);
if (guide[0] != NULL) {
/* Fixate partition to boot. */
const char *keys= guide[0];
const char *logical= guide[1];
size_t i;
int logfd;
u32_t offset;
struct partition geometry;
/* A string of digits to be seen as keystrokes. */
i= 0;
do {
if (!between('0', keys[i], '9')) {
fprintf(stderr,
"installboot: bad guide keys '%s'\n",
keys);
exit(1);
}
} while (keys[++i] != 0);
if (size + i + 1 > PARTPOS) {
fprintf(stderr,
"installboot: not enough space after '%s' for '%s'\n",
masterboot, keys);
exit(1);
}
memcpy(buf + size, keys, i);
size += i;
buf[size]= '\r';
if (logical != NULL) {
if ((logfd= open(logical, O_RDONLY)) < 0
|| ioctl(logfd, DIOCGETP, &geometry) < 0
) {
fatal(logical);
}
offset= div64u(geometry.base, SECTOR_SIZE);
if (size + 5 > PARTPOS) {
fprintf(stderr,
"installboot: not enough space "
"after '%s' for '%s' and an offset "
"to '%s'\n",
masterboot, keys, logical);
exit(1);
}
buf[size]= '#';
memcpy(buf+size+1, &offset, 4);
}
}
/* Install signature. */
buf[SIGPOS+0]= (SIGNATURE >> 0) & 0xFF;
buf[SIGPOS+1]= (SIGNATURE >> 8) & 0xFF;
writeblock(BOOTBLOCK, buf, BOOT_BLOCK_SIZE);
}
static void usage(void)
{
fprintf(stderr,
"Usage: installboot -i(mage) image kernel mm fs ... init\n"
" installboot -(e)x(tract) image\n"
" installboot -d(evice) device bootblock boot [image ...]\n"
" installboot -b(oot) device bootblock boot image ...\n"
" installboot -m(aster) device masterboot [keys [logical]]\n");
exit(1);
}
static int isoption(const char *option, const char *test)
/* Check if the option argument is equals "test". Also accept -i as short
* for -image, and the special case -x for -extract.
*/
{
if (strcmp(option, test) == 0) return 1;
if (option[0] != '-' && strlen(option) != 2) return 0;
if (option[1] == test[1]) return 1;
if (option[1] == 'x' && test[1] == 'e') return 1;
return 0;
}
int main(int argc, char **argv)
{
if (argc < 2) usage();
if (argc >= 4 && isoption(argv[1], "-image")) {
make_image(argv[2], argv + 3);
} else
if (argc == 3 && isoption(argv[1], "-extract")) {
extract_image(argv[2]);
} else
if (argc >= 5 && isoption(argv[1], "-device")) {
make_bootable(FS, argv[2], argv[3], argv[4], argv + 5);
} else
if (argc >= 6 && isoption(argv[1], "-boot")) {
make_bootable(BOOT, argv[2], argv[3], argv[4], argv + 5);
} else
if ((4 <= argc && argc <= 6) && isoption(argv[1], "-master")) {
install_master(argv[2], argv[3], argv + 4);
} else {
usage();
}
exit(0);
}
/*
* $PchId: installboot.c,v 1.10 2000/08/13 22:07:50 philip Exp $
*/

View File

@ -1,19 +0,0 @@
# jumpboot: supplementary MBR code (alternate to masterboot)
.include <bsd.own.mk>
# XXX: Can only be built with ACK currently
.include "${MINIXSRCDIR}/boot/minix.ack16.mk"
AFLAGS+= -Was-ncc
STRIPFLAG= -s
PROG= jumpboot
SRCS= jumpboot.s
BINDIR= /usr/mdec
MAN=
LIBC= # defined, to silence bsd.*.mk
.include <bsd.prog.mk>

View File

@ -1,261 +0,0 @@
! jumpboot 1.0 - Jump to another bootstrap Author: Kees J. Bot
! 14 Apr 1999
!
! This code may be placed into any free boot sector, like the first sector
! of an extended partition, a file system partition other than the root,
! or even the master bootstrap. It will load and run another bootstrap whose
! disk, partition, and slice number (not necessarily all three) are patched
! into this code by installboot. If the ALT key is held down when this code
! is booted then you can type the disk, partition, and slice numbers manually.
! The manual interface is default if no numbers are patched in by installboot.
!
o32 = 0x66 ! This assembler doesn't know 386 extensions
LOADOFF = 0x7C00 ! 0x0000:LOADOFF is where this code is loaded
BUFFER = 0x0600 ! First free memory
PART_TABLE = 446 ! Location of partition table within master
PENTRYSIZE = 16 ! Size of one partition table entry
MAGIC = 510 ! Location of the AA55 magic number
! <ibm/partition.h>:
MINIX_PART = 0x81
sysind = 4
lowsec = 8
.text
! Find and load another bootstrap and jump to it.
jumpboot:
xor ax, ax
mov ds, ax
mov es, ax
cli
mov ss, ax ! ds = es = ss = Vector segment
mov sp, #LOADOFF
sti
! Move this code to safety, then jump to it.
mov si, sp ! si = start of this code
mov di, #BUFFER ! di = Buffer area
mov cx, #512/2 ! One sector
cld
rep movs
jmpf BUFFER+migrate, 0 ! To safety
migrate:
mov bp, #BUFFER+guide ! Patched guiding characters
altkey:
movb ah, #0x02 ! Keyboard shift status
int 0x16
testb al, #0x08 ! Bit 3 = ALT key
jz noalt ! ALT key pressed?
again:
mov bp, #zero ! Ignore patched stuff
noalt:
! Follow guide characters to find the boot partition.
call print
.ascii "d?\b\0" ! Initial greeting
! Disk number?
disk:
movb dl, #0x80 - 0x30 ! Prepare to add an ASCII digit
call getch ! Get number to tell which disk
addb dl, al ! dl = 0x80 + (al - '0')
jns n0nboot ! Result should be >= 0x80
mov si, #BUFFER+zero-lowsec ! si = where lowsec(si) is zero
cmpb (bp), #0x23 ! Next guide character is '#'?
jne notlogical
lea si, 1-lowsec(bp) ! Logical sector offset follows '#'
notlogical:
call load ! Load chosen sector of chosen disk
cmpb (bp), #0x23
je boot ! Run bootstrap if a logical is chosen
call print ! Intro to partition number
.ascii "p?\b\0"
part:
call getch ! Get character to tell partition
call gettable ! Get partition table
call sort ! Sort partition table
call choose_load ! Compute chosen entry and load
cmpb sysind(si), #MINIX_PART ! Minix subpartition table possible?
jne waitboot
call print ! Intro to slice number
.ascii "s?\b\0"
slice:
call getch ! Get character to tell slice
call gettable ! Get partition table
call choose_load ! Compute chosen entry and load
waitboot:
call print ! Intro to nothing
.ascii " ?\b\0"
call getch ! Supposed to type RETURN now
n0nboot:jmp nonboot ! Sorry, can't go further
! Get a character, either the patched-in, or one from the keyboard.
getch:
movb al, (bp) ! Get patched-in character
testb al, al
jz getkey
inc bp
jmp gotkey
getkey: xorb ah, ah ! Wait for keypress
int 0x16
gotkey: testb dl, dl ! Ignore CR if disk number not yet set
jns putch
cmpb al, #0x0D ! Carriage return?
je boot
!jmp putch
! Print a character
putch: movb ah, #0x0E ! Print character in teletype mode
mov bx, #0x0001 ! Page 0, foreground color
int 0x10
ret
! Print a message.
print: mov cx, si ! Save si
pop si ! si = String following 'call print'
prnext: lodsb ! al = *si++ is char to be printed
testb al, al ! Null marks end
jz prdone
call putch
jmp prnext
prdone: xchg si, cx ! Restore si
jmp (cx) ! Continue after the string
! Return typed (or in patched data) means to run the bootstrap now in core!
boot:
call print ! Make line on screen look proper
.ascii "\b \r\n\0"
jmp LOADOFF-BUFFER ! Jump to LOADOFF
! Compute address of chosen partition entry from choice al into si, then
! continue to load the boot sector of that partition.
choose_load:
subb al, #0x30 ! al -= '0'
cmpb al, #4 ! Only four partitions
ja n0nboot
movb ah, #PENTRYSIZE
mulb ah ! al *= PENTRYSIZE
add ax, #BUFFER+PART_TABLE
mov si, ax ! si = &part_table[al - '0']
movb al, sysind(si) ! System indicator
testb al, al ! Unused partition?
jz n0nboot
!jmp load ! Continue to load boot sector
! Load boot sector of the current partition.
load:
push dx ! Save drive code
push es ! Next call sets es
movb ah, #0x08 ! Code for drive parameters
int 0x13
pop es
andb cl, #0x3F ! cl = max sector number (1-origin)
incb dh ! dh = 1 + max head number (0-origin)
movb al, cl ! al = cl = sectors per track
mulb dh ! dh = heads, ax = heads * sectors
mov bx, ax ! bx = sectors per cylinder = heads * sectors
mov ax, lowsec+0(si)
mov dx, lowsec+2(si) ! dx:ax = sector within drive
cmp dx, #[1024*255*63-255]>>16 ! Near 8G limit?
jae bigdisk
div bx ! ax = cylinder, dx = sector within cylinder
xchg ax, dx ! ax = sector within cylinder, dx = cylinder
movb ch, dl ! ch = low 8 bits of cylinder
divb cl ! al = head, ah = sector (0-origin)
xorb dl, dl ! About to shift bits 8-9 of cylinder into dl
shr dx, #1
shr dx, #1 ! dl[6..7] = high cylinder
orb dl, ah ! dl[0..5] = sector (0-origin)
movb cl, dl ! cl[0..5] = sector, cl[6..7] = high cyl
incb cl ! cl[0..5] = sector (1-origin)
pop dx ! Restore drive code in dl
movb dh, al ! dh = al = head
mov bx, #LOADOFF ! es:bx = where sector is loaded
mov ax, #0x0201 ! ah = Code for read / al = one sector
int 0x13
jmp rdeval ! Evaluate read result
bigdisk:
mov bx, dx ! bx:ax = dx:ax = sector to read
pop dx ! Restore drive code in dl
push si ! Save si
mov si, #BUFFER+ext_rw ! si = extended read/write parameter packet
mov 8(si), ax ! Starting block number = bx:ax
mov 10(si), bx
movb ah, #0x42 ! Extended read
int 0x13
pop si ! Restore si to point to partition entry
!jmp rdeval
rdeval:
jnc rdok
rderr:
call print
.ascii "\r\nRead error\r\n\0"
jmp again
rdok:
cmp LOADOFF+MAGIC, #0xAA55
je sigok ! Signature ok?
nonboot:
call print
.ascii "\r\nNot bootable\r\n\0"
jmp again
sigok:
ret
! Get the partition table into my space.
gettable:
mov si, #LOADOFF+PART_TABLE
mov di, #BUFFER+PART_TABLE
mov cx, #4*PENTRYSIZE/2
rep movs
ret
! Sort the partition table.
sort:
mov cx, #4 ! Four times is enough to sort
bubble: mov si, #BUFFER+PART_TABLE ! First table entry
bubble1:lea di, PENTRYSIZE(si) ! Next entry
cmpb sysind(si), ch ! Partition type, nonzero when in use
jz exchg ! Unused entries sort to the end
inuse: mov bx, lowsec+0(di)
sub bx, lowsec+0(si) ! Compute di->lowsec - si->lowsec
mov bx, lowsec+2(di)
sbb bx, lowsec+2(si)
jae order ! In order if si->lowsec <= di->lowsec
exchg: movb bl, (si)
xchgb bl, PENTRYSIZE(si) ! Exchange entries byte by byte
movb (si), bl
inc si
cmp si, di
jb exchg
order: mov si, di
cmp si, #BUFFER+PART_TABLE+3*PENTRYSIZE
jb bubble1
loop bubble
ret
.data
! Extended read/write commands require a parameter packet.
ext_rw:
.data1 0x10 ! Length of extended r/w packet
.data1 0 ! Reserved
.data2 1 ! Blocks to transfer (just one)
.data2 LOADOFF ! Buffer address offset
.data2 0 ! Buffer address segment
.data4 0 ! Starting block number low 32 bits (tbfi)
zero: .data4 0 ! Starting block number high 32 bits
.align 2
guide:
! Guide characters and possibly a logical partition number patched here by
! installboot, up to 6 bytes maximum.

View File

@ -1,20 +0,0 @@
# masterboot: MBR code, first to run, 16-bit mode
.include <bsd.own.mk>
# XXX: Can only be built with ACK currently
.include "${MINIXSRCDIR}/boot/minix.ack16.mk"
AFLAGS+= -Was-ncc
STRIPFLAG= -s
PROG= masterboot
SRCS= masterboot.s
BINDIR= /usr/mdec
MAN=
LIBC= # defined, to silence bsd.*.mk
.include <bsd.prog.mk>

View File

@ -1,218 +0,0 @@
! masterboot 2.0 - Master boot block code Author: Kees J. Bot
!
! This code may be placed in the first sector (the boot sector) of a floppy,
! hard disk or hard disk primary partition. There it will perform the
! following actions at boot time:
!
! - If the booted device is a hard disk and one of the partitions is active
! then the active partition is booted.
!
! - Otherwise the next floppy or hard disk device is booted, trying them one
! by one.
!
! To make things a little clearer, the boot path might be:
! /dev/fd0 - Floppy disk containing data, tries fd1 then d0
! [/dev/fd1] - Drive empty
! /dev/c0d0 - Master boot block, selects active partition 2
! /dev/c0d0p2 - Submaster, selects active subpartition 0
! /dev/c0d0p2s0 - Minix bootblock, reads Boot Monitor /boot
! Minix - Started by /boot from a kernel image in /minix
LOADOFF = 0x7C00 ! 0x0000:LOADOFF is where this code is loaded
BUFFER = 0x0600 ! First free memory
PART_TABLE = 446 ! Location of partition table within this code
PENTRYSIZE = 16 ! Size of one partition table entry
MAGIC = 510 ! Location of the AA55 magic number
! <ibm/partition>.h:
bootind = 0
sysind = 4
lowsec = 8
.text
! Find active (sub)partition, load its first sector, run it.
master:
xor ax, ax
mov ds, ax
mov es, ax
cli
mov ss, ax ! ds = es = ss = Vector segment
mov sp, #LOADOFF
sti
! Copy this code to safety, then jump to it.
mov si, sp ! si = start of this code
push si ! Also where we'll return to eventually
mov di, #BUFFER ! Buffer area
mov cx, #512/2 ! One sector
cld
rep movs
jmpf BUFFER+migrate, 0 ! To safety
migrate:
! Find the active partition
findactive:
testb dl, dl
jns nextdisk ! No bootable partitions on floppies
mov si, #BUFFER+PART_TABLE
find: cmpb sysind(si), #0 ! Partition type, nonzero when in use
jz nextpart
testb bootind(si), #0x80 ! Active partition flag in bit 7
jz nextpart ! It's not active
loadpart:
call load ! Load partition bootstrap
jc error1 ! Not supposed to fail
bootstrap:
ret ! Jump to the master bootstrap
nextpart:
add si, #PENTRYSIZE
cmp si, #BUFFER+PART_TABLE+4*PENTRYSIZE
jb find
! No active partition, tell 'em
call print
.ascii "No active partition\0"
jmp reboot
! There are no active partitions on this drive, try the next drive.
nextdisk:
incb dl ! Increment dl for the next drive
testb dl, dl
js nexthd ! Hard disk if negative
int 0x11 ! Get equipment configuration
shl ax, #1 ! Highest floppy drive # in bits 6-7
shl ax, #1 ! Now in bits 0-1 of ah
andb ah, #0x03 ! Extract bits
cmpb dl, ah ! Must be dl <= ah for drive to exist
ja nextdisk ! Otherwise try disk 0 eventually
call load0 ! Read the next floppy bootstrap
jc nextdisk ! It failed, next disk please
ret ! Jump to the next master bootstrap
nexthd: call load0 ! Read the hard disk bootstrap
error1: jc error ! No disk?
ret
! Load sector 0 from the current device. It's either a floppy bootstrap or
! a hard disk master bootstrap.
load0:
mov si, #BUFFER+zero-lowsec ! si = where lowsec(si) is zero
!jmp load
! Load sector lowsec(si) from the current device. The obvious head, sector,
! and cylinder numbers are ignored in favour of the more trustworthy absolute
! start of partition.
load:
mov di, #3 ! Three retries for floppy spinup
retry: push dx ! Save drive code
push es
push di ! Next call destroys es and di
movb ah, #0x08 ! Code for drive parameters
int 0x13
pop di
pop es
andb cl, #0x3F ! cl = max sector number (1-origin)
incb dh ! dh = 1 + max head number (0-origin)
movb al, cl ! al = cl = sectors per track
mulb dh ! dh = heads, ax = heads * sectors
mov bx, ax ! bx = sectors per cylinder = heads * sectors
mov ax, lowsec+0(si)
mov dx, lowsec+2(si)! dx:ax = sector within drive
cmp dx, #[1024*255*63-255]>>16 ! Near 8G limit?
jae bigdisk
div bx ! ax = cylinder, dx = sector within cylinder
xchg ax, dx ! ax = sector within cylinder, dx = cylinder
movb ch, dl ! ch = low 8 bits of cylinder
divb cl ! al = head, ah = sector (0-origin)
xorb dl, dl ! About to shift bits 8-9 of cylinder into dl
shr dx, #1
shr dx, #1 ! dl[6..7] = high cylinder
orb dl, ah ! dl[0..5] = sector (0-origin)
movb cl, dl ! cl[0..5] = sector, cl[6..7] = high cyl
incb cl ! cl[0..5] = sector (1-origin)
pop dx ! Restore drive code in dl
movb dh, al ! dh = al = head
mov bx, #LOADOFF ! es:bx = where sector is loaded
mov ax, #0x0201 ! Code for read, just one sector
int 0x13 ! Call the BIOS for a read
jmp rdeval ! Evaluate read result
bigdisk:
mov bx, dx ! bx:ax = dx:ax = sector to read
pop dx ! Restore drive code in dl
push si ! Save si
mov si, #BUFFER+ext_rw ! si = extended read/write parameter packet
mov 8(si), ax ! Starting block number = bx:ax
mov 10(si), bx
movb ah, #0x42 ! Extended read
int 0x13
pop si ! Restore si to point to partition entry
!jmp rdeval
rdeval:
jnc rdok ! Read succeeded
cmpb ah, #0x80 ! Disk timed out? (Floppy drive empty)
je rdbad
dec di
jl rdbad ! Retry count expired
xorb ah, ah
int 0x13 ! Reset
jnc retry ! Try again
rdbad: stc ! Set carry flag
ret
rdok: cmp LOADOFF+MAGIC, #0xAA55
jne nosig ! Error if signature wrong
ret ! Return with carry still clear
nosig: call print
.ascii "Not bootable\0"
jmp reboot
! A read error occurred, complain and hang
error:
mov si, #LOADOFF+errno+1
prnum: movb al, ah ! Error number in ah
andb al, #0x0F ! Low 4 bits
cmpb al, #10 ! A-F?
jb digit ! 0-9!
addb al, #7 ! 'A' - ':'
digit: addb (si), al ! Modify '0' in string
dec si
movb cl, #4 ! Next 4 bits
shrb ah, cl
jnz prnum ! Again if digit > 0
call print
.ascii "Read error "
errno: .ascii "00\0"
!jmp reboot
reboot:
call print
.ascii ". Hit any key to reboot.\0"
xorb ah, ah ! Wait for keypress
int 0x16
call print
.ascii "\r\n\0"
int 0x19
! Print a message.
print: pop si ! si = String following 'call print'
prnext: lodsb ! al = *si++ is char to be printed
testb al, al ! Null marks end
jz prdone
movb ah, #0x0E ! Print character in teletype mode
mov bx, #0x0001 ! Page 0, foreground color
int 0x10
jmp prnext
prdone: jmp (si) ! Continue after the string
.data
! Extended read/write commands require a parameter packet.
ext_rw:
.data1 0x10 ! Length of extended r/w packet
.data1 0 ! Reserved
.data2 1 ! Blocks to transfer (just one)
.data2 LOADOFF ! Buffer address offset
.data2 0 ! Buffer address segment
.data4 0 ! Starting block number low 32 bits (tbfi)
zero: .data4 0 ! Starting block number high 32 bits

View File

@ -1,12 +0,0 @@
# Makefile fragment to use Ack compiler (16-bit i86 target)
ARCH= i86
LIBDIR= /usr/lib/i86 # force
CC:=${CC:C/.*[gp]cc/cc/:C/clang/cc/}
AR=aal
COMPILER_TYPE=ack
OBJECT_FMT=a.out
CPPFLAGS+= -mi86
AFLAGS+= -mi86
LDFLAGS+= -mi86 -.o $(MINIXID) # no crtso
MINIXID?= -com # common I+D default

View File

@ -1,313 +0,0 @@
/* rawfs.c - Raw Minix file system support. Author: Kees J. Bot
* 23 Dec 1991
* Based on readfs by Paul Polderman
*/
#define _POSIX_SOURCE 1
#define _MINIX 1
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>
#include <errno.h>
#include <minix/config.h>
#include <minix/const.h>
#include <minix/type.h>
#include <servers/mfs/const.h>
#include <servers/mfs/type.h>
#include <servers/mfs/super.h>
#include <servers/mfs/inode.h>
#include "rawfs.h"
#include <servers/mfs/buf.h>
void readblock(off_t blockno, char *buf, int);
/* The following code handles two file system types: Version 1 with small
* inodes and 16-bit disk addresses and Version 2 with big inodes and 32-bit
* disk addresses.
#ifdef FLEX
* To make matters worse, Minix-vmd knows about the normal Unix Version 7
* directories and directories with flexible entries.
#endif
*/
/* File system parameters. */
static unsigned nr_dzones; /* Fill these in after reading superblock. */
static unsigned nr_indirects;
static unsigned inodes_per_block;
static int block_size;
#if __minix_vmd
static struct v12_super_block super; /* Superblock of file system */
#define s_log_zone_size s_dummy /* Zones are obsolete. */
#else
static struct super_block super; /* Superblock of file system */
#define SUPER_V1 SUPER_MAGIC /* V1 magic has a weird name. */
#endif
static struct inode curfil; /* Inode of file under examination */
static char indir[_MAX_BLOCK_SIZE]; /* Single indirect block. */
static char dindir[_MAX_BLOCK_SIZE]; /* Double indirect block. */
static char dirbuf[_MAX_BLOCK_SIZE]; /* Scratch/Directory block. */
#define scratch dirbuf
static block_t a_indir, a_dindir; /* Addresses of the indirects. */
static off_t dirpos; /* Reading pos in a dir. */
#define fsbuf(b) (* (union fsdata_u *) (b))
#define zone_shift (super.s_log_zone_size) /* zone to block ratio */
off_t r_super(int *bs)
/* Initialize variables, return size of file system in blocks,
* (zero on error).
*/
{
/* Read superblock. (The superblock is always at 1kB offset,
* that's why we lie to readblock and say the block size is 1024
* and we want block number 1 (the 'second block', at offset 1kB).)
*/
readblock(1, scratch, 1024);
memcpy(&super, scratch, sizeof(super));
/* Is it really a MINIX file system ? */
if (super.s_magic == SUPER_V2 || super.s_magic == SUPER_V3) {
if(super.s_magic == SUPER_V2)
super.s_block_size = 1024;
*bs = block_size = super.s_block_size;
if(block_size < _MIN_BLOCK_SIZE ||
block_size > _MAX_BLOCK_SIZE) {
return 0;
}
nr_dzones= V2_NR_DZONES;
nr_indirects= V2_INDIRECTS(block_size);
inodes_per_block= V2_INODES_PER_BLOCK(block_size);
return (off_t) super.s_zones << zone_shift;
} else
if (super.s_magic == SUPER_V1) {
*bs = block_size = 1024;
nr_dzones= V1_NR_DZONES;
nr_indirects= V1_INDIRECTS;
inodes_per_block= V1_INODES_PER_BLOCK;
return (off_t) super.s_nzones << zone_shift;
} else {
/* Filesystem not recognized as Minix. */
return 0;
}
}
void r_stat(Ino_t inum, struct stat *stp)
/* Return information about a file like stat(2) and remember it. */
{
block_t block;
block_t ino_block;
ino_t ino_offset;
union fsdata_u *blockbuf;
/* Calculate start of i-list */
block = START_BLOCK + super.s_imap_blocks + super.s_zmap_blocks;
/* Calculate block with inode inum */
ino_block = ((inum - 1) / inodes_per_block);
ino_offset = ((inum - 1) % inodes_per_block);
block += ino_block;
/* Fetch the block */
blockbuf = (union fsdata_u *) scratch;
readblock(block, (char *) blockbuf, block_size);
if (super.s_magic == SUPER_V2 || super.s_magic == SUPER_V3) {
d2_inode *dip;
int i;
dip= &blockbuf->b__v2_ino[(unsigned int) ino_offset];
curfil.i_mode= dip->d2_mode;
curfil.i_nlinks= dip->d2_nlinks;
curfil.i_uid= dip->d2_uid;
curfil.i_gid= dip->d2_gid;
curfil.i_size= dip->d2_size;
curfil.i_atime= dip->d2_atime;
curfil.i_mtime= dip->d2_mtime;
curfil.i_ctime= dip->d2_ctime;
for (i= 0; i < V2_NR_TZONES; i++)
curfil.i_zone[i]= dip->d2_zone[i];
} else {
d1_inode *dip;
int i;
dip= &blockbuf->b__v1_ino[(unsigned int) ino_offset];
curfil.i_mode= dip->d1_mode;
curfil.i_nlinks= dip->d1_nlinks;
curfil.i_uid= dip->d1_uid;
curfil.i_gid= dip->d1_gid;
curfil.i_size= dip->d1_size;
curfil.i_atime= dip->d1_mtime;
curfil.i_mtime= dip->d1_mtime;
curfil.i_ctime= dip->d1_mtime;
for (i= 0; i < V1_NR_TZONES; i++)
curfil.i_zone[i]= dip->d1_zone[i];
}
curfil.i_dev= -1; /* Can't fill this in alas. */
curfil.i_num= inum;
stp->st_dev= curfil.i_dev;
stp->st_ino= curfil.i_num;
stp->st_mode= curfil.i_mode;
stp->st_nlink= curfil.i_nlinks;
stp->st_uid= curfil.i_uid;
stp->st_gid= curfil.i_gid;
stp->st_rdev= (dev_t) curfil.i_zone[0];
stp->st_size= curfil.i_size;
stp->st_atime= curfil.i_atime;
stp->st_mtime= curfil.i_mtime;
stp->st_ctime= curfil.i_ctime;
a_indir= a_dindir= 0;
dirpos= 0;
}
ino_t r_readdir(char *name)
/* Read next directory entry at "dirpos" from file "curfil". */
{
ino_t inum= 0;
int blkpos;
struct direct *dp;
if (!S_ISDIR(curfil.i_mode)) { errno= ENOTDIR; return -1; }
if(!block_size) { errno = 0; return -1; }
while (inum == 0 && dirpos < curfil.i_size) {
if ((blkpos= (int) (dirpos % block_size)) == 0) {
/* Need to fetch a new directory block. */
readblock(r_vir2abs(dirpos / block_size), dirbuf, block_size);
}
/* Let dp point to the next entry. */
dp= (struct direct *) (dirbuf + blkpos);
if ((inum= dp->mfs_d_ino) != 0) {
/* This entry is occupied, return name. */
strncpy(name, dp->mfs_d_name, sizeof(dp->mfs_d_name));
name[sizeof(dp->mfs_d_name)]= 0;
}
dirpos+= DIR_ENTRY_SIZE;
}
return inum;
}
off_t r_vir2abs(off_t virblk)
/* Translate a block number in a file to an absolute disk block number.
* Returns 0 for a hole and -1 if block is past end of file.
*/
{
block_t b= virblk;
zone_t zone, ind_zone;
block_t z, zone_index;
int i;
if(!block_size) return -1;
/* Check if virblk within file. */
if (virblk * block_size >= curfil.i_size) return -1;
/* Calculate zone in which the datablock number is contained */
zone = (zone_t) (b >> zone_shift);
/* Calculate index of the block number in the zone */
zone_index = b - ((block_t) zone << zone_shift);
/* Go get the zone */
if (zone < (zone_t) nr_dzones) { /* direct block */
zone = curfil.i_zone[(int) zone];
z = ((block_t) zone << zone_shift) + zone_index;
return z;
}
/* The zone is not a direct one */
zone -= (zone_t) nr_dzones;
/* Is it single indirect ? */
if (zone < (zone_t) nr_indirects) { /* single indirect block */
ind_zone = curfil.i_zone[nr_dzones];
} else { /* double indirect block */
/* Fetch the double indirect block */
if ((ind_zone = curfil.i_zone[nr_dzones + 1]) == 0) return 0;
z = (block_t) ind_zone << zone_shift;
if (a_dindir != z) {
readblock(z, dindir, block_size);
a_dindir= z;
}
/* Extract the indirect zone number from it */
zone -= (zone_t) nr_indirects;
i = zone / (zone_t) nr_indirects;
ind_zone = (super.s_magic == SUPER_V2 || super.s_magic == SUPER_V3)
? fsbuf(dindir).b__v2_ind[i]
: fsbuf(dindir).b__v1_ind[i];
zone %= (zone_t) nr_indirects;
}
if (ind_zone == 0) return 0;
/* Extract the datablock number from the indirect zone */
z = (block_t) ind_zone << zone_shift;
if (a_indir != z) {
readblock(z, indir, block_size);
a_indir= z;
}
zone = (super.s_magic == SUPER_V2 || super.s_magic == SUPER_V3)
? fsbuf(indir).b__v2_ind[(int) zone]
: fsbuf(indir).b__v1_ind[(int) zone];
/* Calculate absolute datablock number */
z = ((block_t) zone << zone_shift) + zone_index;
return z;
}
ino_t r_lookup(Ino_t cwd, const char *path)
/* Translates a pathname to an inode number. This is just a nice utility
* function, it only needs r_stat and r_readdir.
*/
{
char name[MFS_DIRSIZ+1], r_name[MFS_DIRSIZ+1];
char *n;
struct stat st;
ino_t ino;
ino= path[0] == '/' ? ROOT_INO : cwd;
for (;;) {
if (ino == 0) {
errno= ENOENT;
return 0;
}
while (*path == '/') path++;
if (*path == 0) return ino;
r_stat(ino, &st);
if (!S_ISDIR(st.st_mode)) {
errno= ENOTDIR;
return 0;
}
n= name;
while (*path != 0 && *path != '/')
if (n < name + MFS_DIRSIZ) *n++ = *path++;
*n= 0;
while ((ino= r_readdir(r_name)) != 0
&& strcmp(name, r_name) != 0) {
}
}
}
/*
* $PchId: rawfs.c,v 1.8 1999/11/05 23:14:15 philip Exp $
*/

View File

@ -1,51 +0,0 @@
/* rawfs.h - Raw Minix file system support. Author: Kees J. Bot
*
* off_t r_super(int *block_size);
* Initialize variables, returns the size of a valid Minix
* file system blocks, but zero on error.
*
* void r_stat(ino_t file, struct stat *stp);
* Return information about a file like stat(2) and
* remembers file for the next two calls.
*
* off_t r_vir2abs(off_t virblockno);
* Translate virtual block number in file to absolute
* disk block number. Returns 0 if the file contains
* a hole, or -1 if the block lies past the end of file.
*
* ino_t r_readdir(char *name);
* Return next directory entry or 0 if there are no more.
* Returns -1 and sets errno on error.
*
* ino_t r_lookup(ino_t cwd, const char *path);
* A utility function that translates a pathname to an
* inode number. It starts from directory "cwd" unless
* path starts with a '/', then from ROOT_INO.
* Returns 0 and sets errno on error.
*
* One function needs to be provided by the outside world:
*
* void readblock(off_t blockno, char *buf, int block_size);
* Read a block into the buffer. Outside world handles
* errors.
*/
#ifndef INC_RAWFS_H
#define INC_RAWFS_H
#include <minix/dirent.h>
#include <servers/mfs/mfsdir.h>
#define ROOT_INO ((ino_t) 1) /* Inode nr of root dir. */
extern off_t r_super(int *);
extern void r_stat(Ino_t file, struct stat *stp);
extern off_t r_vir2abs(off_t virblockno);
extern ino_t r_readdir(char *name);
extern ino_t r_lookup(Ino_t cwd, const char *path);
/*
* $PchId: rawfs.h,v 1.4 1996/04/19 08:16:36 philip Exp $
*/
#endif

View File

@ -1,28 +0,0 @@
#!/bin/sh
set -e
MDEC=/usr/mdec
BOOT=/boot/boot
ROOT=`printroot -r`
if [ ! -b "$ROOT" ]
then echo root device $ROOT not found
exit 1
fi
echo -n "Install boot as $BOOT on current root and patch into $ROOT? (y/N) "
read ans
if [ ! "$ans" = y ]
then echo Aborting.
exit 1
fi
make install || true
echo Installing boot monitor into $BOOT.
cp $MDEC/boot $BOOT
echo Patching position of $BOOT into $ROOT.
installboot_minix -d "$ROOT" $MDEC/bootblock $BOOT
sync

View File

@ -1,28 +0,0 @@
#!/bin/sh
#
# M, U - mount or unmount standard devices.
case $#:$2 in
1:|2:-r) ;;
*) echo "Usage: $0 <abbreviation> [-r]" >&2; exit 1
esac
. /etc/fstab
dev=$1 dir=$1
case $1 in
0) dev=/dev/fd0 dir=fd0 ;;
1) dev=/dev/fd1 dir=fd1 ;;
PS0|at0|fd0|pat0|pc0|ps0) dev=/dev/$dev dir=fd0 ;;
PS1|at1|fd1|pat1|pc1|ps1) dev=/dev/$dev dir=fd1 ;;
root) dev=$root ;;
tmp) dev=$tmp ;;
usr) dev=$usr ;;
*) dev=/dev/$dev dir=mnt
esac
case $0 in
*M) mount $dev /$dir $2 ;;
*U) umount $dev
esac

View File

@ -1,7 +0,0 @@
SCRIPTS= M.sh
BINDIR= /bin
MAN=
LINKS+= ${BINDIR}/M ${BINDIR}/U
.include <bsd.prog.mk>

View File

@ -2,22 +2,22 @@
.include <bsd.own.mk>
SUBDIR= aal add_route arp ash at autil awk \
backup badblocks banner basename binpackage \
binpackages btrace cal calendar \
cat cawf cd cdprobe checkhier chmem \
SUBDIR= add_route arp ash at autil awk \
backup badblocks banner basename \
btrace cal calendar \
cat cawf cd cdprobe checkhier \
chmod chown chroot ci cksum cleantmp clear cmp co \
comm compress cp crc cron crontab cut date \
comm compress cp crc cron crontab cut \
dd decomp16 DESCRIBE dev2name devsize df dhcpd \
dhrystone diff dirname dis386 dis88 diskctl du dumpcore \
dhrystone diff dirname diskctl du dumpcore \
ed eject elle elvis env expand factor fbdctl file \
find finger fingerd fix fold format fortune fsck.mfs \
ftp101 gcore gcov-pull getty grep head hexdump host \
hostaddr id ifconfig ifdef install \
intr ipcrm ipcs irdpd isoread join kill last leave \
less lex loadkeys loadramdisk logger login look lp \
lpd ls lspci M mail make MAKEDEV \
mdb mesg mined ackmkdep mkfifo mkfs.mfs mknod \
lpd ls lspci mail make MAKEDEV \
mdb mesg mined mkfifo mkfs.mfs mknod \
mkproto modem mount mt netconf newroot nice acknm nohup \
nonamed od paste patch pax \
ping postinstall poweroff pr prep printf printroot \
@ -25,7 +25,7 @@ SUBDIR= aal add_route arp ash at autil awk \
ramdisk rarpd rawspeed rcp rdate readall readclock \
reboot remsync rev rget rlogin rlogind \
rotate rsh rshd sed service setup shar acksize \
sleep slip sort spell split srccrc ackstrip \
sleep slip sort spell split srccrc \
stty su sum svclog swifi sync synctree sysenv \
syslogd tail tar tcpd tcpdp tcpstat tee telnet \
telnetd term termcap tget time touch tr \
@ -35,15 +35,10 @@ SUBDIR= aal add_route arp ash at autil awk \
xargs yacc yes zdump zmodem pkgin_cd \
mktemp worldstone
.if ${COMPILER_TYPE} == "gnu"
SUBDIR += elf2aout
.endif
.if ${ARCH} == "i386"
SUBDIR+= atnormalize dosread fdisk loadfont \
autopart part partition playwave postmort \
recwave repartition screendump padtext
SUBDIR+= acd asmconv gas2ack
autopart part partition playwave \
recwave repartition screendump
.endif
.include <bsd.subdir.mk>

View File

@ -1,14 +1,3 @@
# Any of the commands can force the new libc being used by
# setting NEED_NBSDLIBC
.if defined(NEED_NBSDLIBC)
.include <minix.newlibc.mk>
.endif
.if (${NBSD_LIBC} != "no")
CPPFLAGS+= -D_MINIX -D_NETBSD_SOURCE -D_MINIX_COMPAT
LDADD+= -lminlib -lcompat_minix -lasyn -lterminfo
.else
CPPFLAGS+= -D_MINIX -D_POSIX_SOURCE
.endif
BINDIR?=/usr/bin

View File

@ -1,11 +0,0 @@
# Makefile for aal
PROG= aal
SRCS= archiver.c print.c rd.c rd_arhdr.c rd_unsig2.c sprint.c \
wr_arhdr.c wr_bytes.c wr_int2.c wr_long.c wr_ranlib.c \
format.c rd_bytes.c system.c write.c long2str.c
CPPFLAGS+= -I${.CURDIR} -DAAL -DSTB -DNDEBUG -DDISTRIBUTION
MAN=
.include <bsd.prog.mk>

View File

@ -1,28 +0,0 @@
/* $Header$ */
/*
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
*/
#ifndef __ARCH_H_INCLUDED
#define __ARCH_H_INCLUDED
#define ARMAG 0177545
#define AALMAG 0177454
struct ar_hdr {
char ar_name[14];
long ar_date;
char ar_uid;
char ar_gid;
short ar_mode;
long ar_size;
};
#define AR_TOTAL 26
#define AR_SIZE 22
extern int rd_arhdr(int fd, register struct ar_hdr arhdr[]);
extern void wr_arhdr(int fd, struct ar_hdr arhdr[]);
#endif /* __ARCH_H_INCLUDED */

View File

@ -1,816 +0,0 @@
/*
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
*/
/* ar - archiver Author: Michiel Huisjes */
/* Made into arch/aal by Ceriel Jacobs
*/
#include <sys/types.h>
#include <fcntl.h>
#include "rd.h"
#include "wr_bytes.h"
#include "wr_long.h"
#include "wr_int2.h"
#include "arch.h"
#include "archiver.h"
#include "print.h"
static char RcsId[] = "$Header$";
/*
* Usage: [arch|aal] [adprtvx] archive [file] ...
* v: verbose
* x: extract
* a: append
* r: replace (append when not in archive)
* d: delete
* t: print contents of archive
* p: print named files
* l: temporaries in current directory instead of /usr/tmp
* c: don't give "create" message
* u: replace only if dated later than member in archive
#ifdef DISTRIBUTION
* D: make distribution: use distr_time, uid=2, gid=2, mode=0644
#endif
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifdef __NBSD_LIBC
#include <sys/time.h>
#endif
#ifndef S_IREAD
#define S_IREAD S_IRUSR
#endif
#ifndef S_IWRITE
#define S_IWRITE S_IWUSR
#endif
#ifndef S_IEXEC
#define S_IEXEC S_IXUSR
#endif
#include <signal.h>
#include <arch.h>
#ifdef AAL
#include <ranlib.h>
#include <out.h>
#define MAGIC_NUMBER AALMAG
long offset;
struct ranlib *tab;
unsigned int tnum = 0;
char *tstrtab;
unsigned int tssiz = 0;
long time();
unsigned int tabsz, strtabsz;
#else
#define MAGIC_NUMBER ARMAG
#endif
long lseek();
#define odd(nr) (nr & 01)
#define even(nr) (odd(nr) ? nr + 1 : nr)
typedef char BOOL;
#define FALSE 0
#define TRUE 1
#define READ 0
#define APPEND 2
#define CREATE 1
#define MEMBER struct ar_hdr
#define IO_SIZE (10 * 1024)
#define equal(str1, str2) (!strncmp((str1), (str2), 14))
#ifndef S_ISDIR
#define S_ISDIR(m) (m & S_IFDIR) /* is a directory */
#endif
BOOL verbose;
BOOL app_fl;
BOOL ex_fl;
BOOL show_fl;
BOOL pr_fl;
BOOL rep_fl;
BOOL del_fl;
BOOL nocr_fl;
BOOL local_fl;
BOOL update_fl;
#ifdef DISTRIBUTION
BOOL distr_fl;
long distr_time;
#endif
int ar_fd;
char io_buffer[IO_SIZE];
char *progname;
char temp_buf[32];
char *temp_arch = &temp_buf[0];
extern char *mktemp();
extern char *ctime();
/* Forward declarations. */
static void enter_name(struct outname *namep);
static void do_names(struct outhead *headp);
static void do_object(int f, long size);
static void show(char *s, char *name);
static void write_symdef(void);
static void mwrite(int fd, char *address, int bytes);
static void extract(register MEMBER *member);
static void copy_member(MEMBER *member, int from, int to, int extracting);
static void add(char *name, int fd, char *mess);
static void get(int argc, char *argv[]);
/*VARARGS2*/
void error1(BOOL quit, char *str1)
{
fputs(str1,stderr);
if (quit) {
unlink(temp_arch);
_exit(1);
}
}
void error2(BOOL quit, char *str1, char *str2)
{
fprintf(stderr,str1,str2);
if (quit) {
unlink(temp_arch);
_exit(1);
}
}
void error3(BOOL quit, char *str1, char *str2, char *str3)
{
fprintf(stderr,str1,str2,str3);
if (quit) {
unlink(temp_arch);
_exit(1);
}
}
void usage()
{
error3(TRUE, "usage: %s %s archive [file] ...\n",
progname,
#ifdef AAL
"[acdrtxvlu]"
#else
"[acdprtxvlu]"
#endif
);
}
char *basename(char *path)
{
register char *ptr = path;
register char *last = NULL;
while (*ptr != '\0') {
if (*ptr == '/')
last = ptr;
ptr++;
}
if (last == NULL)
return path;
if (*(last + 1) == '\0') {
*last = '\0';
return basename(path);
}
return last + 1;
}
extern unsigned int rd_unsigned2();
int open_archive(char *name, int mode)
{
unsigned short magic = 0;
int fd;
if (mode == CREATE) {
if ((fd = creat(name, 0666)) < 0)
error2(TRUE, "cannot creat %s\n", name);
magic = MAGIC_NUMBER;
wr_int2(fd, magic);
return fd;
}
if ((fd = open(name, mode)) < 0) {
if (mode == APPEND) {
close(open_archive(name, CREATE));
if (!nocr_fl) error3(FALSE, "%s: creating %s\n", progname, name);
return open_archive(name, APPEND);
}
error2(TRUE, "cannot open %s\n", name);
}
lseek(fd, 0L, 0);
magic = rd_unsigned2(fd);
if (magic != AALMAG && magic != ARMAG)
error2(TRUE, "%s is not in ar format\n", name);
return fd;
}
#if __STDC__
void catch(int sig)
#else
catch()
#endif
{
unlink(temp_arch);
_exit (2);
}
int main(int argc, char *argv[])
{
register char *ptr;
int needs_arg = 0;
progname = argv[0];
if (argc < 3)
usage();
for (ptr = argv[1]; *ptr; ptr++) {
switch (*ptr) {
case 't' :
show_fl = TRUE;
break;
case 'v' :
verbose = TRUE;
break;
case 'x' :
ex_fl = TRUE;
break;
case 'a' :
needs_arg = 1;
app_fl = TRUE;
break;
case 'c' :
nocr_fl = TRUE;
break;
#ifndef AAL
case 'p' :
needs_arg = 1;
pr_fl = TRUE;
break;
#endif
case 'd' :
needs_arg = 1;
del_fl = TRUE;
break;
case 'r' :
needs_arg = 1;
rep_fl = TRUE;
break;
case 'l' :
local_fl = TRUE;
break;
case 'u' :
update_fl = TRUE;
break;
#ifdef DISTRIBUTION
case 'D' :
distr_fl = TRUE;
break;
#endif
default :
usage();
}
}
if (needs_arg && argc <= 3)
usage();
#ifdef DISTRIBUTION
if (distr_fl) {
struct stat statbuf;
stat(progname, &statbuf);
distr_time = statbuf.st_mtime;
}
#endif
if (local_fl) strcpy(temp_arch, "ar.XXXXXX");
else strcpy(temp_arch, "/usr/tmp/ar.XXXXXX");
if (app_fl + ex_fl + del_fl + rep_fl + show_fl + pr_fl != 1)
usage();
if (update_fl && !rep_fl)
usage();
if (rep_fl || del_fl
#ifdef AAL
|| app_fl
#endif
) {
mktemp(temp_arch);
}
#ifdef AAL
tab = (struct ranlib *) malloc(512 * sizeof(struct ranlib));
tstrtab = malloc(4096);
if (!tab || !tstrtab) error1(TRUE,"Out of core\n");
tabsz = 512;
strtabsz = 4096;
#endif
signal(SIGINT, catch);
get(argc, argv);
return 0;
}
MEMBER *
get_member()
{
static MEMBER member;
again:
if (rd_arhdr(ar_fd, &member) == 0)
return NULL;
if (member.ar_size < 0) {
error1(TRUE, "archive has member with negative size\n");
}
#ifdef AAL
if (equal(SYMDEF, member.ar_name)) {
lseek(ar_fd, member.ar_size, 1);
goto again;
}
#endif
return &member;
}
char *get_mode();
static void get(int argc, char *argv[])
{
register MEMBER *member;
int i = 0;
int temp_fd, read_chars;
ar_fd = open_archive(argv[2], (show_fl || pr_fl || ex_fl) ? READ : APPEND);
if (rep_fl || del_fl
#ifdef AAL
|| app_fl
#endif
)
temp_fd = open_archive(temp_arch, CREATE);
while ((member = get_member()) != NULL) {
if (argc > 3) {
for (i = 3; i < argc; i++) {
if (equal(basename(argv[i]), member->ar_name))
break;
}
if (i == argc || app_fl) {
if (rep_fl || del_fl
#ifdef AAL
|| app_fl
#endif
) {
#ifdef AAL
if (i != argc) {
print("%s: already in archive\n", argv[i]);
argv[i] = "";
}
#endif
wr_arhdr(temp_fd, member);
copy_member(member, ar_fd, temp_fd, 0);
}
else {
#ifndef AAL
if (app_fl && i != argc) {
print("%s: already in archive\n", argv[i]);
argv[i] = "";
}
#endif
lseek(ar_fd, even(member->ar_size),1);
}
continue;
}
}
if (ex_fl || pr_fl)
extract(member);
else {
if (rep_fl) {
int isold = 0;
if(update_fl) {
struct stat status;
if (stat(argv[i], &status) >= 0) {
if(status.st_mtime <= member->ar_date)
isold = 1;
}
}
if(!isold)
add(argv[i], temp_fd, "r - %s\n");
else {
wr_arhdr(temp_fd, member);
copy_member(member, ar_fd, temp_fd, 0);
if(verbose)
show("r - %s (old)\n", member->ar_name);
}
}
else if (show_fl) {
char buf[sizeof(member->ar_name) + 2];
register char *p = buf, *q = member->ar_name;
while (q <= &member->ar_name[sizeof(member->ar_name)-1] && *q) {
*p++ = *q++;
}
*p++ = '\n';
*p = '\0';
if (verbose) {
char *mode = get_mode(member->ar_mode);
char *date = ctime(&(member->ar_date));
*(date + 16) = '\0';
*(date + 24) = '\0';
print("%s%3u/%u%7ld %s %s %s",
mode,
(unsigned) (member->ar_uid & 0377),
(unsigned) (member->ar_gid & 0377),
member->ar_size,
date+4,
date+20,
buf);
}
else print(buf);
}
else if (del_fl)
show("d - %s\n", member->ar_name);
lseek(ar_fd, even(member->ar_size), 1);
}
argv[i] = "";
}
if (argc > 3) {
for (i = 3; i < argc; i++)
if (argv[i][0] != '\0') {
#ifndef AAL
if (app_fl)
add(argv[i], ar_fd, "a - %s\n");
else
#endif
if (rep_fl
#ifdef AAL
|| app_fl
#endif
)
add(argv[i], temp_fd, "a - %s\n");
else {
print("%s: not found\n", argv[i]);
}
}
}
if (rep_fl || del_fl
#ifdef AAL
|| app_fl
#endif
) {
signal(SIGINT, SIG_IGN);
close(ar_fd);
close(temp_fd);
ar_fd = open_archive(argv[2], CREATE);
temp_fd = open_archive(temp_arch, APPEND);
#ifdef AAL
write_symdef();
#endif
while ((read_chars = read(temp_fd, io_buffer, IO_SIZE)) > 0)
mwrite(ar_fd, io_buffer, read_chars);
close(temp_fd);
unlink(temp_arch);
}
close(ar_fd);
}
static void add(char *name, int fd, char *mess)
{
static MEMBER member;
register int read_chars;
struct stat status;
int src_fd;
if (stat(name, &status) < 0) {
error2(FALSE, "cannot find %s\n", name);
return;
}
else if (S_ISDIR(status.st_mode)) {
error2(FALSE, "%s is a directory (ignored)\n", name);
return;
}
else if ((src_fd = open(name, 0)) < 0) {
error2(FALSE, "cannot open %s\n", name);
return;
}
strncpy (member.ar_name, basename (name), sizeof(member.ar_name));
member.ar_uid = status.st_uid;
member.ar_gid = status.st_gid;
member.ar_mode = status.st_mode;
member.ar_date = status.st_mtime;
member.ar_size = status.st_size;
#ifdef DISTRIBUTION
if (distr_fl) {
member.ar_uid = 2;
member.ar_gid = 2;
member.ar_mode = 0644;
member.ar_date = distr_time;
}
#endif
wr_arhdr(fd, &member);
#ifdef AAL
do_object(src_fd, member.ar_size);
lseek(src_fd, 0L, 0);
offset += AR_TOTAL + even(member.ar_size);
#endif
while (status.st_size > 0) {
int x = IO_SIZE;
read_chars = x;
if (status.st_size < x) {
x = status.st_size;
read_chars = x;
status.st_size = 0;
x = even(x);
}
else status.st_size -= x;
if (read(src_fd, io_buffer, read_chars) != read_chars) {
error2(FALSE,"%s seems to shrink\n", name);
break;
}
mwrite(fd, io_buffer, x);
}
if (verbose)
show(mess, member.ar_name);
close(src_fd);
}
static void extract(register MEMBER *member)
{
int fd = 1;
char buf[sizeof(member->ar_name) + 1];
strncpy(buf, member->ar_name, sizeof(member->ar_name));
buf[sizeof(member->ar_name)] = 0;
if (pr_fl == FALSE && (fd = creat(buf, 0666)) < 0) {
error2(FALSE, "cannot create %s\n", buf);
fd = -1;
}
if (verbose) {
if (pr_fl == FALSE) show("x - %s\n", buf);
else show("\n<%s>\n\n", buf);
}
copy_member(member, ar_fd, fd, 1);
if (fd >= 0 && fd != 1)
close(fd);
if (pr_fl == FALSE) chmod(buf, member->ar_mode);
}
static void copy_member(MEMBER *member, int from, int to, int extracting)
{
register int rest;
long mem_size = member->ar_size;
BOOL is_odd = odd(mem_size) ? TRUE : FALSE;
#ifdef AAL
if (! extracting) {
long pos = lseek(from, 0L, 1);
do_object(from, mem_size);
offset += AR_TOTAL + even(mem_size);
lseek(from, pos, 0);
}
#endif
do {
rest = mem_size > (long) IO_SIZE ? IO_SIZE : (int) mem_size;
if (read(from, io_buffer, rest) != rest) {
char buf[sizeof(member->ar_name) + 1];
strncpy(buf, member->ar_name, sizeof(member->ar_name));
buf[sizeof(member->ar_name)] = 0;
error2(TRUE, "read error on %s\n", buf);
}
if (to >= 0) mwrite(to, io_buffer, rest);
mem_size -= (long) rest;
} while (mem_size > 0L);
if (is_odd) {
lseek(from, 1L, 1);
if (to >= 0 && ! extracting)
lseek(to, 1L, 1);
}
}
char *
get_mode(mode)
register int mode;
{
static char mode_buf[11];
register int tmp = mode;
int i;
mode_buf[9] = ' ';
for (i = 0; i < 3; i++) {
mode_buf[i * 3] = (tmp & S_IREAD) ? 'r' : '-';
mode_buf[i * 3 + 1] = (tmp & S_IWRITE) ? 'w' : '-';
mode_buf[i * 3 + 2] = (tmp & S_IEXEC) ? 'x' : '-';
tmp <<= 3;
}
if (mode & S_ISUID)
mode_buf[2] = 's';
if (mode & S_ISGID)
mode_buf[5] = 's';
return mode_buf;
}
void wr_fatal()
{
error1(TRUE, "write error\n");
}
void rd_fatal()
{
error1(TRUE, "read error\n");
}
static void mwrite(int fd, char *address, int bytes)
{
if (write(fd, address, bytes) != bytes)
error1(TRUE, "write error\n");
}
static void show(char *s, char *name)
{
MEMBER x;
char buf[sizeof(x.ar_name)+1];
register char *p = buf, *q = name;
while (q <= &name[sizeof(x.ar_name)-1] && *q) *p++ = *q++;
*p++ = '\0';
print(s, buf);
}
#ifdef AAL
/*
* Write out the ranlib table: first 4 bytes telling how many ranlib structs
* there are, followed by the ranlib structs,
* then 4 bytes giving the size of the string table, followed by the string
* table itself.
*/
static void write_symdef(void)
{
register struct ranlib *ran;
register int i;
register long delta;
MEMBER arbuf;
if (odd(tssiz))
tstrtab[tssiz++] = '\0';
for (i = 0; i < sizeof(arbuf.ar_name); i++)
arbuf.ar_name[i] = '\0';
strcpy(arbuf.ar_name, SYMDEF);
arbuf.ar_size = 4 + 2 * 4 * (long)tnum + 4 + (long)tssiz;
time(&arbuf.ar_date);
arbuf.ar_uid = getuid();
arbuf.ar_gid = getgid();
arbuf.ar_mode = 0444;
#ifdef DISTRIBUTION
if (distr_fl) {
arbuf.ar_uid = 2;
arbuf.ar_gid = 2;
arbuf.ar_date = distr_time;
}
#endif
wr_arhdr(ar_fd,&arbuf);
wr_long(ar_fd, (long) tnum);
/*
* Account for the space occupied by the magic number
* and the ranlib table.
*/
delta = 2 + AR_TOTAL + arbuf.ar_size;
for (ran = tab; ran < &tab[tnum]; ran++) {
ran->ran_pos += delta;
}
wr_ranlib(ar_fd, tab, (long) tnum);
wr_long(ar_fd, (long) tssiz);
wr_bytes(ar_fd, tstrtab, (long) tssiz);
}
/*
* Return whether the bytes in `buf' form a good object header.
* The header is put in `headp'.
*/
int
is_outhead(register struct outhead *headp)
{
return !BADMAGIC(*headp) && headp->oh_nname != 0;
}
static void do_object(int f, long size)
{
struct outhead headbuf;
if (size < SZ_HEAD) {
/* It can't be an object file. */
return;
}
/*
* Read a header to see if it is an object file.
*/
if (! rd_fdopen(f)) {
rd_fatal();
}
rd_ohead(&headbuf);
if (!is_outhead(&headbuf)) {
return;
}
do_names(&headbuf);
}
/*
* First skip the names and read in the string table, then seek back to the
* name table and read and write the names one by one. Update the ranlib table
* accordingly.
*/
static void do_names(struct outhead *headp)
{
register char *strings;
register int nnames = headp->oh_nname;
#define NNAMES 100
struct outname namebuf[NNAMES];
long xxx = OFF_CHAR(*headp);
if ( headp->oh_nchar != (unsigned int)headp->oh_nchar ||
(strings = malloc((unsigned int)headp->oh_nchar)) == (char *)0
) {
error1(TRUE, "string table too big\n");
}
rd_string(strings, headp->oh_nchar);
while (nnames) {
int i = nnames >= NNAMES ? NNAMES : nnames;
register struct outname *p = namebuf;
nnames -= i;
rd_name(namebuf, i);
while (i--) {
long off = p->on_foff - xxx;
if (p->on_foff == (long)0) {
p++;
continue; /* An unrecognizable name. */
}
p->on_mptr = strings + off;
/*
* Only enter names that are exported and are really
* defined. Also enter common names. Note, that
* this might cause problems when the name is really
* defined in a later file, with a value != 0.
* However, this problem also exists on the Unix
* ranlib archives.
*/
if ( (p->on_type & S_EXT) &&
(p->on_type & S_TYP) != S_UND
)
enter_name(p);
p++;
}
}
free(strings);
}
static void enter_name(struct outname *namep)
{
register char *cp;
if (tnum >= tabsz) {
tab = (struct ranlib *)
realloc((char *) tab, (tabsz += 512) * sizeof(struct ranlib));
if (! tab) error1(TRUE, "Out of core\n");
}
tab[tnum].ran_off = tssiz;
tab[tnum].ran_pos = offset;
for (cp = namep->on_mptr;; cp++) {
if (tssiz >= strtabsz) {
tstrtab = realloc(tstrtab, (strtabsz += 4096));
if (! tstrtab) error1(TRUE, "string table overflow\n");
}
tstrtab[tssiz++] = *cp;
if (!*cp) break;
}
tnum++;
}
#endif /* AAL */

View File

@ -1,3 +0,0 @@
extern void rd_fatal();
extern void wr_fatal();

View File

@ -1,9 +0,0 @@
#if defined(mc68020) || defined(mc68000) || defined(sparc)
#define BYTES_REVERSED 1
#define WORDS_REVERSED 1
#define CHAR_UNSIGNED 0
#else
#define BYTES_REVERSED 0
#define WORDS_REVERSED 0
#define CHAR_UNSIGNED 0
#endif

View File

@ -1,112 +0,0 @@
/*
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
*/
/* $Header$ */
#if __STDC__
#include <stdarg.h>
#else
#include <varargs.h>
#endif
#include <string.h>
extern char *long2str();
static int
integral(int c)
{
switch (c) {
case 'b':
return -2;
case 'd':
return 10;
case 'o':
return -8;
case 'u':
return -10;
case 'x':
return -16;
}
return 0;
}
/*VARARGS2*/
/*FORMAT1 $
%s = char *
%l = long
%c = int
%[uxbo] = unsigned int
%d = int
$ */
int
_format(char *buf, char *fmt, va_list argp)
{
register char *pf = fmt;
register char *pb = buf;
while (*pf) {
if (*pf == '%') {
register int width, base, pad, npad;
char *arg;
char cbuf[2];
char *badformat = "<bad format>";
/* get padder */
if (*++pf == '0') {
pad = '0';
++pf;
}
else
pad = ' ';
/* get width */
width = 0;
while (*pf >= '0' && *pf <= '9')
width = 10 * width + *pf++ - '0';
if (*pf == 's') {
arg = va_arg(argp, char *);
}
else
if (*pf == 'c') {
cbuf[0] = va_arg(argp, int);
cbuf[1] = '\0';
arg = &cbuf[0];
}
else
if (*pf == 'l') {
/* alignment ??? */
base = integral(*++pf);
if (base) {
arg = long2str(va_arg(argp,long), base);
}
else {
pf--;
arg = badformat;
}
}
else
if ((base = integral(*pf))) {
arg = long2str((long)va_arg(argp,int), base);
}
else
if (*pf == '%')
arg = "%";
else
arg = badformat;
npad = width - strlen(arg);
while (npad-- > 0)
*pb++ = pad;
while (*pb++ = *arg++);
pb--;
pf++;
}
else
*pb++ = *pf++;
}
return pb - buf;
}

View File

@ -1,2 +0,0 @@
extern int _format(char *buf, char *fmt, va_list argp);

View File

@ -1,19 +0,0 @@
/* $Header$ */
/*
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
*/
/* collection of options, selected by including or excluding 'defines' */
/* Version number of the EM object code */
# define VERSION 3 /* 16 bits number */
/* The default machine used by ack, acc, apc */
# define ACKM "minix"
/* size of local machine, either 0 (for 16 bit address space), or 1 */
# undef BIGMACHINE
/* operating system, SYS_5, V7, BSD4_1 or BSD4_2; Do NOT delete the comment
in the next line! */
# define V7 1 /* SYSTEM */

View File

@ -1,67 +0,0 @@
/* $Header$ */
/*
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
*/
/* Integer to String translator
-> base is a value from [-16,-2] V [2,16]
-> base < 0: see 'val' as unsigned value
-> no checks for buffer overflow and illegal parameters
(1985, EHB)
*/
#define MAXWIDTH 32
char *
long2str(val, base)
register long val;
register int base;
{
static char numbuf[MAXWIDTH];
static char vec[] = "0123456789ABCDEF";
register char *p = &numbuf[MAXWIDTH];
int sign = (base > 0);
*--p = '\0'; /* null-terminate string */
if (val) {
if (base > 0) {
if (val < 0L) {
long v1 = -val;
if (v1 == val)
goto overflow;
val = v1;
}
else
sign = 0;
}
else
if (base < 0) { /* unsigned */
base = -base;
if (val < 0L) { /* taken from Amoeba src */
register int mod, i;
overflow:
mod = 0;
for (i = 0; i < 8 * sizeof val; i++) {
mod <<= 1;
if (val < 0)
mod++;
val <<= 1;
if (mod >= base) {
mod -= base;
val++;
}
}
*--p = vec[mod];
}
}
do {
*--p = vec[(int) (val % base)];
val /= base;
} while (val != 0L);
if (sign)
*--p = '-'; /* don't forget it !! */
}
else
*--p = '0'; /* just a simple 0 */
return p;
}

View File

@ -1,76 +0,0 @@
/* $Header$ */
/*
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
*/
#include "byte_order.h"
#include <local.h>
#include <stdio.h>
#if CHAR_UNSIGNED
#define Xchar(ch) (ch)
#else
#define Xchar(ch) ((ch) & 0377)
#endif
#if ! defined(BYTES_REVERSED)
#define BYTES_REVERSED 1
#endif
#if ! defined(WORDS_REVERSED)
#define WORDS_REVERSED 1
#endif
#if BYTES_REVERSED
#define uget2(c) (Xchar((c)[0]) | ((unsigned) Xchar((c)[1]) << 8))
#define Xput2(i, c) (((c)[0] = (i)), ((c)[1] = (i) >> 8))
#define put2(i, c) { register int j = (i); Xput2(j, c); }
#else
#define uget2(c) (* ((unsigned short *) (c)))
#define Xput2(i, c) (* ((short *) (c)) = (i))
#define put2(i, c) Xput2(i, c)
#endif
#define get2(c) ((short) uget2(c))
#if WORDS_REVERSED || BYTES_REVERSED
#define get4(c) (uget2(c) | ((long) uget2((c)+2) << 16))
#define put4(l, c) { register long x=(l); \
Xput2((int)x,c); \
Xput2((int)(x>>16),(c)+2); \
}
#else
#define get4(c) (* ((long *) (c)))
#define put4(l, c) (* ((long *) (c)) = (l))
#endif
#define SECTCNT 3 /* number of sections with own output buffer */
#if BIGMACHINE
#define WBUFSIZ (8*BUFSIZ)
#else
#define WBUFSIZ BUFSIZ
#endif
struct fil {
int cnt;
char *pnow;
char *pbegin;
long currpos;
int fd;
char pbuf[WBUFSIZ];
};
extern struct fil __parts[];
#define PARTEMIT 0
#define PARTRELO (PARTEMIT+SECTCNT)
#define PARTNAME (PARTRELO+1)
#define PARTCHAR (PARTNAME+1)
#ifdef SYMDBUG
#define PARTDBUG (PARTCHAR+1)
#else
#define PARTDBUG (PARTCHAR+0)
#endif
#define NPARTS (PARTDBUG + 1)
#define getsect(s) (PARTEMIT+((s)>=(SECTCNT-1)?(SECTCNT-1):(s)))

View File

@ -1,126 +0,0 @@
/*
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
*/
/* $Header$ */
#ifndef __OUT_H_INCLUDED
#define __OUT_H_INCLUDED
/*
* output format for ACK assemblers
*/
#ifndef ushort
#define ushort unsigned short
#endif /* ushort */
struct outhead {
ushort oh_magic; /* magic number */
ushort oh_stamp; /* version stamp */
ushort oh_flags; /* several format flags */
ushort oh_nsect; /* number of outsect structures */
ushort oh_nrelo; /* number of outrelo structures */
ushort oh_nname; /* number of outname structures */
long oh_nemit; /* sum of all os_flen */
long oh_nchar; /* size of string area */
};
#define O_MAGIC 0x0201 /* magic number of output file */
#define O_STAMP 0 /* version stamp */
#define MAXSECT 64 /* Maximum number of sections */
#define HF_LINK 0x0004 /* unresolved references left */
#define HF_8086 0x0008 /* os_base specially encoded */
struct outsect {
long os_base; /* startaddress in machine */
long os_size; /* section size in machine */
long os_foff; /* startaddress in file */
long os_flen; /* section size in file */
long os_lign; /* section alignment */
};
struct outrelo {
char or_type; /* type of reference */
char or_sect; /* referencing section */
ushort or_nami; /* referenced symbol index */
long or_addr; /* referencing address */
};
struct outname {
union {
char *on_ptr; /* symbol name (in core) */
long on_off; /* symbol name (in file) */
} on_u;
#define on_mptr on_u.on_ptr
#define on_foff on_u.on_off
ushort on_type; /* symbol type */
ushort on_desc; /* debug info */
long on_valu; /* symbol value */
};
/*
* relocation type bits
*/
#define RELSZ 0x07 /* relocation length */
#define RELO1 1 /* 1 byte */
#define RELO2 2 /* 2 bytes */
#define RELO4 4 /* 4 bytes */
#define RELPC 0x08 /* pc relative */
#define RELBR 0x10 /* High order byte lowest address. */
#define RELWR 0x20 /* High order word lowest address. */
/*
* section type bits and fields
*/
#define S_TYP 0x007F /* undefined, absolute or relative */
#define S_EXT 0x0080 /* external flag */
#define S_ETC 0x7F00 /* for symbolic debug, bypassing 'as' */
/*
* S_TYP field values
*/
#define S_UND 0x0000 /* undefined item */
#define S_ABS 0x0001 /* absolute item */
#define S_MIN 0x0002 /* first user section */
#define S_MAX (S_TYP-1) /* last user section */
#define S_CRS S_TYP /* on_valu is symbol index which contains value */
/*
* S_ETC field values
*/
#define S_SCT 0x0100 /* section names */
#define S_LIN 0x0200 /* hll source line item */
#define S_FIL 0x0300 /* hll source file item */
#define S_MOD 0x0400 /* ass source file item */
#define S_COM 0x1000 /* Common name. */
#define S_STB 0xe000 /* entries with any of these bits set are
reserved for debuggers
*/
/*
* structure format strings
*/
#define SF_HEAD "22222244"
#define SF_SECT "44444"
#define SF_RELO "1124"
#define SF_NAME "4224"
/*
* structure sizes (bytes in file; add digits in SF_*)
*/
#define SZ_HEAD 20
#define SZ_SECT 20
#define SZ_RELO 8
#define SZ_NAME 12
/*
* file access macros
*/
#define BADMAGIC(x) ((x).oh_magic!=O_MAGIC)
#define OFF_SECT(x) SZ_HEAD
#define OFF_EMIT(x) (OFF_SECT(x) + ((long)(x).oh_nsect * SZ_SECT))
#define OFF_RELO(x) (OFF_EMIT(x) + (x).oh_nemit)
#define OFF_NAME(x) (OFF_RELO(x) + ((long)(x).oh_nrelo * SZ_RELO))
#define OFF_CHAR(x) (OFF_NAME(x) + ((long)(x).oh_nname * SZ_NAME))
#endif /* __OUT_H_INCLUDED */

View File

@ -1,7 +0,0 @@
/*
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
*/
/* $Header$ */
#define SSIZE 1024

View File

@ -1,44 +0,0 @@
/*
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
*/
/* $Header$ */
#if __STDC__
#include <stdarg.h>
#else
#include <varargs.h>
#endif
#include <system.h>
#include "param.h"
#include "format.h"
#include "write.h"
/*VARARGS*/
/*FORMAT0v $
%s = char *
%l = long
%c = int
%[uxbo] = unsigned int
%d = int
$ */
void
#if __STDC__
print(char *fmt, ...)
#else
print(fmt, va_alist)
char *fmt;
va_dcl
#endif
{
va_list args;
char buf[SSIZE];
#if __STDC__
va_start(args, fmt);
#else
va_start(args);
#endif
sys_write(STDOUT, buf, _format(buf, fmt, args));
va_end(args);
}

View File

@ -1,2 +0,0 @@
extern void print(char *fmt, ...);

View File

@ -1,36 +0,0 @@
/*
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
*/
/* $Header$ */
#ifndef __RANLIB_H_INCLUDED
#define __RANLIB_H_INCLUDED
#ifndef SYMDEF
# define SYMDEF "__.SYMDEF"
#endif /* SYMDEF */
/*
* Structure of the SYMDEF table of contents for an archive.
* SYMDEF begins with a long giving the number of ranlib
* structures that immediately follow, and then continues with a string
* table consisting of a long giving the number of bytes of
* strings that follow and then the strings themselves.
*/
struct ranlib {
union {
char *ran__ptr; /* symbol name (in core) */
long ran__off; /* symbol name (in file) */
} ran_u;
#define ran_ptr ran_u.ran__ptr
#define ran_off ran_u.ran__off
long ran_pos; /* library member is at this position */
};
#define SZ_RAN 8
#define SF_RAN "44"
extern void wr_ranlib(int fd, struct ranlib ran[], long cnt);
#endif /* __RANLIB_H_INCLUDED */

View File

@ -1,247 +0,0 @@
/* $Header$ */
/*
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
*/
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include "out.h"
#include "object.h"
#include "rd.h"
#include "rd_bytes.h"
extern long lseek();
/*
* Parts of the output file.
*/
#undef PARTEMIT
#undef PARTRELO
#undef PARTNAME
#undef PARTCHAR
#undef PARTDBUG
#undef NPARTS
#define PARTEMIT 0
#define PARTRELO 1
#define PARTNAME 2
#define PARTCHAR 3
#ifdef SYMDBUG
#define PARTDBUG 4
#else
#define PARTDBUG 3
#endif
#define NPARTS (PARTDBUG + 1)
static long offset[MAXSECT];
static int outfile;
static long outseek[NPARTS];
static long currpos;
static long rd_base;
#define OUTSECT(i) \
(outseek[PARTEMIT] = offset[i])
#define BEGINSEEK(p, o) \
(outseek[(p)] = (o))
static int sectionnr;
static
void OUTREAD(int p, char *b, long n)
{
register long l = outseek[p];
if (currpos != l) {
lseek(outfile, l, 0);
}
rd_bytes(outfile, b, n);
l += n;
currpos = l;
outseek[p] = l;
}
/*
* Open the output file according to the chosen strategy.
*/
int
rd_open(char *f)
{
int outfile = open(f, 0);
if (outfile < 0)
return 0;
return rd_fdopen(outfile);
}
static int offcnt;
int rd_fdopen(int fd)
{
register int i;
for (i = 0; i < NPARTS; i++) outseek[i] = 0;
offcnt = 0;
rd_base = lseek(fd, 0L, 1);
if (rd_base < 0) {
return 0;
}
currpos = rd_base;
outseek[PARTEMIT] = currpos;
outfile = fd;
sectionnr = 0;
return 1;
}
void rd_close()
{
close(outfile);
outfile = -1;
}
int rd_fd()
{
return outfile;
}
void rd_ohead(register struct outhead *head)
{
register long off;
OUTREAD(PARTEMIT, (char *) head, (long) SZ_HEAD);
#if ! (BYTES_REVERSED || WORDS_REVERSED)
if (sizeof(struct outhead) != SZ_HEAD)
#endif
{
register char *c = (char *) head + (SZ_HEAD-4);
head->oh_nchar = get4(c);
c -= 4; head->oh_nemit = get4(c);
c -= 2; head->oh_nname = uget2(c);
c -= 2; head->oh_nrelo = uget2(c);
c -= 2; head->oh_nsect = uget2(c);
c -= 2; head->oh_flags = uget2(c);
c -= 2; head->oh_stamp = uget2(c);
c -= 2; head->oh_magic = uget2(c);
}
off = OFF_RELO(*head) + rd_base;
BEGINSEEK(PARTRELO, off);
off += (long) head->oh_nrelo * SZ_RELO;
BEGINSEEK(PARTNAME, off);
off += (long) head->oh_nname * SZ_NAME;
BEGINSEEK(PARTCHAR, off);
#ifdef SYMDBUG
off += head->oh_nchar;
BEGINSEEK(PARTDBUG, off);
#endif
}
void rd_rew_relos(head)
register struct outhead *head;
{
register long off = OFF_RELO(*head) + rd_base;
BEGINSEEK(PARTRELO, off);
}
void rd_sect(sect, cnt)
register struct outsect *sect;
register unsigned int cnt;
{
register char *c = (char *) sect + cnt * SZ_SECT;
OUTREAD(PARTEMIT, (char *) sect, (long)cnt * SZ_SECT);
sect += cnt;
offcnt += cnt;
while (cnt--) {
sect--;
#if ! (BYTES_REVERSED || WORDS_REVERSED)
if (sizeof(struct outsect) != SZ_SECT)
#endif
{
c -= 4; sect->os_lign = get4(c);
c -= 4; sect->os_flen = get4(c);
c -= 4; sect->os_foff = get4(c);
}
offset[--offcnt] = sect->os_foff + rd_base;
#if ! (BYTES_REVERSED || WORDS_REVERSED)
if (sizeof(struct outsect) != SZ_SECT)
#endif
{
c -= 4; sect->os_size = get4(c);
c -= 4; sect->os_base = get4(c);
}
}
}
void rd_outsect(int s)
{
OUTSECT(s);
sectionnr = s;
}
/*
* We don't have to worry about byte order here.
*/
void rd_emit(emit, cnt)
char *emit;
long cnt;
{
OUTREAD(PARTEMIT, emit, cnt);
offset[sectionnr] += cnt;
}
void rd_relo(relo, cnt)
register struct outrelo *relo;
register unsigned int cnt;
{
OUTREAD(PARTRELO, (char *) relo, (long) cnt * SZ_RELO);
#if ! (BYTES_REVERSED || WORDS_REVERSED)
if (sizeof(struct outrelo) != SZ_RELO)
#endif
{
register char *c = (char *) relo + (long) cnt * SZ_RELO;
relo += cnt;
while (cnt--) {
relo--;
c -= 4; relo->or_addr = get4(c);
c -= 2; relo->or_nami = uget2(c);
relo->or_sect = *--c;
relo->or_type = *--c;
}
}
}
void rd_name(struct outname *name, unsigned int cnt)
{
OUTREAD(PARTNAME, (char *) name, (long) cnt * SZ_NAME);
#if ! (BYTES_REVERSED || WORDS_REVERSED)
if (sizeof(struct outname) != SZ_NAME)
#endif
{
register char *c = (char *) name + (long) cnt * SZ_NAME;
name += cnt;
while (cnt--) {
name--;
c -= 4; name->on_valu = get4(c);
c -= 2; name->on_desc = uget2(c);
c -= 2; name->on_type = uget2(c);
c -= 4; name->on_foff = get4(c);
}
}
}
void rd_string(char *addr, long len)
{
OUTREAD(PARTCHAR, addr, len);
}
#ifdef SYMDBUG
void rd_dbug(char *buf, long size)
{
OUTREAD(PARTDBUG, buf, size);
}
#endif

View File

@ -1,10 +0,0 @@
/*
* Headers for rd.c
*/
#include "out.h"
extern void rd_string(char *addr, long len);
extern void rd_name(struct outname name[], unsigned int cnt);
extern int rd_fdopen(int fd);
extern void rd_ohead(register struct outhead head[]);

View File

@ -1,39 +0,0 @@
/* $Header$ */
/*
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
*/
#include <sys/types.h>
#include <unistd.h>
#include <arch.h>
#include "object.h"
#include "arch.h"
#include "archiver.h"
int
rd_arhdr(int fd, register struct ar_hdr *arhdr)
{
char buf[AR_TOTAL];
register char *c = buf;
register char *p = arhdr->ar_name;
register int i;
i = read(fd, c, AR_TOTAL);
if (i == 0) return 0;
if (i != AR_TOTAL) {
rd_fatal();
}
i = 14;
while (i--) {
*p++ = *c++;
}
arhdr->ar_date = ((long) get2(c)) << 16; c += 2;
arhdr->ar_date |= ((long) get2(c)) & 0xffff; c += 2;
arhdr->ar_uid = *c++;
arhdr->ar_gid = *c++;
arhdr->ar_mode = get2(c); c += 2;
arhdr->ar_size = (long) get2(c) << 16; c += 2;
arhdr->ar_size |= (long) get2(c) & 0xffff;
return 1;
}

View File

@ -1,35 +0,0 @@
/* $Header$ */
/*
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
*/
#define MININT (1 << (sizeof(int) * 8 - 1))
#define MAXCHUNK (~MININT) /* Highest count we read(2). */
/* Unfortunately, MAXCHUNK is too large with some compilers. Put it in
an int!
*/
#include <sys/types.h>
#include <unistd.h>
#include "archiver.h"
#include "rd_bytes.h"
static int maxchunk = MAXCHUNK;
/*
* We don't have to worry about byte order here.
* Just read "cnt" bytes from file-descriptor "fd".
*/
void rd_bytes(int fd, char *string, long cnt)
{
while (cnt) {
register int n = cnt >= maxchunk ? maxchunk : cnt;
if (read(fd, string, n) != n)
rd_fatal();
string += n;
cnt -= n;
}
}

View File

@ -1,2 +0,0 @@
extern void rd_bytes(int fd, char *string, long cnt);

View File

@ -1,16 +0,0 @@
/* $Header$ */
/*
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
*/
#include "object.h"
#include "rd_bytes.h"
unsigned int
rd_unsigned2(int fd)
{
char buf[2];
rd_bytes(fd, buf, 2L);
return uget2(buf);
}

View File

@ -1,43 +0,0 @@
/*
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
*/
/* $Header$ */
#if __STDC__
#include <stdarg.h>
#else
#include <varargs.h>
#endif
#include <system.h>
#include "param.h"
#include "format.h"
/*VARARGS*/
/*FORMAT1v $
%s = char *
%l = long
%c = int
%[uxbo] = unsigned int
%d = int
$ */
char *
#if __STDC__
sprint(char *buf, char *fmt, ...)
#else
sprint(buf, fmt, va_alist)
char *buf, *fmt;
va_dcl
#endif
{
va_list args;
#if __STDC__
va_start(args, fmt);
#else
va_start(args);
#endif
buf[_format(buf, fmt, args)] = '\0';
va_end(args);
return buf;
}

View File

@ -1,24 +0,0 @@
/*
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
*/
/* RCS: $Header$ */
#include <system.h>
File _sys_ftab[SYS_NOPEN] = {
{ 0, OP_READ},
{ 1, OP_APPEND},
{ 2, OP_APPEND}
};
File *
_get_entry()
{
register File *fp;
for (fp = &_sys_ftab[0]; fp < &_sys_ftab[SYS_NOPEN]; fp++)
if (fp->o_flags == 0)
return fp;
return (File *)0;
}

View File

@ -1,49 +0,0 @@
/*
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
*/
/* RCS: $Header$ */
#ifndef __SYSTEM_INCLUDED__
#define __SYSTEM_INCLUDED__
struct _sys_fildes {
int o_fd; /* UNIX filedescriptor */
int o_flags; /* flags for open; 0 if not used */
};
typedef struct _sys_fildes File;
extern File _sys_ftab[];
/* flags for sys_open() */
#define OP_READ 01
#define OP_WRITE 02
#define OP_APPEND 04
/* flags for sys_access() */
#define AC_EXIST 00
#define AC_READ 04
#define AC_WRITE 02
#define AC_EXEC 01
/* flags for sys_stop() */
#define S_END 0
#define S_EXIT 1
#define S_ABORT 2
/* standard file decsriptors */
#define STDIN &_sys_ftab[0]
#define STDOUT &_sys_ftab[1]
#define STDERR &_sys_ftab[2]
/* maximum number of open files */
#define SYS_NOPEN 20
/* return value for sys_break */
#define ILL_BREAK ((char *)0)
/* system's idea of block */
#ifndef BUFSIZ
#define BUFSIZ 1024
#endif
#endif /* __SYSTEM_INCLUDED__ */

View File

@ -1,16 +0,0 @@
/*
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
*/
/* $Header$ */
#ifndef _VARARGS_H
#define _VARARGS_H
typedef char *va_list;
# define __va_sz(mode) (((sizeof(mode) + sizeof(int) - 1) / sizeof(int)) * sizeof(int))
# define va_dcl int va_alist;
# define va_start(list) (list = (char *) &va_alist)
# define va_end(list)
# define va_arg(list,mode) (*((mode *)((list += __va_sz(mode)) - __va_sz(mode))))
#endif /* _VARARGS_H */

View File

@ -1,30 +0,0 @@
/* $Header$ */
/*
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
*/
#include <arch.h>
#include "object.h"
#include "arch.h"
#include "write.h"
#include "wr_bytes.h"
void wr_arhdr(int fd, struct ar_hdr *arhdr)
{
char buf[AR_TOTAL];
register char *c = buf;
register char *p = arhdr->ar_name;
register int i = 14;
while (i--) {
*c++ = *p++;
}
put2((int)(arhdr->ar_date>>16),c); c += 2;
put2((int)(arhdr->ar_date),c); c += 2;
*c++ = arhdr->ar_uid;
*c++ = arhdr->ar_gid;
put2(arhdr->ar_mode,c); c += 2;
put2((int)(arhdr->ar_size>>16),c); c += 2;
put2((int)(arhdr->ar_size),c);
wr_bytes(fd, buf, (long) AR_TOTAL);
}

View File

@ -1,33 +0,0 @@
/* $Header$ */
/*
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
*/
#define MININT (1 << (sizeof(int) * 8 - 1))
#define MAXCHUNK (~MININT) /* Highest count we write(2). */
/* Notice that MAXCHUNK itself might be too large with some compilers.
You have to put it in an int!
*/
#include <sys/types.h>
#include <unistd.h>
#include "wr_bytes.h"
#include "archiver.h"
static int maxchunk = MAXCHUNK;
/*
* Just write "cnt" bytes to file-descriptor "fd".
*/
void wr_bytes(int fd, register char *string, long cnt)
{
while (cnt) {
register int n = cnt >= maxchunk ? maxchunk : cnt;
if (write(fd, string, n) != n)
wr_fatal();
string += n;
cnt -= n;
}
}

View File

@ -1,4 +0,0 @@
/*
* Exported symbols of wr_bytes.c
*/
extern void wr_bytes(int fd, register char *string, long cnt);

View File

@ -1,16 +0,0 @@
/* $Header$ */
/*
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
*/
#include "object.h"
#include "wr_int2.h"
#include "wr_bytes.h"
void wr_int2(int fd, int i)
{
char buf[2];
put2(i, buf);
wr_bytes(fd, buf, 2L);
}

View File

@ -1,2 +0,0 @@
extern void wr_int2(int fd, int i);

View File

@ -1,16 +0,0 @@
/* $Header$ */
/*
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
*/
#include "object.h"
#include "wr_bytes.h"
#include "wr_long.h"
void wr_long(int fd, long l)
{
char buf[4];
put4(l, buf);
wr_bytes(fd, buf, 4L);
}

View File

@ -1,2 +0,0 @@
extern void wr_long(int fd, long l);

View File

@ -1,36 +0,0 @@
/* $Header$ */
/*
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
*/
#include <ranlib.h>
#include "object.h"
#include "wr_bytes.h"
#include "ranlib.h"
void wr_ranlib(int fd, struct ranlib *ran, long cnt)
{
#if ! (BYTES_REVERSED || WORDS_REVERSED)
if (sizeof (struct ranlib) != SZ_RAN)
#endif
{
char buf[100 * SZ_RAN];
while (cnt) {
register int i = (cnt > 100) ? 100 : cnt;
register char *c = buf;
long j = i * SZ_RAN;
cnt -= i;
while (i--) {
put4(ran->ran_off,c); c += 4;
put4(ran->ran_pos,c); c += 4;
ran++;
}
wr_bytes(fd, buf, j);
}
}
#if ! (BYTES_REVERSED || WORDS_REVERSED)
else wr_bytes(fd, (char *) ran, cnt * SZ_RAN);
#endif
}

View File

@ -1,17 +0,0 @@
/*
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
*/
/* $Header$ */
#include <sys/types.h>
#include <unistd.h>
#include <system.h>
#include "write.h"
int
sys_write(File *fp, char *bufptr, int nbytes)
{
if (! fp) return 0;
return write(fp->o_fd, bufptr, nbytes) == nbytes;
}

View File

@ -1,3 +0,0 @@
#include "system.h"
extern int sys_write(File *fp, char *bufptr, int nbytes);

View File

@ -1,10 +0,0 @@
# Makefile for acd
.include <bsd.own.mk>
PROG= acd
CPPFLAGS+= -DARCH=\"`arch`\" -DDESCR=\"/usr/lib/descr\"
LINKS+= ${BINDIR}/acd ${BINDIR}/cc
MAN=
.include <bsd.prog.mk>

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +0,0 @@
SCRIPTS= ackmkdep.sh
MAN=
.include <bsd.prog.mk>

View File

@ -1,60 +0,0 @@
#!/bin/sh
#
# ackmkdep 1.1 - Generate Makefile dependencies. Author: Kees J. Bot
#
# Does what 'cc -M' should do, but no compiler gets it right, they all
# strip the leading path of the '.o' file.)
#
# Added option to generate .depend files in subdirectories of given dir.
# Jorrit N. Herder
set -e
case $# in
# Display help ...
0)
echo "Usage: ackmkdep 'cpp command' file ..." >&2
echo " ackmkdep directory" >&2
;;
# Create .depend files ...
1)
echo "Creating .depend files in $1"
for dir in `find $1 -type d ! -name CVS ! -name .svn`
do
touch $dir/.depend
done
;;
# Get dependencies ...
*)
cpp="$1"; shift
for f
do
: < "$f" || exit
o=`expr "$f" : '\(.*\)\..*'`.o
o=`basename $o`
echo
$cpp "$f" | \
/usr/bin/sed -e '/^#/!d
s/.*"\(.*\)".*/\1/
s:^\./::' \
-e '/^<built-in>$/d' \
-e '/^<command.line>$/d' \
-e "s:^:$o\: :" | \
sort -u
done
esac
exit 0
#
# $PchId: mkdep.sh,v 1.3 1998/07/23 21:24:38 philip Exp $
#

View File

@ -1,4 +0,0 @@
PROG= ackstrip
MAN=
.include <bsd.prog.mk>

View File

@ -1,169 +0,0 @@
/* strip - remove symbols. Author: Dick van Veen */
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <a.out.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
/* Strip [file] ...
*
* - when no file is present, a.out is assumed.
*
*/
#define A_OUT "a.out"
#define NAME_LENGTH 128 /* max file path name */
char buffer[BUFSIZ]; /* used to copy executable */
char new_file[NAME_LENGTH]; /* contains name of temporary */
struct exec header;
_PROTOTYPE(int main, (int argc, char **argv));
_PROTOTYPE(void strip, (char *file));
_PROTOTYPE(int read_header, (int fd));
_PROTOTYPE(int write_header, (int fd));
_PROTOTYPE(int make_tmp, (char *new_name, char *name));
_PROTOTYPE(int copy_file, (int fd1, int fd2, long size));
int main(argc, argv)
int argc;
char **argv;
{
argv++;
if (*argv == NULL)
strip(A_OUT);
else
while (*argv != NULL) {
strip(*argv);
argv++;
}
return(0);
}
void strip(file)
char *file;
{
int fd, new_fd;
struct stat buf;
long symb_size, relo_size;
fd = open(file, O_RDONLY);
if (fd == -1) {
fprintf(stderr, "can't open %s\n", file);
close(fd);
return;
}
if (read_header(fd)) {
fprintf(stderr, "%s: not an executable file\n", file);
close(fd);
return;
}
if (header.a_syms == 0L) {
close(fd); /* no symbol table present */
return;
}
symb_size = header.a_syms;
header.a_syms = 0L; /* remove table size */
fstat(fd, &buf);
relo_size = buf.st_size - (A_MINHDR + header.a_text + header.a_data + symb_size);
new_fd = make_tmp(new_file, file);
if (new_fd == -1) {
fprintf(stderr, "can't create temporary file\n");
close(fd);
return;
}
if (write_header(new_fd)) {
fprintf(stderr, "can't write temporary file\n");
unlink(new_file);
close(fd);
close(new_fd);
return;
}
if (copy_file(fd, new_fd, header.a_text + header.a_data)) {
fprintf(stderr, "can't copy %s\n", file);
unlink(new_file);
close(fd);
close(new_fd);
return;
}
if (relo_size != 0) {
lseek(fd, symb_size, 1);
if (copy_file(fd, new_fd, relo_size)) {
fprintf(stderr, "can't copy %s\n", file);
unlink(new_file);
close(fd);
close(new_fd);
return;
}
}
close(fd);
close(new_fd);
if (unlink(file) == -1) {
fprintf(stderr, "can't unlink %s\n", file);
unlink(new_file);
return;
}
link(new_file, file);
unlink(new_file);
chmod(file, buf.st_mode);
}
int read_header(fd)
int fd;
{
if (read(fd, (char *) &header, A_MINHDR) != A_MINHDR) return(1);
if (BADMAG(header)) return (1);
if (header.a_hdrlen > sizeof(struct exec)) return (1);
lseek(fd, 0L, SEEK_SET); /* variable size header */
if (read(fd, (char *)&header, (int)header.a_hdrlen) != (int) header.a_hdrlen)
return(1);
return(0);
}
int write_header(fd)
int fd;
{
lseek(fd, 0L, SEEK_SET);
if (write(fd, (char *)&header, (int)header.a_hdrlen) != (int)header.a_hdrlen)
return(1);
return(0);
}
int make_tmp(new_name, name)
char *new_name, *name;
{
int len;
char *nameptr;
len = strlen(name);
if (len + 1 > NAME_LENGTH) return(-1);
strcpy(new_name, name);
nameptr = strrchr(new_name, '/');
if (nameptr == NULL) nameptr = new_name - 1;
if (nameptr - new_name + 6 + 1 > NAME_LENGTH) return (-1);
strcpy(nameptr + 1, "XXXXXX");
mktemp(new_name);
return(creat(new_name, 0777));
}
int copy_file(fd1, fd2, size)
int fd1, fd2;
long size;
{
int length;
while (size > 0) {
if (size < sizeof(buffer))
length = size;
else
length = sizeof(buffer);
if (read(fd1, buffer, length) != length) return(1);
if (write(fd2, buffer, length) != length) return (1);
size -= length;
}
return(0);
}

View File

@ -1,8 +0,0 @@
# Makefile for asmconv.
PROG= asmconv
SRCS= asm86.c asmconv.c parse_ack.c parse_gnu.c parse_bas.c \
tokenize.c emit_ack.c emit_gnu.c
MAN=
.include <bsd.prog.mk>

View File

@ -1,85 +0,0 @@
/* asm86.c - 80X86 assembly intermediate Author: Kees J. Bot
* 24 Dec 1993
*/
#define nil 0
#include <stddef.h>
#include <string.h>
#include <assert.h>
#include "asm86.h"
#include "asmconv.h"
#include "token.h"
expression_t *new_expr(void)
/* Make a new cell to build an expression. */
{
expression_t *e;
e= allocate(nil, sizeof(*e));
e->operator= -1;
e->left= e->middle= e->right= nil;
e->name= nil;
e->magic= 31624;
return e;
}
void del_expr(expression_t *e)
/* Delete an expression tree. */
{
if (e != nil) {
assert(e->magic == 31624);
e->magic= 0;
deallocate(e->name);
del_expr(e->left);
del_expr(e->middle);
del_expr(e->right);
deallocate(e);
}
}
asm86_t *new_asm86(void)
/* Make a new cell to hold an 80X86 instruction. */
{
asm86_t *a;
a= allocate(nil, sizeof(*a));
a->opcode= -1;
get_file(&a->file, &a->line);
a->optype= -1;
a->oaz= 0;
a->rep= ONCE;
a->seg= DEFSEG;
a->args= nil;
a->magic= 37937;
return a;
}
void del_asm86(asm86_t *a)
/* Delete an 80X86 instruction. */
{
assert(a != nil);
assert(a->magic == 37937);
a->magic= 0;
del_expr(a->args);
deallocate(a);
}
int isregister(const char *name)
/* True if the string is a register name. Return its size. */
{
static char *regs[] = {
"al", "bl", "cl", "dl", "ah", "bh", "ch", "dh",
"ax", "bx", "cx", "dx", "si", "di", "bp", "sp",
"cs", "ds", "es", "fs", "gs", "ss",
"eax", "ebx", "ecx", "edx", "esi", "edi", "ebp", "esp",
"cr0", "cr1", "cr2", "cr3",
"st",
};
int reg;
for (reg= 0; reg < arraysize(regs); reg++) {
if (strcmp(name, regs[reg]) == 0) {
return reg < 8 ? 1 : reg < 22 ? 2 : 4;
}
}
return 0;
}

View File

@ -1,250 +0,0 @@
/* asm86.h - 80X86 assembly intermediate Author: Kees J. Bot
* 27 Jun 1993
*/
typedef enum opcode { /* 80486 opcodes, from the i486 reference manual.
* Synonyms left out, some new words invented.
*/
DOT_ALIGN,
DOT_ASCII, DOT_ASCIZ,
DOT_ASSERT, /* Pseudo's invented */
DOT_BASE,
DOT_COMM, DOT_LCOMM,
DOT_DATA1,
DOT_DATA2,
DOT_DATA4,
DOT_DEFINE, DOT_EXTERN,
DOT_EQU,
DOT_FILE, DOT_LINE,
DOT_LABEL,
DOT_LIST, DOT_NOLIST,
DOT_SPACE,
DOT_SYMB,
DOT_TEXT, DOT_ROM, DOT_DATA, DOT_BSS, DOT_END,
DOT_USE16, DOT_USE32,
AAA,
AAD,
AAM,
AAS,
ADC,
ADD,
AND,
ARPL,
BOUND,
BSF,
BSR,
BSWAP,
BT,
BTC,
BTR,
BTS,
CALL, CALLF, /* CALLF added */
CBW,
CLC,
CLD,
CLI,
CLTS,
CMC,
CMP,
CMPS,
CMPXCHG,
CWD,
DAA,
DAS,
DEC,
DIV,
ENTER,
F2XM1,
FABS,
FADD, FADDD, FADDS, FADDP, FIADDL, FIADDS,
FBLD,
FBSTP,
FCHS,
FCLEX,
FCOMD, FCOMS, FCOMPD, FCOMPS, FCOMPP,
FCOS,
FDECSTP,
FDIVD, FDIVS, FDIVP, FIDIVL, FIDIVS,
FDIVRD, FDIVRS, FDIVRP, FIDIVRL, FIDIVRS,
FFREE,
FICOM, FICOMP,
FILDQ, FILDL, FILDS,
FINCSTP,
FINIT,
FISTL, FISTS, FISTP,
FLDX, FLDD, FLDS,
FLD1, FLDL2T, FLDL2E, FLDPI, FLDLG2, FLDLN2, FLDZ,
FLDCW,
FLDENV,
FMULD, FMULS, FMULP, FIMULL, FIMULS,
FNOP,
FPATAN,
FPREM,
FPREM1,
FPTAN,
FRNDINT,
FRSTOR,
FSAVE,
FSCALE,
FSIN,
FSINCOS,
FSQRT,
FSTD, FSTS, FSTP, FSTPX, FSTPD, FSTPS,
FSTCW,
FSTENV,
FSTSW,
FSUBD, FSUBS, FSUBP, FISUBL, FISUBS,
FSUBRD, FSUBRS, FSUBPR, FISUBRL, FISUBRS,
FTST,
FUCOM, FUCOMP, FUCOMPP,
FXAM,
FXCH,
FXTRACT,
FYL2X,
FYL2XP1,
HLT,
IDIV,
IMUL,
IN,
INC,
INS,
INT, INTO,
INVD,
INVLPG,
IRET, IRETD,
JA, JAE, JB, JBE, JCXZ, JE, JG, JGE, JL,
JLE, JNE, JNO, JNP, JNS, JO, JP, JS,
JMP, JMPF, /* JMPF added */
LAHF,
LAR,
LEA,
LEAVE,
LGDT, LIDT,
LGS, LSS, LDS, LES, LFS,
LLDT,
LMSW,
LOCK,
LODS,
LOOP, LOOPE, LOOPNE,
LSL,
LTR,
MOV,
MOVS,
MOVSX,
MOVSXB,
MOVZX,
MOVZXB,
MUL,
NEG,
NOP,
NOT,
OR,
OUT,
OUTS,
POP,
POPA,
POPF,
PUSH,
PUSHA,
PUSHF,
RCL, RCR, ROL, ROR,
RET, RETF, /* RETF added */
SAHF,
SAL, SAR, SHL, SHR,
SBB,
SCAS,
SETA, SETAE, SETB, SETBE, SETE, SETG, SETGE, SETL,
SETLE, SETNE, SETNO, SETNP, SETNS, SETO, SETP, SETS,
SGDT, SIDT,
SHLD,
SHRD,
SLDT,
SMSW,
STC,
STD,
STI,
STOS,
STR,
SUB,
TEST,
VERR, VERW,
WAIT,
WBINVD,
XADD,
XCHG,
XLAT,
XOR
} opcode_t;
#define is_pseudo(o) ((o) <= DOT_USE32)
#define N_OPCODES ((int) XOR + 1)
#define OPZ 0x01 /* Operand size prefix. */
#define ADZ 0x02 /* Address size prefix. */
typedef enum optype {
PSEUDO, JUMP, BYTE, WORD, OWORD /* Ordered list! */
} optype_t;
typedef enum repeat {
ONCE, REP, REPE, REPNE
} repeat_t;
typedef enum segment {
DEFSEG, CSEG, DSEG, ESEG, FSEG, GSEG, SSEG
} segment_t;
typedef struct expression {
int operator;
struct expression *left, *middle, *right;
char *name;
size_t len;
unsigned magic;
} expression_t;
typedef struct asm86 {
opcode_t opcode; /* DOT_TEXT, MOV, ... */
char *file; /* Name of the file it is found in. */
long line; /* Line number. */
optype_t optype; /* Type of operands: byte, word... */
int oaz; /* Operand/address size prefix? */
repeat_t rep; /* Repeat prefix used on this instr. */
segment_t seg; /* Segment override. */
expression_t *args; /* Arguments in ACK order. */
unsigned magic;
} asm86_t;
expression_t *new_expr(void);
void del_expr(expression_t *a);
asm86_t *new_asm86(void);
void del_asm86(asm86_t *a);
int isregister(const char *name);
/*
* Format of the arguments of the asm86_t structure:
*
*
* ACK assembly operands expression_t cell:
* or part of operand: {operator, left, middle, right, name, len}
*
* [expr] {'[', nil, expr, nil}
* word {'W', nil, nil, nil, word}
* "string" {'S', nil, nil, nil, "string", strlen("string")}
* label = expr {'=', nil, expr, nil, label}
* expr * expr {'*', expr, nil, expr}
* - expr {'-', nil, expr, nil}
* (memory) {'(', nil, memory, nil}
* offset(base)(index*n) {'O', offset, base, index*n}
* base {'B', nil, nil, nil, base}
* index*4 {'4', nil, nil, nil, index}
* operand, oplist {',', operand, nil, oplist}
* label : {':', nil, nil, nil, label}
*
* The precedence of operators is ignored. The expression is simply copied
* as is, including parentheses. Problems like missing operators in the
* target language will have to be handled by rewriting the source language.
* 16-bit or 32-bit registers must be used where they are required by the
* target assembler even though ACK makes no difference between 'ax' and
* 'eax'. Asmconv is smart enough to transform compiler output. Human made
* assembly can be fixed up to be transformable.
*/

View File

@ -1,157 +0,0 @@
/* asmconv 1.11 - convert 80X86 assembly Author: Kees J. Bot
* 24 Dec 1993
*/
static char version[] = "1.11";
#define nil 0
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include "asmconv.h"
#include "asm86.h"
#include "languages.h"
void fatal(char *label)
{
fprintf(stderr, "asmconv: %s: %s\n", label, strerror(errno));
exit(EXIT_FAILURE);
}
void *allocate(void *mem, size_t size)
/* A checked malloc/realloc(). Yes, I know ISO C allows realloc(NULL, size). */
{
mem= mem == nil ? malloc(size) : realloc(mem, size);
if (mem == nil) fatal("malloc()");
return mem;
}
void deallocate(void *mem)
/* Free a malloc()d cell. (Yes I know ISO C allows free(NULL) */
{
if (mem != nil) free(mem);
}
char *copystr(const char *s)
{
char *c;
c= allocate(nil, (strlen(s) + 1) * sizeof(s[0]));
strcpy(c, s);
return c;
}
int isanumber(const char *s)
/* True if s can be turned into a number. */
{
char *end;
(void) strtol(s, &end, 0);
return end != s && *end == 0;
}
/* "Invisible" globals. */
int asm_mode32= (sizeof(int) == 4);
int err_code= EXIT_SUCCESS;
int main(int argc, char **argv)
{
void (*parse_init)(char *file);
asm86_t *(*get_instruction)(void);
void (*emit_init)(char *file, const char *banner);
void (*emit_instruction)(asm86_t *instr);
char *lang_parse, *lang_emit, *input_file, *output_file;
asm86_t *instr;
char banner[80];
if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'm') {
if (strcmp(argv[1], "-mi86") == 0) {
set_use16();
} else
if (strcmp(argv[1], "-mi386") == 0) {
set_use32();
} else {
fprintf(stderr, "asmconv: '%s': unknown machine\n",
argv[1]+2);
}
argc--;
argv++;
}
if (argc < 3 || argc > 5) {
fprintf(stderr,
"Usage: asmconv <input-type> <output-type> [input-file [output-file]]\n");
exit(EXIT_FAILURE);
}
lang_parse= argv[1];
lang_emit= argv[2];
input_file= argc < 4 ? nil : argv[3];
output_file= argc < 5 ? nil : argv[4];
/* Choose the parsing routines. */
if (strcmp(lang_parse, "ack") == 0) {
/* Standard ACK. */
parse_init= ack_parse_init;
get_instruction= ack_get_instruction;
} else
if (strcmp(lang_parse, "ncc") == 0) {
/* ACK Xenix assembly, a black sheep among ACK assemblies. */
parse_init= ncc_parse_init;
get_instruction= ncc_get_instruction;
} else
if (strcmp(lang_parse, "gnu") == 0) {
/* GNU assembly. Parser by R.S. Veldema. */
parse_init= gnu_parse_init;
get_instruction= gnu_get_instruction;
} else
if (strcmp(lang_parse, "bas") == 0) {
/* Bruce Evans' assembler. */
parse_init= bas_parse_init;
get_instruction= bas_get_instruction;
} else {
fprintf(stderr, "asmconv: '%s': unknown input language\n",
lang_parse);
exit(EXIT_FAILURE);
}
/* Choose the output language. */
if (strcmp(lang_emit, "ack") == 0) {
/* Standard ACK. */
emit_init= ack_emit_init;
emit_instruction= ack_emit_instruction;
} else
if (strcmp(lang_emit, "ncc") == 0) {
/* ACK Xenix assembly, can be read by BAS and the 8086 ACK
* ANSI C compiler. (Allows us to compile the Boot Monitor.)
*/
emit_init= ncc_emit_init;
emit_instruction= ncc_emit_instruction;
} else
if (strcmp(lang_emit, "gnu") == 0) {
/* GNU assembler. So we can assemble the ACK stuff among the
* kernel sources and in the library.
*/
emit_init= gnu_emit_init;
emit_instruction= gnu_emit_instruction;
} else {
fprintf(stderr, "asmconv: '%s': unknown output language\n",
lang_emit);
exit(EXIT_FAILURE);
}
sprintf(banner, "Translated from %s to %s by asmconv %s",
lang_parse, lang_emit, version);
(*parse_init)(input_file);
(*emit_init)(output_file, banner);
for (;;) {
instr= (*get_instruction)();
(*emit_instruction)(instr);
if (instr == nil) break;
del_asm86(instr);
}
exit(err_code);
}

View File

@ -1,24 +0,0 @@
/* asmconv.h - shared functions Author: Kees J. Bot
* 19 Dec 1993
*/
#define arraysize(a) (sizeof(a)/sizeof((a)[0]))
#define arraylimit(a) ((a) + arraysize(a))
#define between(a, c, z) \
((unsigned)((c) - (a)) <= (unsigned)((z) - (a)))
void *allocate(void *mem, size_t size);
void deallocate(void *mem);
void fatal(char *label);
char *copystr(const char *s);
int isanumber(const char *s);
extern int asm_mode32; /* In 32 bit mode if true. */
#define use16() (!asm_mode32)
#define use32() ((int) asm_mode32)
#define set_use16() ((void) (asm_mode32= 0))
#define set_use32() ((void) (asm_mode32= 1))
extern int err_code; /* Exit code. */
#define set_error() ((void) (err_code= EXIT_FAILURE))

View File

@ -1,621 +0,0 @@
/* emit_ack.c - emit ACK assembly Author: Kees J. Bot
* emit NCC assembly 27 Dec 1993
*/
#define nil 0
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <assert.h>
#include "asmconv.h"
#include "token.h"
#include "asm86.h"
#include "languages.h"
typedef struct mnemonic { /* ACK as86 mnemonics translation table. */
opcode_t opcode;
char *name;
} mnemonic_t;
static mnemonic_t mnemtab[] = {
{ AAA, "aaa" },
{ AAD, "aad" },
{ AAM, "aam" },
{ AAS, "aas" },
{ ADC, "adc%" },
{ ADD, "add%" },
{ AND, "and%" },
{ ARPL, "arpl" },
{ BOUND, "bound" },
{ BSF, "bsf" },
{ BSR, "bsr" },
{ BSWAP, "bswap" },
{ BT, "bt" },
{ BTC, "btc" },
{ BTR, "btr" },
{ BTS, "bts" },
{ CALL, "call" },
{ CALLF, "callf" },
{ CBW, "cbw" },
{ CLC, "clc" },
{ CLD, "cld" },
{ CLI, "cli" },
{ CLTS, "clts" },
{ CMC, "cmc" },
{ CMP, "cmp%" },
{ CMPS, "cmps%" },
{ CMPXCHG, "cmpxchg" },
{ CWD, "cwd" },
{ DAA, "daa" },
{ DAS, "das" },
{ DEC, "dec%" },
{ DIV, "div%" },
{ DOT_ALIGN, ".align" },
{ DOT_ASCII, ".ascii" },
{ DOT_ASCIZ, ".asciz" },
{ DOT_ASSERT, ".assert" },
{ DOT_BASE, ".base" },
{ DOT_BSS, ".sect .bss" },
{ DOT_COMM, ".comm" },
{ DOT_DATA, ".sect .data" },
{ DOT_DATA1, ".data1" },
{ DOT_DATA2, ".data2" },
{ DOT_DATA4, ".data4" },
{ DOT_DEFINE, ".define" },
{ DOT_END, ".sect .end" },
{ DOT_EXTERN, ".extern" },
{ DOT_FILE, ".file" },
{ DOT_LCOMM, ".comm" },
{ DOT_LINE, ".line" },
{ DOT_LIST, ".list" },
{ DOT_NOLIST, ".nolist" },
{ DOT_ROM, ".sect .rom" },
{ DOT_SPACE, ".space" },
{ DOT_SYMB, ".symb" },
{ DOT_TEXT, ".sect .text" },
{ DOT_USE16, ".use16" },
{ DOT_USE32, ".use32" },
{ ENTER, "enter" },
{ F2XM1, "f2xm1" },
{ FABS, "fabs" },
{ FADD, "fadd" },
{ FADDD, "faddd" },
{ FADDP, "faddp" },
{ FADDS, "fadds" },
{ FBLD, "fbld" },
{ FBSTP, "fbstp" },
{ FCHS, "fchs" },
{ FCLEX, "fclex" },
{ FCOMD, "fcomd" },
{ FCOMPD, "fcompd" },
{ FCOMPP, "fcompp" },
{ FCOMPS, "fcomps" },
{ FCOMS, "fcoms" },
{ FCOS, "fcos" },
{ FDECSTP, "fdecstp" },
{ FDIVD, "fdivd" },
{ FDIVP, "fdivp" },
{ FDIVRD, "fdivrd" },
{ FDIVRP, "fdivrp" },
{ FDIVRS, "fdivrs" },
{ FDIVS, "fdivs" },
{ FFREE, "ffree" },
{ FIADDL, "fiaddl" },
{ FIADDS, "fiadds" },
{ FICOM, "ficom" },
{ FICOMP, "ficomp" },
{ FIDIVL, "fidivl" },
{ FIDIVRL, "fidivrl" },
{ FIDIVRS, "fidivrs" },
{ FIDIVS, "fidivs" },
{ FILDL, "fildl" },
{ FILDQ, "fildq" },
{ FILDS, "filds" },
{ FIMULL, "fimull" },
{ FIMULS, "fimuls" },
{ FINCSTP, "fincstp" },
{ FINIT, "finit" },
{ FISTL, "fistl" },
{ FISTP, "fistp" },
{ FISTS, "fists" },
{ FISUBL, "fisubl" },
{ FISUBRL, "fisubrl" },
{ FISUBRS, "fisubrs" },
{ FISUBS, "fisubs" },
{ FLD1, "fld1" },
{ FLDCW, "fldcw" },
{ FLDD, "fldd" },
{ FLDENV, "fldenv" },
{ FLDL2E, "fldl2e" },
{ FLDL2T, "fldl2t" },
{ FLDLG2, "fldlg2" },
{ FLDLN2, "fldln2" },
{ FLDPI, "fldpi" },
{ FLDS, "flds" },
{ FLDX, "fldx" },
{ FLDZ, "fldz" },
{ FMULD, "fmuld" },
{ FMULP, "fmulp" },
{ FMULS, "fmuls" },
{ FNOP, "fnop" },
{ FPATAN, "fpatan" },
{ FPREM, "fprem" },
{ FPREM1, "fprem1" },
{ FPTAN, "fptan" },
{ FRNDINT, "frndint" },
{ FRSTOR, "frstor" },
{ FSAVE, "fsave" },
{ FSCALE, "fscale" },
{ FSIN, "fsin" },
{ FSINCOS, "fsincos" },
{ FSQRT, "fsqrt" },
{ FSTCW, "fstcw" },
{ FSTD, "fstd" },
{ FSTENV, "fstenv" },
{ FSTPD, "fstpd" },
{ FSTPS, "fstps" },
{ FSTPX, "fstpx" },
{ FSTS, "fsts" },
{ FSTSW, "fstsw" },
{ FSUBD, "fsubd" },
{ FSUBP, "fsubp" },
{ FSUBPR, "fsubpr" },
{ FSUBRD, "fsubrd" },
{ FSUBRS, "fsubrs" },
{ FSUBS, "fsubs" },
{ FTST, "ftst" },
{ FUCOM, "fucom" },
{ FUCOMP, "fucomp" },
{ FUCOMPP, "fucompp" },
{ FXAM, "fxam" },
{ FXCH, "fxch" },
{ FXTRACT, "fxtract" },
{ FYL2X, "fyl2x" },
{ FYL2XP1, "fyl2xp1" },
{ HLT, "hlt" },
{ IDIV, "idiv%" },
{ IMUL, "imul%" },
{ IN, "in%" },
{ INC, "inc%" },
{ INS, "ins%" },
{ INT, "int" },
{ INTO, "into" },
{ INVD, "invd" },
{ INVLPG, "invlpg" },
{ IRET, "iret" },
{ IRETD, "iretd" },
{ JA, "ja" },
{ JAE, "jae" },
{ JB, "jb" },
{ JBE, "jbe" },
{ JCXZ, "jcxz" },
{ JE, "je" },
{ JG, "jg" },
{ JGE, "jge" },
{ JL, "jl" },
{ JLE, "jle" },
{ JMP, "jmp" },
{ JMPF, "jmpf" },
{ JNE, "jne" },
{ JNO, "jno" },
{ JNP, "jnp" },
{ JNS, "jns" },
{ JO, "jo" },
{ JP, "jp" },
{ JS, "js" },
{ LAHF, "lahf" },
{ LAR, "lar" },
{ LDS, "lds" },
{ LEA, "lea" },
{ LEAVE, "leave" },
{ LES, "les" },
{ LFS, "lfs" },
{ LGDT, "lgdt" },
{ LGS, "lgs" },
{ LIDT, "lidt" },
{ LLDT, "lldt" },
{ LMSW, "lmsw" },
{ LOCK, "lock" },
{ LODS, "lods%" },
{ LOOP, "loop" },
{ LOOPE, "loope" },
{ LOOPNE, "loopne" },
{ LSL, "lsl" },
{ LSS, "lss" },
{ LTR, "ltr" },
{ MOV, "mov%" },
{ MOVS, "movs%" },
{ MOVSX, "movsx" },
{ MOVSXB, "movsxb" },
{ MOVZX, "movzx" },
{ MOVZXB, "movzxb" },
{ MUL, "mul%" },
{ NEG, "neg%" },
{ NOP, "nop" },
{ NOT, "not%" },
{ OR, "or%" },
{ OUT, "out%" },
{ OUTS, "outs%" },
{ POP, "pop" },
{ POPA, "popa" },
{ POPF, "popf" },
{ PUSH, "push" },
{ PUSHA, "pusha" },
{ PUSHF, "pushf" },
{ RCL, "rcl%" },
{ RCR, "rcr%" },
{ RET, "ret" },
{ RETF, "retf" },
{ ROL, "rol%" },
{ ROR, "ror%" },
{ SAHF, "sahf" },
{ SAL, "sal%" },
{ SAR, "sar%" },
{ SBB, "sbb%" },
{ SCAS, "scas%" },
{ SETA, "seta" },
{ SETAE, "setae" },
{ SETB, "setb" },
{ SETBE, "setbe" },
{ SETE, "sete" },
{ SETG, "setg" },
{ SETGE, "setge" },
{ SETL, "setl" },
{ SETLE, "setle" },
{ SETNE, "setne" },
{ SETNO, "setno" },
{ SETNP, "setnp" },
{ SETNS, "setns" },
{ SETO, "seto" },
{ SETP, "setp" },
{ SETS, "sets" },
{ SGDT, "sgdt" },
{ SHL, "shl%" },
{ SHLD, "shld" },
{ SHR, "shr%" },
{ SHRD, "shrd" },
{ SIDT, "sidt" },
{ SLDT, "sldt" },
{ SMSW, "smsw" },
{ STC, "stc" },
{ STD, "std" },
{ STI, "sti" },
{ STOS, "stos%" },
{ STR, "str" },
{ SUB, "sub%" },
{ TEST, "test%" },
{ VERR, "verr" },
{ VERW, "verw" },
{ WAIT, "wait" },
{ WBINVD, "wbinvd" },
{ XADD, "xadd" },
{ XCHG, "xchg%" },
{ XLAT, "xlat" },
{ XOR, "xor%" },
};
#define farjmp(o) ((o) == JMPF || (o) == CALLF)
static FILE *ef;
static long eline= 1;
static char *efile;
static char *orig_efile;
static char *opcode2name_tab[N_OPCODES];
static enum dialect { ACK, NCC } dialect= ACK;
static void ack_putchar(int c)
/* LOOK, this programmer checks the return code of putc! What an idiot, noone
* does that!
*/
{
if (putc(c, ef) == EOF) fatal(orig_efile);
}
static void ack_printf(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
if (vfprintf(ef, fmt, ap) == EOF) fatal(orig_efile);
va_end(ap);
}
void ack_emit_init(char *file, const char *banner)
/* Prepare producing an ACK assembly file. */
{
mnemonic_t *mp;
if (file == nil) {
file= "stdout";
ef= stdout;
} else {
if ((ef= fopen(file, "w")) == nil) fatal(file);
}
orig_efile= file;
efile= file;
ack_printf("! %s", banner);
if (dialect == ACK) {
/* Declare the four sections used under Minix. */
ack_printf(
"\n.sect .text; .sect .rom; .sect .data; .sect .bss\n.sect .text");
}
/* Initialize the opcode to mnemonic translation table. */
for (mp= mnemtab; mp < arraylimit(mnemtab); mp++) {
assert(opcode2name_tab[mp->opcode] == nil);
opcode2name_tab[mp->opcode]= mp->name;
}
}
#define opcode2name(op) (opcode2name_tab[op] + 0)
static void ack_put_string(const char *s, size_t n)
/* Emit a string with weird characters quoted. */
{
while (n > 0) {
int c= *s;
if (c < ' ' || c > 0177) {
ack_printf("\\%03o", c & 0xFF);
} else
if (c == '"' || c == '\\') {
ack_printf("\\%c", c);
} else {
ack_putchar(c);
}
s++;
n--;
}
}
static void ack_put_expression(asm86_t *a, expression_t *e, int deref)
/* Send an expression, i.e. instruction operands, to the output file. Deref
* is true when the rewrite for the ncc dialect may be made.
*/
{
assert(e != nil);
switch (e->operator) {
case ',':
if (dialect == NCC && farjmp(a->opcode)) {
/* ACK jmpf seg:off -> NCC jmpf off,seg */
ack_put_expression(a, e->right, deref);
ack_printf(", ");
ack_put_expression(a, e->left, deref);
} else {
ack_put_expression(a, e->left, deref);
ack_printf(farjmp(a->opcode) ? ":" : ", ");
ack_put_expression(a, e->right, deref);
}
break;
case 'O':
if (deref && a->optype == JUMP) ack_putchar('@');
if (e->left != nil) ack_put_expression(a, e->left, 0);
if (e->middle != nil) ack_put_expression(a, e->middle, 0);
if (e->right != nil) ack_put_expression(a, e->right, 0);
break;
case '(':
if (deref && a->optype == JUMP) ack_putchar('@');
if (!deref) ack_putchar('(');
ack_put_expression(a, e->middle, 0);
if (!deref) ack_putchar(')');
break;
case 'B':
ack_printf("(%s)", e->name);
break;
case '1':
case '2':
case '4':
case '8':
ack_printf((use16() && e->operator == '1')
? "(%s)" : "(%s*%c)", e->name, e->operator);
break;
case '+':
case '-':
case '~':
if (e->middle != nil) {
if (deref && a->optype != JUMP) ack_putchar('#');
ack_putchar(e->operator);
ack_put_expression(a, e->middle, 0);
break;
}
/*FALL THROUGH*/
case '*':
case '/':
case '%':
case '&':
case '|':
case '^':
case S_LEFTSHIFT:
case S_RIGHTSHIFT:
if (deref && a->optype != JUMP) ack_putchar('#');
ack_put_expression(a, e->left, 0);
if (e->operator == S_LEFTSHIFT) {
ack_printf("<<");
} else
if (e->operator == S_RIGHTSHIFT) {
ack_printf(">>");
} else {
ack_putchar(e->operator);
}
ack_put_expression(a, e->right, 0);
break;
case '[':
if (deref && a->optype != JUMP) ack_putchar('#');
ack_putchar('[');
ack_put_expression(a, e->middle, 0);
ack_putchar(']');
break;
case 'W':
if (deref && a->optype == JUMP && isregister(e->name))
{
ack_printf("(%s)", e->name);
break;
}
if (deref && a->optype != JUMP && !isregister(e->name)) {
ack_putchar('#');
}
ack_printf("%s", e->name);
break;
case 'S':
ack_putchar('"');
ack_put_string(e->name, e->len);
ack_putchar('"');
break;
default:
fprintf(stderr,
"asmconv: internal error, unknown expression operator '%d'\n",
e->operator);
exit(EXIT_FAILURE);
}
}
void ack_emit_instruction(asm86_t *a)
/* Output one instruction and its operands. */
{
int same= 0;
char *p;
static int high_seg;
int deref;
if (a == nil) {
/* Last call */
ack_putchar('\n');
return;
}
/* Make sure the line number of the line to be emitted is ok. */
if ((a->file != efile && strcmp(a->file, efile) != 0)
|| a->line < eline || a->line > eline+10) {
ack_putchar('\n');
ack_printf("# %ld \"%s\"\n", a->line, a->file);
efile= a->file;
eline= a->line;
} else {
if (a->line == eline) {
ack_printf("; ");
same= 1;
}
while (eline < a->line) {
ack_putchar('\n');
eline++;
}
}
if (a->opcode == DOT_LABEL) {
assert(a->args->operator == ':');
ack_printf("%s:", a->args->name);
} else
if (a->opcode == DOT_EQU) {
assert(a->args->operator == '=');
ack_printf("\t%s = ", a->args->name);
ack_put_expression(a, a->args->middle, 0);
} else
if ((p= opcode2name(a->opcode)) != nil) {
char *sep= dialect == ACK ? "" : ";";
if (!is_pseudo(a->opcode) && !same) ack_putchar('\t');
switch (a->rep) {
case ONCE: break;
case REP: ack_printf("rep"); break;
case REPE: ack_printf("repe"); break;
case REPNE: ack_printf("repne"); break;
default: assert(0);
}
if (a->rep != ONCE) {
ack_printf(dialect == ACK ? " " : "; ");
}
switch (a->seg) {
case DEFSEG: break;
case CSEG: ack_printf("cseg"); break;
case DSEG: ack_printf("dseg"); break;
case ESEG: ack_printf("eseg"); break;
case FSEG: ack_printf("fseg"); break;
case GSEG: ack_printf("gseg"); break;
case SSEG: ack_printf("sseg"); break;
default: assert(0);
}
if (a->seg != DEFSEG) {
ack_printf(dialect == ACK ? " " : "; ");
}
if (a->oaz & OPZ) ack_printf(use16() ? "o32 " : "o16 ");
if (a->oaz & ADZ) ack_printf(use16() ? "a32 " : "a16 ");
if (a->opcode == CBW) {
p= !(a->oaz & OPZ) == use16() ? "cbw" : "cwde";
}
if (a->opcode == CWD) {
p= !(a->oaz & OPZ) == use16() ? "cwd" : "cdq";
}
if (a->opcode == DOT_COMM && a->args != nil
&& a->args->operator == ','
&& a->args->left->operator == 'W'
) {
ack_printf(".define\t%s; ", a->args->left->name);
}
while (*p != 0) {
if (*p == '%') {
if (a->optype == BYTE) ack_putchar('b');
} else {
ack_putchar(*p);
}
p++;
}
if (a->args != nil) {
ack_putchar('\t');
switch (a->opcode) {
case IN:
case OUT:
case INT:
deref= 0;
break;
default:
deref= (dialect == NCC && a->optype != PSEUDO);
}
ack_put_expression(a, a->args, deref);
}
if (a->opcode == DOT_USE16) set_use16();
if (a->opcode == DOT_USE32) set_use32();
} else {
fprintf(stderr,
"asmconv: internal error, unknown opcode '%d'\n",
a->opcode);
exit(EXIT_FAILURE);
}
}
/* A few ncc mnemonics are different. */
static mnemonic_t ncc_mnemtab[] = {
{ DOT_BSS, ".bss" },
{ DOT_DATA, ".data" },
{ DOT_END, ".end" },
{ DOT_ROM, ".rom" },
{ DOT_TEXT, ".text" },
};
void ncc_emit_init(char *file, const char *banner)
/* The assembly produced by the Minix ACK ANSI C compiler for the 8086 is
* different from the normal ACK assembly, and different from the old K&R
* assembler. This brings us endless joy. (It was supposed to make
* translation of the assembly used by the old K&R assembler easier by
* not deviating too much from that dialect.)
*/
{
mnemonic_t *mp;
dialect= NCC;
ack_emit_init(file, banner);
/* Replace a few mnemonics. */
for (mp= ncc_mnemtab; mp < arraylimit(ncc_mnemtab); mp++) {
opcode2name_tab[mp->opcode]= mp->name;
}
}
void ncc_emit_instruction(asm86_t *a)
{
ack_emit_instruction(a);
}

View File

@ -1,679 +0,0 @@
/* emit_gnu.c - emit GNU assembly Author: Kees J. Bot
* 28 Dec 1993
*/
#define nil 0
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <assert.h>
#include "asmconv.h"
#include "token.h"
#include "asm86.h"
#include "languages.h"
typedef struct mnemonic { /* GNU as386 mnemonics translation table. */
opcode_t opcode;
char *name;
} mnemonic_t;
static mnemonic_t mnemtab[] = {
{ AAA, "aaa" },
{ AAD, "aad" },
{ AAM, "aam" },
{ AAS, "aas" },
{ ADC, "adc%" },
{ ADD, "add%" },
{ AND, "and%" },
{ ARPL, "arpl" },
{ BOUND, "bound%" },
{ BSF, "bsf%" },
{ BSR, "bsr%" },
{ BSWAP, "bswap" },
{ BT, "bt%" },
{ BTC, "btc%" },
{ BTR, "btr%" },
{ BTS, "bts%" },
{ CALL, "call" },
{ CALLF, "lcall" },
{ CBW, "cbtw" },
{ CLC, "clc" },
{ CLD, "cld" },
{ CLI, "cli" },
{ CLTS, "clts" },
{ CMC, "cmc" },
{ CMP, "cmp%" },
{ CMPS, "cmps%" },
{ CMPXCHG, "cmpxchg" },
{ CWD, "cwtd" },
{ DAA, "daa" },
{ DAS, "das" },
{ DEC, "dec%" },
{ DIV, "div%" },
{ DOT_ALIGN, ".align" },
{ DOT_ASCII, ".ascii" },
{ DOT_ASCIZ, ".asciz" },
{ DOT_ASSERT, ".assert" },
{ DOT_BASE, ".base" },
{ DOT_BSS, ".bss" },
{ DOT_COMM, ".comm" },
{ DOT_DATA, ".data" },
{ DOT_DATA1, ".byte" },
{ DOT_DATA2, ".short" },
{ DOT_DATA4, ".long" },
{ DOT_DEFINE, ".globl" },
{ DOT_EXTERN, ".globl" },
{ DOT_FILE, ".file" },
{ DOT_LCOMM, ".lcomm" },
{ DOT_LINE, ".line" },
{ DOT_LIST, ".list" },
{ DOT_NOLIST, ".nolist" },
{ DOT_ROM, ".data" }, /* Minix -- separate I&D. */
{ DOT_SPACE, ".space" },
{ DOT_SYMB, ".symb" },
{ DOT_TEXT, ".text" },
{ DOT_USE16, ".use16" },
{ DOT_USE32, ".use32" },
{ ENTER, "enter" },
{ F2XM1, "f2xm1" },
{ FABS, "fabs" },
{ FADD, "fadd" },
{ FADDD, "faddl" },
{ FADDP, "faddp" },
{ FADDS, "fadds" },
{ FBLD, "fbld" },
{ FBSTP, "fbstp" },
{ FCHS, "fchs" },
{ FCLEX, "fnclex" },
{ FCOMD, "fcoml" },
{ FCOMPD, "fcompl" },
{ FCOMPP, "fcompp" },
{ FCOMPS, "fcomps" },
{ FCOMS, "fcoms" },
{ FCOS, "fcos" },
{ FDECSTP, "fdecstp" },
{ FDIVD, "fdivl" },
{ FDIVP, "fdivp" },
{ FDIVRD, "fdivrl" },
{ FDIVRP, "fdivrp" },
{ FDIVRS, "fdivrs" },
{ FDIVS, "fdivs" },
{ FFREE, "ffree" },
{ FIADDL, "fiaddl" },
{ FIADDS, "fiadds" },
{ FICOM, "ficom" },
{ FICOMP, "ficomp" },
{ FIDIVL, "fidivl" },
{ FIDIVRL, "fidivrl" },
{ FIDIVRS, "fidivrs" },
{ FIDIVS, "fidivs" },
{ FILDL, "fildl" },
{ FILDQ, "fildq" },
{ FILDS, "filds" },
{ FIMULL, "fimull" },
{ FIMULS, "fimuls" },
{ FINCSTP, "fincstp" },
{ FINIT, "fninit" },
{ FISTL, "fistl" },
{ FISTP, "fistp" },
{ FISTS, "fists" },
{ FISUBL, "fisubl" },
{ FISUBRL, "fisubrl" },
{ FISUBRS, "fisubrs" },
{ FISUBS, "fisubs" },
{ FLD1, "fld1" },
{ FLDCW, "fldcw" },
{ FLDD, "fldl" },
{ FLDENV, "fldenv" },
{ FLDL2E, "fldl2e" },
{ FLDL2T, "fldl2t" },
{ FLDLG2, "fldlg2" },
{ FLDLN2, "fldln2" },
{ FLDPI, "fldpi" },
{ FLDS, "flds" },
{ FLDX, "fldt" },
{ FLDZ, "fldz" },
{ FMULD, "fmull" },
{ FMULP, "fmulp" },
{ FMULS, "fmuls" },
{ FNOP, "fnop" },
{ FPATAN, "fpatan" },
{ FPREM, "fprem" },
{ FPREM1, "fprem1" },
{ FPTAN, "fptan" },
{ FRNDINT, "frndint" },
{ FRSTOR, "frstor" },
{ FSAVE, "fnsave" },
{ FSCALE, "fscale" },
{ FSIN, "fsin" },
{ FSINCOS, "fsincos" },
{ FSQRT, "fsqrt" },
{ FSTCW, "fnstcw" },
{ FSTD, "fstl" },
{ FSTENV, "fnstenv" },
{ FSTP, "fstp" },
{ FSTPD, "fstpl" },
{ FSTPS, "fstps" },
{ FSTPX, "fstpt" },
{ FSTS, "fsts" },
{ FSTSW, "fstsw" },
{ FSUBD, "fsubl" },
{ FSUBP, "fsubp" },
{ FSUBPR, "fsubpr" },
{ FSUBRD, "fsubrl" },
{ FSUBRS, "fsubrs" },
{ FSUBS, "fsubs" },
{ FTST, "ftst" },
{ FUCOM, "fucom" },
{ FUCOMP, "fucomp" },
{ FUCOMPP, "fucompp" },
{ FXAM, "fxam" },
{ FXCH, "fxch" },
{ FXTRACT, "fxtract" },
{ FYL2X, "fyl2x" },
{ FYL2XP1, "fyl2xp1" },
{ HLT, "hlt" },
{ IDIV, "idiv%" },
{ IMUL, "imul%" },
{ IN, "in%" },
{ INC, "inc%" },
{ INS, "ins%" },
{ INT, "int" },
{ INTO, "into" },
{ INVD, "invd" },
{ INVLPG, "invlpg" },
{ IRET, "iret" },
{ IRETD, "iret" },
{ JA, "ja" },
{ JAE, "jae" },
{ JB, "jb" },
{ JBE, "jbe" },
{ JCXZ, "jcxz" },
{ JE, "je" },
{ JG, "jg" },
{ JGE, "jge" },
{ JL, "jl" },
{ JLE, "jle" },
{ JMP, "jmp" },
{ JMPF, "ljmp" },
{ JNE, "jne" },
{ JNO, "jno" },
{ JNP, "jnp" },
{ JNS, "jns" },
{ JO, "jo" },
{ JP, "jp" },
{ JS, "js" },
{ LAHF, "lahf" },
{ LAR, "lar" },
{ LDS, "lds" },
{ LEA, "lea%" },
{ LEAVE, "leave" },
{ LES, "les" },
{ LFS, "lfs" },
{ LGDT, "lgdt" },
{ LGS, "lgs" },
{ LIDT, "lidt" },
{ LLDT, "lldt" },
{ LMSW, "lmsw" },
{ LOCK, "lock" },
{ LODS, "lods%" },
{ LOOP, "loop" },
{ LOOPE, "loope" },
{ LOOPNE, "loopne" },
{ LSL, "lsl" },
{ LSS, "lss" },
{ LTR, "ltr" },
{ MOV, "mov%" },
{ MOVS, "movs%" },
{ MOVSX, "movswl" },
{ MOVSXB, "movsb%" },
{ MOVZX, "movzwl" },
{ MOVZXB, "movzb%" },
{ MUL, "mul%" },
{ NEG, "neg%" },
{ NOP, "nop" },
{ NOT, "not%" },
{ OR, "or%" },
{ OUT, "out%" },
{ OUTS, "outs%" },
{ POP, "pop%" },
{ POPA, "popa%" },
{ POPF, "popf%" },
{ PUSH, "push%" },
{ PUSHA, "pusha%" },
{ PUSHF, "pushf%" },
{ RCL, "rcl%" },
{ RCR, "rcr%" },
{ RET, "ret" },
{ RETF, "lret" },
{ ROL, "rol%" },
{ ROR, "ror%" },
{ SAHF, "sahf" },
{ SAL, "sal%" },
{ SAR, "sar%" },
{ SBB, "sbb%" },
{ SCAS, "scas%" },
{ SETA, "setab" },
{ SETAE, "setaeb" },
{ SETB, "setbb" },
{ SETBE, "setbeb" },
{ SETE, "seteb" },
{ SETG, "setgb" },
{ SETGE, "setgeb" },
{ SETL, "setlb" },
{ SETLE, "setleb" },
{ SETNE, "setneb" },
{ SETNO, "setnob" },
{ SETNP, "setnpb" },
{ SETNS, "setnsb" },
{ SETO, "setob" },
{ SETP, "setpb" },
{ SETS, "setsb" },
{ SGDT, "sgdt" },
{ SHL, "shl%" },
{ SHLD, "shld%" },
{ SHR, "shr%" },
{ SHRD, "shrd%" },
{ SIDT, "sidt" },
{ SLDT, "sldt" },
{ SMSW, "smsw" },
{ STC, "stc" },
{ STD, "std" },
{ STI, "sti" },
{ STOS, "stos%" },
{ STR, "str" },
{ SUB, "sub%" },
{ TEST, "test%" },
{ VERR, "verr" },
{ VERW, "verw" },
{ WAIT, "wait" },
{ WBINVD, "wbinvd" },
{ XADD, "xadd" },
{ XCHG, "xchg%" },
{ XLAT, "xlat" },
{ XOR, "xor%" },
};
static FILE *ef;
static long eline= 1;
static char *efile;
static char *orig_efile;
static char *opcode2name_tab[N_OPCODES];
static void gnu_putchar(int c)
/* LOOK, this programmer checks the return code of putc! What an idiot, noone
* does that!
*/
{
if (putc(c, ef) == EOF) fatal(orig_efile);
}
static void gnu_printf(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
if (vfprintf(ef, fmt, ap) == EOF) fatal(orig_efile);
va_end(ap);
}
void gnu_emit_init(char *file, const char *banner)
/* Prepare producing a GNU assembly file. */
{
mnemonic_t *mp;
if (file == nil) {
file= "stdout";
ef= stdout;
} else {
if ((ef= fopen(file, "w")) == nil) fatal(file);
}
orig_efile= file;
efile= file;
gnu_printf("/ %s", banner);
/* Initialize the opcode to mnemonic translation table. */
for (mp= mnemtab; mp < arraylimit(mnemtab); mp++) {
assert(opcode2name_tab[mp->opcode] == nil);
opcode2name_tab[mp->opcode]= mp->name;
}
}
#define opcode2name(op) (opcode2name_tab[op] + 0)
static void gnu_put_string(const char *s, size_t n)
/* Emit a string with weird characters quoted. */
{
while (n > 0) {
int c= *s;
if (c < ' ' || c > 0177) {
gnu_printf("\\%03o", c);
} else
if (c == '"' || c == '\\') {
gnu_printf("\\%c", c & 0xFF);
} else {
gnu_putchar(c);
}
s++;
n--;
}
}
static void gnu_put_expression(asm86_t *a, expression_t *e, int deref)
/* Send an expression, i.e. instruction operands, to the output file. Deref
* is true when the rewrite of "x" -> "#x" or "(x)" -> "x" may be made.
*/
{
assert(e != nil);
switch (e->operator) {
case ',':
if (is_pseudo(a->opcode)) {
/* Pseudo's are normal. */
gnu_put_expression(a, e->left, deref);
gnu_printf(", ");
gnu_put_expression(a, e->right, deref);
} else {
/* He who invented GNU assembly has seen one VAX too
* many, operands are given in the wrong order. This
* makes coding from an Intel databook a real delight.
* A good thing this program allows us to write the
* more normal ACK assembly.
*/
gnu_put_expression(a, e->right, deref);
gnu_printf(", ");
gnu_put_expression(a, e->left, deref);
}
break;
case 'O':
if (deref && a->optype == JUMP) gnu_putchar('*');
if (e->left != nil) gnu_put_expression(a, e->left, 0);
gnu_putchar('(');
if (e->middle != nil) gnu_put_expression(a, e->middle, 0);
if (e->right != nil) {
gnu_putchar(',');
gnu_put_expression(a, e->right, 0);
}
gnu_putchar(')');
break;
case '(':
if (!deref) gnu_putchar('(');
if (deref && a->optype == JUMP) gnu_putchar('*');
gnu_put_expression(a, e->middle, 0);
if (!deref) gnu_putchar(')');
break;
case 'B':
gnu_printf("%%%s", e->name);
break;
case '1':
case '2':
case '4':
case '8':
gnu_printf("%%%s,%c", e->name, e->operator);
break;
case '+':
case '-':
case '~':
if (e->middle != nil) {
if (deref && a->optype >= BYTE) gnu_putchar('$');
gnu_putchar(e->operator);
gnu_put_expression(a, e->middle, 0);
break;
}
/*FALL THROUGH*/
case '*':
case '/':
case '%':
case '&':
case '|':
case '^':
case S_LEFTSHIFT:
case S_RIGHTSHIFT:
if (deref && a->optype >= BYTE) gnu_putchar('$');
gnu_put_expression(a, e->left, 0);
if (e->operator == S_LEFTSHIFT) {
gnu_printf("<<");
} else
if (e->operator == S_RIGHTSHIFT) {
gnu_printf(">>");
} else {
gnu_putchar(e->operator);
}
gnu_put_expression(a, e->right, 0);
break;
case '[':
if (deref && a->optype >= BYTE) gnu_putchar('$');
gnu_putchar('(');
gnu_put_expression(a, e->middle, 0);
gnu_putchar(')');
break;
case 'W':
if (isregister(e->name)) {
if (a->optype == JUMP) gnu_putchar('*');
gnu_printf("%%%s", e->name);
} else {
if (deref && a->optype >= BYTE) gnu_putchar('$');
gnu_printf("%s", e->name);
}
break;
case 'S':
gnu_putchar('"');
gnu_put_string(e->name, e->len);
gnu_putchar('"');
break;
default:
fprintf(stderr,
"asmconv: internal error, unknown expression operator '%d'\n",
e->operator);
exit(EXIT_FAILURE);
}
}
void gnu_emit_instruction(asm86_t *a)
/* Output one instruction and its operands. */
{
int same= 0;
char *p;
if (a == nil) {
/* Last call */
gnu_putchar('\n');
return;
}
if (use16()) {
fprintf(stderr,
"asmconv: the GNU assembler can't translate 8086 code\n");
exit(EXIT_FAILURE);
}
/* Make sure the line number of the line to be emitted is ok. */
if ((a->file != efile && strcmp(a->file, efile) != 0)
|| a->line < eline || a->line > eline+10) {
gnu_putchar('\n');
gnu_printf("# %ld \"%s\"\n", a->line, a->file);
efile= a->file;
eline= a->line;
} else {
if (a->line == eline) {
gnu_printf("; ");
same= 1;
}
while (eline < a->line) {
gnu_putchar('\n');
eline++;
}
}
if (a->opcode == DOT_END) {
/* Stop translating after .sect .end. */
exit(0);
} else
if (a->opcode == DOT_LABEL) {
assert(a->args->operator == ':');
gnu_printf("%s:", a->args->name);
} else
if (a->opcode == DOT_EQU) {
assert(a->args->operator == '=');
gnu_printf("\t%s = ", a->args->name);
gnu_put_expression(a, a->args->middle, 0);
} else
if (a->opcode == DOT_ALIGN) {
/* GNU .align thinks in powers of two. */
unsigned long n;
unsigned s;
assert(a->args->operator == 'W' && isanumber(a->args->name));
n= strtoul(a->args->name, nil, 0);
for (s= 0; s <= 16 && (1 << s) < n; s++) {}
gnu_printf(".align\t%u", s);
} else
if ((p= opcode2name(a->opcode)) != nil) {
if (!is_pseudo(a->opcode) && !same) gnu_putchar('\t');
switch (a->rep) {
case ONCE: break;
case REP: gnu_printf("rep; "); break;
case REPE: gnu_printf("repe; "); break;
case REPNE: gnu_printf("repne; "); break;
default: assert(0);
}
switch (a->seg) {
/* Kludge to avoid knowing where to put the "%es:" */
case DEFSEG: break;
case CSEG: gnu_printf(".byte 0x2e; "); break;
case DSEG: gnu_printf(".byte 0x3e; "); break;
case ESEG: gnu_printf(".byte 0x26; "); break;
case FSEG: gnu_printf(".byte 0x64; "); break;
case GSEG: gnu_printf(".byte 0x65; "); break;
case SSEG: gnu_printf(".byte 0x36; "); break;
default: assert(0);
}
/* Exceptions, exceptions... */
if (a->opcode == CBW) {
if (!(a->oaz & OPZ)) p= "cwtl";
a->oaz&= ~OPZ;
}
if (a->opcode == CWD) {
if (!(a->oaz & OPZ)) p= "cltd";
a->oaz&= ~OPZ;
}
if (a->opcode == RET || a->opcode == RETF) {
/* Argument of RET needs a '$'. */
a->optype= WORD;
}
if (a->opcode == MUL && a->args != nil
&& a->args->operator == ',') {
/* Two operand MUL is an IMUL? */
p="imul%";
}
/* GAS doesn't understand the interesting combinations. */
if (a->oaz & ADZ) gnu_printf(".byte 0x67; ");
if (a->oaz & OPZ && strchr(p, '%') == nil)
gnu_printf(".byte 0x66; ");
/* Unsupported instructions that Minix code needs. */
if (a->opcode == JMPF && a->args != nil
&& a->args->operator == ',') {
/* JMPF seg:off. */
gnu_printf(".byte 0xEA; .long ");
gnu_put_expression(a, a->args->right, 0);
gnu_printf("; .short ");
gnu_put_expression(a, a->args->left, 0);
return;
}
if (a->opcode == JMPF && a->args != nil
&& a->args->operator == 'O'
&& a->args->left != nil
&& a->args->right == nil
&& a->args->middle != nil
&& a->args->middle->operator == 'B'
&& strcmp(a->args->middle->name, "esp") == 0
) {
/* JMPF offset(ESP). */
gnu_printf(".byte 0xFF,0x6C,0x24,");
gnu_put_expression(a, a->args->left, 0);
return;
}
if (a->opcode == MOV && a->args != nil
&& a->args->operator == ','
&& a->args->left != nil
&& a->args->left->operator == 'W'
&& (strcmp(a->args->left->name, "ds") == 0
|| strcmp(a->args->left->name, "es") == 0)
&& a->args->right->operator == 'O'
&& a->args->right->left != nil
&& a->args->right->right == nil
&& a->args->right->middle != nil
&& a->args->right->middle->operator == 'B'
&& strcmp(a->args->right->middle->name, "esp") == 0
) {
/* MOV DS, offset(ESP); MOV ES, offset(ESP) */
gnu_printf(".byte 0x8E,0x%02X,0x24,",
a->args->left->name[0] == 'd' ? 0x5C : 0x44);
gnu_put_expression(a, a->args->right->left, 0);
return;
}
if (a->opcode == MOV && a->args != nil
&& a->args->operator == ','
&& a->args->left != nil
&& a->args->left->operator == 'W'
&& (strcmp(a->args->left->name, "ds") == 0
|| strcmp(a->args->left->name, "es") == 0)
&& a->args->right->operator == '('
&& a->args->right->middle != nil
) {
/* MOV DS, (memory); MOV ES, (memory) */
gnu_printf(".byte 0x8E,0x%02X; .long ",
a->args->left->name[0] == 'd' ? 0x1D : 0x05);
gnu_put_expression(a, a->args->right->middle, 0);
return;
}
while (*p != 0) {
if (*p == '%') {
if (a->optype == BYTE) {
gnu_putchar('b');
} else
if (a->optype == WORD) {
gnu_putchar((a->oaz & OPZ) ? 'w' : 'l');
} else {
assert(0);
}
} else {
gnu_putchar(*p);
}
p++;
}
if (a->args != nil) {
static char *aregs[] = { "al", "ax", "eax" };
gnu_putchar('\t');
switch (a->opcode) {
case IN:
gnu_put_expression(a, a->args, 1);
gnu_printf(", %%%s", aregs[a->optype - BYTE]);
break;
case OUT:
gnu_printf("%%%s, ", aregs[a->optype - BYTE]);
gnu_put_expression(a, a->args, 1);
break;
default:
gnu_put_expression(a, a->args, 1);
}
}
if (a->opcode == DOT_USE16) set_use16();
if (a->opcode == DOT_USE32) set_use32();
} else {
fprintf(stderr,
"asmconv: internal error, unknown opcode '%d'\n",
a->opcode);
exit(EXIT_FAILURE);
}
}

View File

@ -1,25 +0,0 @@
/* languages.h - functions that parse or emit assembly
* Author: Kees J. Bot
* 27 Dec 1993
*/
void ack_parse_init(char *file);
asm86_t *ack_get_instruction(void);
void ncc_parse_init(char *file);
asm86_t *ncc_get_instruction(void);
void gnu_parse_init(char *file);
asm86_t *gnu_get_instruction(void);
void bas_parse_init(char *file);
asm86_t *bas_get_instruction(void);
void ack_emit_init(char *file, const char *banner);
void ack_emit_instruction(asm86_t *instr);
void ncc_emit_init(char *file, const char *banner);
void ncc_emit_instruction(asm86_t *instr);
void gnu_emit_init(char *file, const char *banner);
void gnu_emit_instruction(asm86_t *instr);

View File

@ -1,911 +0,0 @@
/* parse_ack.c - parse ACK assembly Author: Kees J. Bot
* parse NCC assembly 18 Dec 1993
*/
#define nil 0
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "asmconv.h"
#include "token.h"
#include "asm86.h"
#include "languages.h"
typedef struct mnemonic { /* ACK as86 mnemonics translation table. */
char *name;
opcode_t opcode;
optype_t optype;
} mnemonic_t;
static mnemonic_t mnemtab[] = { /* This array is sorted. */
{ ".align", DOT_ALIGN, PSEUDO },
{ ".ascii", DOT_ASCII, PSEUDO },
{ ".asciz", DOT_ASCIZ, PSEUDO },
{ ".assert", DOT_ASSERT, PSEUDO },
{ ".base", DOT_BASE, PSEUDO },
{ ".bss", DOT_BSS, PSEUDO },
{ ".comm", DOT_LCOMM, PSEUDO },
{ ".data", DOT_DATA, PSEUDO },
{ ".data1", DOT_DATA1, PSEUDO },
{ ".data2", DOT_DATA2, PSEUDO },
{ ".data4", DOT_DATA4, PSEUDO },
{ ".define", DOT_DEFINE, PSEUDO },
{ ".end", DOT_END, PSEUDO },
{ ".extern", DOT_EXTERN, PSEUDO },
{ ".file", DOT_FILE, PSEUDO },
{ ".line", DOT_LINE, PSEUDO },
{ ".list", DOT_LIST, PSEUDO },
{ ".nolist", DOT_NOLIST, PSEUDO },
{ ".rom", DOT_ROM, PSEUDO },
{ ".space", DOT_SPACE, PSEUDO },
{ ".symb", DOT_SYMB, PSEUDO },
{ ".text", DOT_TEXT, PSEUDO },
{ ".use16", DOT_USE16, PSEUDO },
{ ".use32", DOT_USE32, PSEUDO },
{ "aaa", AAA, WORD },
{ "aad", AAD, WORD },
{ "aam", AAM, WORD },
{ "aas", AAS, WORD },
{ "adc", ADC, WORD },
{ "adcb", ADC, BYTE },
{ "add", ADD, WORD },
{ "addb", ADD, BYTE },
{ "and", AND, WORD },
{ "andb", AND, BYTE },
{ "arpl", ARPL, WORD },
{ "bound", BOUND, WORD },
{ "bsf", BSF, WORD },
{ "bsr", BSR, WORD },
{ "bswap", BSWAP, WORD },
{ "bt", BT, WORD },
{ "btc", BTC, WORD },
{ "btr", BTR, WORD },
{ "bts", BTS, WORD },
{ "call", CALL, JUMP },
{ "callf", CALLF, JUMP },
{ "cbw", CBW, WORD },
{ "cdq", CWD, WORD },
{ "clc", CLC, WORD },
{ "cld", CLD, WORD },
{ "cli", CLI, WORD },
{ "clts", CLTS, WORD },
{ "cmc", CMC, WORD },
{ "cmp", CMP, WORD },
{ "cmpb", CMP, BYTE },
{ "cmps", CMPS, WORD },
{ "cmpsb", CMPS, BYTE },
{ "cmpxchg", CMPXCHG, WORD },
{ "cwd", CWD, WORD },
{ "cwde", CBW, WORD },
{ "daa", DAA, WORD },
{ "das", DAS, WORD },
{ "dec", DEC, WORD },
{ "decb", DEC, BYTE },
{ "div", DIV, WORD },
{ "divb", DIV, BYTE },
{ "enter", ENTER, WORD },
{ "f2xm1", F2XM1, WORD },
{ "fabs", FABS, WORD },
{ "fadd", FADD, WORD },
{ "faddd", FADDD, WORD },
{ "faddp", FADDP, WORD },
{ "fadds", FADDS, WORD },
{ "fbld", FBLD, WORD },
{ "fbstp", FBSTP, WORD },
{ "fchs", FCHS, WORD },
{ "fclex", FCLEX, WORD },
{ "fcomd", FCOMD, WORD },
{ "fcompd", FCOMPD, WORD },
{ "fcompp", FCOMPP, WORD },
{ "fcomps", FCOMPS, WORD },
{ "fcoms", FCOMS, WORD },
{ "fcos", FCOS, WORD },
{ "fdecstp", FDECSTP, WORD },
{ "fdivd", FDIVD, WORD },
{ "fdivp", FDIVP, WORD },
{ "fdivrd", FDIVRD, WORD },
{ "fdivrp", FDIVRP, WORD },
{ "fdivrs", FDIVRS, WORD },
{ "fdivs", FDIVS, WORD },
{ "ffree", FFREE, WORD },
{ "fiaddl", FIADDL, WORD },
{ "fiadds", FIADDS, WORD },
{ "ficom", FICOM, WORD },
{ "ficomp", FICOMP, WORD },
{ "fidivl", FIDIVL, WORD },
{ "fidivrl", FIDIVRL, WORD },
{ "fidivrs", FIDIVRS, WORD },
{ "fidivs", FIDIVS, WORD },
{ "fildl", FILDL, WORD },
{ "fildq", FILDQ, WORD },
{ "filds", FILDS, WORD },
{ "fimull", FIMULL, WORD },
{ "fimuls", FIMULS, WORD },
{ "fincstp", FINCSTP, WORD },
{ "finit", FINIT, WORD },
{ "fistl", FISTL, WORD },
{ "fistp", FISTP, WORD },
{ "fists", FISTS, WORD },
{ "fisubl", FISUBL, WORD },
{ "fisubrl", FISUBRL, WORD },
{ "fisubrs", FISUBRS, WORD },
{ "fisubs", FISUBS, WORD },
{ "fld1", FLD1, WORD },
{ "fldcw", FLDCW, WORD },
{ "fldd", FLDD, WORD },
{ "fldenv", FLDENV, WORD },
{ "fldl2e", FLDL2E, WORD },
{ "fldl2t", FLDL2T, WORD },
{ "fldlg2", FLDLG2, WORD },
{ "fldln2", FLDLN2, WORD },
{ "fldpi", FLDPI, WORD },
{ "flds", FLDS, WORD },
{ "fldx", FLDX, WORD },
{ "fldz", FLDZ, WORD },
{ "fmuld", FMULD, WORD },
{ "fmulp", FMULP, WORD },
{ "fmuls", FMULS, WORD },
{ "fnop", FNOP, WORD },
{ "fpatan", FPATAN, WORD },
{ "fprem", FPREM, WORD },
{ "fprem1", FPREM1, WORD },
{ "fptan", FPTAN, WORD },
{ "frndint", FRNDINT, WORD },
{ "frstor", FRSTOR, WORD },
{ "fsave", FSAVE, WORD },
{ "fscale", FSCALE, WORD },
{ "fsin", FSIN, WORD },
{ "fsincos", FSINCOS, WORD },
{ "fsqrt", FSQRT, WORD },
{ "fstcw", FSTCW, WORD },
{ "fstd", FSTD, WORD },
{ "fstenv", FSTENV, WORD },
{ "fstp", FSTP, WORD },
{ "fstpd", FSTPD, WORD },
{ "fstps", FSTPS, WORD },
{ "fstpx", FSTPX, WORD },
{ "fsts", FSTS, WORD },
{ "fstsw", FSTSW, WORD },
{ "fsubd", FSUBD, WORD },
{ "fsubp", FSUBP, WORD },
{ "fsubpr", FSUBPR, WORD },
{ "fsubrd", FSUBRD, WORD },
{ "fsubrs", FSUBRS, WORD },
{ "fsubs", FSUBS, WORD },
{ "ftst", FTST, WORD },
{ "fucom", FUCOM, WORD },
{ "fucomp", FUCOMP, WORD },
{ "fucompp", FUCOMPP, WORD },
{ "fxam", FXAM, WORD },
{ "fxch", FXCH, WORD },
{ "fxtract", FXTRACT, WORD },
{ "fyl2x", FYL2X, WORD },
{ "fyl2xp1", FYL2XP1, WORD },
{ "hlt", HLT, WORD },
{ "idiv", IDIV, WORD },
{ "idivb", IDIV, BYTE },
{ "imul", IMUL, WORD },
{ "imulb", IMUL, BYTE },
{ "in", IN, WORD },
{ "inb", IN, BYTE },
{ "inc", INC, WORD },
{ "incb", INC, BYTE },
{ "ins", INS, WORD },
{ "insb", INS, BYTE },
{ "int", INT, WORD },
{ "into", INTO, JUMP },
{ "invd", INVD, WORD },
{ "invlpg", INVLPG, WORD },
{ "iret", IRET, JUMP },
{ "iretd", IRETD, JUMP },
{ "ja", JA, JUMP },
{ "jae", JAE, JUMP },
{ "jb", JB, JUMP },
{ "jbe", JBE, JUMP },
{ "jc", JB, JUMP },
{ "jcxz", JCXZ, JUMP },
{ "je", JE, JUMP },
{ "jecxz", JCXZ, JUMP },
{ "jg", JG, JUMP },
{ "jge", JGE, JUMP },
{ "jl", JL, JUMP },
{ "jle", JLE, JUMP },
{ "jmp", JMP, JUMP },
{ "jmpf", JMPF, JUMP },
{ "jna", JBE, JUMP },
{ "jnae", JB, JUMP },
{ "jnb", JAE, JUMP },
{ "jnbe", JA, JUMP },
{ "jnc", JAE, JUMP },
{ "jne", JNE, JUMP },
{ "jng", JLE, JUMP },
{ "jnge", JL, JUMP },
{ "jnl", JGE, JUMP },
{ "jnle", JG, JUMP },
{ "jno", JNO, JUMP },
{ "jnp", JNP, JUMP },
{ "jns", JNS, JUMP },
{ "jnz", JNE, JUMP },
{ "jo", JO, JUMP },
{ "jp", JP, JUMP },
{ "js", JS, JUMP },
{ "jz", JE, JUMP },
{ "lahf", LAHF, WORD },
{ "lar", LAR, WORD },
{ "lds", LDS, WORD },
{ "lea", LEA, WORD },
{ "leave", LEAVE, WORD },
{ "les", LES, WORD },
{ "lfs", LFS, WORD },
{ "lgdt", LGDT, WORD },
{ "lgs", LGS, WORD },
{ "lidt", LIDT, WORD },
{ "lldt", LLDT, WORD },
{ "lmsw", LMSW, WORD },
{ "lock", LOCK, WORD },
{ "lods", LODS, WORD },
{ "lodsb", LODS, BYTE },
{ "loop", LOOP, JUMP },
{ "loope", LOOPE, JUMP },
{ "loopne", LOOPNE, JUMP },
{ "loopnz", LOOPNE, JUMP },
{ "loopz", LOOPE, JUMP },
{ "lsl", LSL, WORD },
{ "lss", LSS, WORD },
{ "ltr", LTR, WORD },
{ "mov", MOV, WORD },
{ "movb", MOV, BYTE },
{ "movs", MOVS, WORD },
{ "movsb", MOVS, BYTE },
{ "movsx", MOVSX, WORD },
{ "movsxb", MOVSXB, WORD },
{ "movzx", MOVZX, WORD },
{ "movzxb", MOVZXB, WORD },
{ "mul", MUL, WORD },
{ "mulb", MUL, BYTE },
{ "neg", NEG, WORD },
{ "negb", NEG, BYTE },
{ "nop", NOP, WORD },
{ "not", NOT, WORD },
{ "notb", NOT, BYTE },
{ "or", OR, WORD },
{ "orb", OR, BYTE },
{ "out", OUT, WORD },
{ "outb", OUT, BYTE },
{ "outs", OUTS, WORD },
{ "outsb", OUTS, BYTE },
{ "pop", POP, WORD },
{ "popa", POPA, WORD },
{ "popad", POPA, WORD },
{ "popf", POPF, WORD },
{ "push", PUSH, WORD },
{ "pusha", PUSHA, WORD },
{ "pushad", PUSHA, WORD },
{ "pushf", PUSHF, WORD },
{ "rcl", RCL, WORD },
{ "rclb", RCL, BYTE },
{ "rcr", RCR, WORD },
{ "rcrb", RCR, BYTE },
{ "ret", RET, JUMP },
{ "retf", RETF, JUMP },
{ "rol", ROL, WORD },
{ "rolb", ROL, BYTE },
{ "ror", ROR, WORD },
{ "rorb", ROR, BYTE },
{ "sahf", SAHF, WORD },
{ "sal", SAL, WORD },
{ "salb", SAL, BYTE },
{ "sar", SAR, WORD },
{ "sarb", SAR, BYTE },
{ "sbb", SBB, WORD },
{ "sbbb", SBB, BYTE },
{ "scas", SCAS, WORD },
{ "scasb", SCAS, BYTE },
{ "seta", SETA, BYTE },
{ "setae", SETAE, BYTE },
{ "setb", SETB, BYTE },
{ "setbe", SETBE, BYTE },
{ "sete", SETE, BYTE },
{ "setg", SETG, BYTE },
{ "setge", SETGE, BYTE },
{ "setl", SETL, BYTE },
{ "setna", SETBE, BYTE },
{ "setnae", SETB, BYTE },
{ "setnb", SETAE, BYTE },
{ "setnbe", SETA, BYTE },
{ "setne", SETNE, BYTE },
{ "setng", SETLE, BYTE },
{ "setnge", SETL, BYTE },
{ "setnl", SETGE, BYTE },
{ "setnle", SETG, BYTE },
{ "setno", SETNO, BYTE },
{ "setnp", SETNP, BYTE },
{ "setns", SETNS, BYTE },
{ "seto", SETO, BYTE },
{ "setp", SETP, BYTE },
{ "sets", SETS, BYTE },
{ "setz", SETE, BYTE },
{ "sgdt", SGDT, WORD },
{ "shl", SHL, WORD },
{ "shlb", SHL, BYTE },
{ "shld", SHLD, WORD },
{ "shr", SHR, WORD },
{ "shrb", SHR, BYTE },
{ "shrd", SHRD, WORD },
{ "sidt", SIDT, WORD },
{ "sldt", SLDT, WORD },
{ "smsw", SMSW, WORD },
{ "stc", STC, WORD },
{ "std", STD, WORD },
{ "sti", STI, WORD },
{ "stos", STOS, WORD },
{ "stosb", STOS, BYTE },
{ "str", STR, WORD },
{ "sub", SUB, WORD },
{ "subb", SUB, BYTE },
{ "test", TEST, WORD },
{ "testb", TEST, BYTE },
{ "verr", VERR, WORD },
{ "verw", VERW, WORD },
{ "wait", WAIT, WORD },
{ "wbinvd", WBINVD, WORD },
{ "xadd", XADD, WORD },
{ "xchg", XCHG, WORD },
{ "xchgb", XCHG, BYTE },
{ "xlat", XLAT, WORD },
{ "xor", XOR, WORD },
{ "xorb", XOR, BYTE },
};
static enum dialect { ACK, NCC } dialect= ACK;
void ack_parse_init(char *file)
/* Prepare parsing of an ACK assembly file. */
{
tok_init(file, '!');
}
void ncc_parse_init(char *file)
/* Prepare parsing of an ACK Xenix assembly file. See emit_ack.c for comments
* on this fine assembly dialect.
*/
{
dialect= NCC;
ack_parse_init(file);
}
static void zap(void)
/* An error, zap the rest of the line. */
{
token_t *t;
while ((t= get_token(0))->type != T_EOF && t->symbol != ';')
skip_token(1);
}
static mnemonic_t *search_mnem(char *name)
/* Binary search for a mnemonic. (That's why the table is sorted.) */
{
int low, mid, high;
int cmp;
mnemonic_t *m;
low= 0;
high= arraysize(mnemtab)-1;
while (low <= high) {
mid= (low + high) / 2;
m= &mnemtab[mid];
if ((cmp= strcmp(name, m->name)) == 0) return m;
if (cmp < 0) high= mid-1; else low= mid+1;
}
return nil;
}
static expression_t *ack_get_C_expression(int *pn)
/* Read a "C-like" expression. Note that we don't worry about precedence,
* the expression is printed later like it is read. If the target language
* does not have all the operators (like ~) then this has to be repaired by
* changing the source file. (No problem, you still have one source file
* to maintain, not two.)
*/
{
expression_t *e, *a1, *a2;
token_t *t;
if ((t= get_token(*pn))->symbol == '[') {
/* [ expr ]: grouping. */
(*pn)++;
if ((a1= ack_get_C_expression(pn)) == nil) return nil;
if (get_token(*pn)->symbol != ']') {
parse_err(1, t, "missing ]\n");
del_expr(a1);
return nil;
}
(*pn)++;
e= new_expr();
e->operator= '[';
e->middle= a1;
} else
if (t->type == T_WORD || t->type == T_STRING) {
/* Label, number, or string. */
e= new_expr();
e->operator= t->type == T_WORD ? 'W' : 'S';
e->name= allocate(nil, (t->len+1) * sizeof(e->name[0]));
memcpy(e->name, t->name, t->len+1);
e->len= t->len;
(*pn)++;
} else
if (t->symbol == '+' || t->symbol == '-' || t->symbol == '~') {
/* Unary operator. */
(*pn)++;
if ((a1= ack_get_C_expression(pn)) == nil) return nil;
e= new_expr();
e->operator= t->symbol;
e->middle= a1;
} else {
parse_err(1, t, "expression syntax error\n");
return nil;
}
switch ((t= get_token(*pn))->symbol) {
case '+':
case '-':
case '*':
case '/':
case '%':
case '&':
case '|':
case '^':
case S_LEFTSHIFT:
case S_RIGHTSHIFT:
(*pn)++;
a1= e;
if ((a2= ack_get_C_expression(pn)) == nil) {
del_expr(a1);
return nil;
}
e= new_expr();
e->operator= t->symbol;
e->left= a1;
e->right= a2;
}
return e;
}
static expression_t *ack_get_operand(int *pn, int deref)
/* Get something like: (memory), offset(base)(index*scale), or simpler. */
{
expression_t *e, *offset, *base, *index;
token_t *t;
int c;
/* Is it (memory)? */
if (get_token(*pn)->symbol == '('
&& ((t= get_token(*pn + 1))->type != T_WORD
|| !isregister(t->name))
) {
/* A memory dereference. */
(*pn)++;
if ((offset= ack_get_C_expression(pn)) == nil) return nil;
if (get_token(*pn)->symbol != ')') {
parse_err(1, t, "operand syntax error\n");
del_expr(offset);
return nil;
}
(*pn)++;
e= new_expr();
e->operator= '(';
e->middle= offset;
return e;
}
/* #constant? */
if (dialect == NCC && deref
&& ((c= get_token(*pn)->symbol) == '#' || c == '*')) {
/* NCC: mov ax,#constant -> ACK: mov ax,constant */
(*pn)++;
return ack_get_C_expression(pn);
}
/* @address? */
if (dialect == NCC && get_token(*pn)->symbol == '@') {
/* NCC: jmp @address -> ACK: jmp (address) */
(*pn)++;
if ((offset= ack_get_operand(pn, deref)) == nil) return nil;
e= new_expr();
e->operator= '(';
e->middle= offset;
return e;
}
/* Offset? */
if (get_token(*pn)->symbol != '(') {
/* There is an offset. */
if ((offset= ack_get_C_expression(pn)) == nil) return nil;
} else {
/* No offset. */
offset= nil;
}
/* (base)? */
if (get_token(*pn)->symbol == '('
&& (t= get_token(*pn + 1))->type == T_WORD
&& isregister(t->name)
&& get_token(*pn + 2)->symbol == ')'
) {
/* A base register expression. */
base= new_expr();
base->operator= 'B';
base->name= copystr(t->name);
(*pn)+= 3;
} else {
/* No base register expression. */
base= nil;
}
/* (index*scale)? */
if (get_token(*pn)->symbol == '(') {
/* An index most likely. */
token_t *m= nil;
if (!( /* This must be true: */
(t= get_token(*pn + 1))->type == T_WORD
&& isregister(t->name)
&& (get_token(*pn + 2)->symbol == ')' || (
get_token(*pn + 2)->symbol == '*'
&& (m= get_token(*pn + 3))->type == T_WORD
&& strchr("1248", m->name[0]) != nil
&& m->name[1] == 0
&& get_token(*pn + 4)->symbol == ')'
))
)) {
/* Alas it isn't */
parse_err(1, t, "operand syntax error\n");
del_expr(offset);
del_expr(base);
return nil;
}
/* Found an index. */
index= new_expr();
index->operator= m == nil ? '1' : m->name[0];
index->name= copystr(t->name);
(*pn)+= (m == nil ? 3 : 5);
} else {
/* No index. */
index= nil;
}
if (dialect == NCC && deref && base == nil && index == nil
&& !(offset != nil && offset->operator == 'W'
&& isregister(offset->name))
) {
/* NCC: mov ax,thing -> ACK mov ax,(thing) */
e= new_expr();
e->operator= '(';
e->middle= offset;
return e;
}
if (base == nil && index == nil) {
/* Return a lone offset as is. */
e= offset;
} else {
e= new_expr();
e->operator= 'O';
e->left= offset;
e->middle= base;
e->right= index;
}
return e;
}
static expression_t *ack_get_oplist(int *pn, int deref)
/* Get a comma (or colon for jmpf and callf) separated list of instruction
* operands.
*/
{
expression_t *e, *o1, *o2;
token_t *t;
if ((e= ack_get_operand(pn, deref)) == nil) return nil;
if ((t= get_token(*pn))->symbol == ',' || t->symbol == ':') {
o1= e;
(*pn)++;
if ((o2= ack_get_oplist(pn, deref)) == nil) {
del_expr(o1);
return nil;
}
e= new_expr();
e->operator= ',';
e->left= o1;
e->right= o2;
}
return e;
}
static asm86_t *ack_get_statement(void)
/* Get a pseudo op or machine instruction with arguments. */
{
token_t *t= get_token(0);
asm86_t *a;
mnemonic_t *m;
int n;
int prefix_seen;
int oaz_prefix;
int deref;
assert(t->type == T_WORD);
if (strcmp(t->name, ".sect") == 0) {
/* .sect .text etc. Accept only four segment names. */
skip_token(1);
t= get_token(0);
if (t->type != T_WORD || (
strcmp(t->name, ".text") != 0
&& strcmp(t->name, ".rom") != 0
&& strcmp(t->name, ".data") != 0
&& strcmp(t->name, ".bss") != 0
&& strcmp(t->name, ".end") != 0
)) {
parse_err(1, t, "weird section name to .sect\n");
return nil;
}
}
a= new_asm86();
/* Process instruction prefixes. */
oaz_prefix= 0;
for (prefix_seen= 0;; prefix_seen= 1) {
if (strcmp(t->name, "o16") == 0) {
if (use16()) {
parse_err(1, t, "o16 in an 8086 section\n");
}
oaz_prefix|= OPZ;
} else
if (strcmp(t->name, "o32") == 0) {
if (use32()) {
parse_err(1, t, "o32 in an 80386 section\n");
}
oaz_prefix|= OPZ;
} else
if (strcmp(t->name, "a16") == 0) {
if (use16()) {
parse_err(1, t, "a16 in an 8086 section\n");
}
oaz_prefix|= ADZ;
} else
if (strcmp(t->name, "a32") == 0) {
if (use32()) {
parse_err(1, t, "a32 in an 80386 section\n");
}
oaz_prefix|= ADZ;
} else
if (strcmp(t->name, "rep") == 0
|| strcmp(t->name, "repe") == 0
|| strcmp(t->name, "repne") == 0
|| strcmp(t->name, "repz") == 0
|| strcmp(t->name, "repnz") == 0
) {
if (a->rep != ONCE) {
parse_err(1, t,
"can't have more than one rep\n");
}
switch (t->name[3]) {
case 0: a->rep= REP; break;
case 'e':
case 'z': a->rep= REPE; break;
case 'n': a->rep= REPNE; break;
}
} else
if (strchr("cdefgs", t->name[0]) != nil
&& strcmp(t->name+1, "seg") == 0) {
if (a->seg != DEFSEG) {
parse_err(1, t,
"can't have more than one segment prefix\n");
}
switch (t->name[0]) {
case 'c': a->seg= CSEG; break;
case 'd': a->seg= DSEG; break;
case 'e': a->seg= ESEG; break;
case 'f': a->seg= FSEG; break;
case 'g': a->seg= GSEG; break;
case 's': a->seg= SSEG; break;
}
} else
if (!prefix_seen) {
/* No prefix here, get out! */
break;
} else {
/* No more prefixes, next must be an instruction. */
if (t->type != T_WORD
|| (m= search_mnem(t->name)) == nil
|| m->optype == PSEUDO
) {
parse_err(1, t,
"machine instruction expected after instruction prefix\n");
del_asm86(a);
return nil;
}
if (oaz_prefix != 0 && m->optype != JUMP
&& m->optype != WORD) {
parse_err(1, t,
"'%s' can't have an operand size prefix\n", m->name);
}
break;
}
/* Skip the prefix and extra newlines. */
do {
skip_token(1);
} while ((t= get_token(0))->symbol == ';');
}
/* All the readahead being done upsets the line counter. */
a->line= t->line;
/* Read a machine instruction or pseudo op. */
if ((m= search_mnem(t->name)) == nil) {
parse_err(1, t, "unknown instruction '%s'\n", t->name);
del_asm86(a);
return nil;
}
a->opcode= m->opcode;
a->optype= m->optype;
a->oaz= oaz_prefix;
switch (a->opcode) {
case IN:
case OUT:
case INT:
deref= 0;
break;
default:
deref= (a->optype >= BYTE);
}
n= 1;
if (get_token(1)->symbol != ';'
&& (a->args= ack_get_oplist(&n, deref)) == nil) {
del_asm86(a);
return nil;
}
if (get_token(n)->symbol != ';') {
parse_err(1, t, "garbage at end of instruction\n");
del_asm86(a);
return nil;
}
switch (a->opcode) {
case DOT_ALIGN:
/* Restrict .align to have a single numeric argument, some
* assemblers think of the argument as a power of two, so
* we need to be able to change the value.
*/
if (a->args == nil || a->args->operator != 'W'
|| !isanumber(a->args->name)) {
parse_err(1, t,
".align is restricted to one numeric argument\n");
del_asm86(a);
return nil;
}
break;
case JMPF:
case CALLF:
/* NCC jmpf off,seg -> ACK jmpf seg:off */
if (dialect == NCC && a->args != nil
&& a->args->operator == ',') {
expression_t *t;
t= a->args->left;
a->args->left= a->args->right;
a->args->right= t;
break;
}
/*FALL THROUGH*/
case JMP:
case CALL:
/* NCC jmp @(reg) -> ACK jmp (reg) */
if (dialect == NCC && a->args != nil && (
(a->args->operator == '('
&& a->args->middle != nil
&& a->args->middle->operator == 'O')
|| (a->args->operator == 'O'
&& a->args->left == nil
&& a->args->middle != nil
&& a->args->right == nil)
)) {
expression_t *t;
t= a->args;
a->args= a->args->middle;
t->middle= nil;
del_expr(t);
if (a->args->operator == 'B') a->args->operator= 'W';
}
break;
default:;
}
skip_token(n+1);
return a;
}
asm86_t *ack_get_instruction(void)
{
asm86_t *a= nil;
expression_t *e;
token_t *t;
while ((t= get_token(0))->symbol == ';')
skip_token(1);
if (t->type == T_EOF) return nil;
if (t->symbol == '#') {
/* Preprocessor line and file change. */
if ((t= get_token(1))->type != T_WORD || !isanumber(t->name)
|| get_token(2)->type != T_STRING
) {
parse_err(1, t, "file not preprocessed?\n");
zap();
} else {
set_file(get_token(2)->name,
strtol(get_token(1)->name, nil, 0) - 1);
/* GNU CPP adds extra cruft, simply zap the line. */
zap();
}
a= ack_get_instruction();
} else
if (t->type == T_WORD && get_token(1)->symbol == ':') {
/* A label definition. */
a= new_asm86();
a->line= t->line;
a->opcode= DOT_LABEL;
a->optype= PSEUDO;
a->args= e= new_expr();
e->operator= ':';
e->name= copystr(t->name);
skip_token(2);
} else
if (t->type == T_WORD && get_token(1)->symbol == '=') {
int n= 2;
if ((e= ack_get_C_expression(&n)) == nil) {
zap();
a= ack_get_instruction();
} else
if (get_token(n)->symbol != ';') {
parse_err(1, t, "garbage after assignment\n");
zap();
a= ack_get_instruction();
} else {
a= new_asm86();
a->line= t->line;
a->opcode= DOT_EQU;
a->optype= PSEUDO;
a->args= new_expr();
a->args->operator= '=';
a->args->name= copystr(t->name);
a->args->middle= e;
skip_token(n+1);
}
} else
if (t->type == T_WORD) {
if ((a= ack_get_statement()) == nil) {
zap();
a= ack_get_instruction();
}
} else {
parse_err(1, t, "syntax error\n");
zap();
a= ack_get_instruction();
}
return a;
}
asm86_t *ncc_get_instruction(void)
{
return ack_get_instruction();
}

View File

@ -1,940 +0,0 @@
/* parse_bas.c - parse BCC AS assembly Author: Kees J. Bot
* 13 Nov 1994
*/
#define nil 0
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "asmconv.h"
#include "token.h"
#include "asm86.h"
#include "languages.h"
typedef struct mnemonic { /* BAS mnemonics translation table. */
char *name;
opcode_t opcode;
optype_t optype;
} mnemonic_t;
static mnemonic_t mnemtab[] = { /* This array is sorted. */
{ ".align", DOT_ALIGN, PSEUDO },
{ ".ascii", DOT_ASCII, PSEUDO },
{ ".asciz", DOT_ASCIZ, PSEUDO },
{ ".assert", DOT_ASSERT, PSEUDO },
{ ".base", DOT_BASE, PSEUDO },
{ ".blkb", DOT_SPACE, PSEUDO },
{ ".bss", DOT_BSS, PSEUDO },
{ ".byte", DOT_DATA1, PSEUDO },
{ ".comm", DOT_COMM, PSEUDO },
{ ".data", DOT_DATA, PSEUDO },
{ ".define", DOT_DEFINE, PSEUDO },
{ ".end", DOT_END, PSEUDO },
{ ".even", DOT_ALIGN, PSEUDO },
{ ".extern", DOT_EXTERN, PSEUDO },
{ ".file", DOT_FILE, PSEUDO },
{ ".globl", DOT_DEFINE, PSEUDO },
{ ".lcomm", DOT_LCOMM, PSEUDO },
{ ".line", DOT_LINE, PSEUDO },
{ ".list", DOT_LIST, PSEUDO },
{ ".long", DOT_DATA4, PSEUDO },
{ ".nolist", DOT_NOLIST, PSEUDO },
{ ".rom", DOT_ROM, PSEUDO },
{ ".space", DOT_SPACE, PSEUDO },
{ ".symb", DOT_SYMB, PSEUDO },
{ ".text", DOT_TEXT, PSEUDO },
{ ".use16", DOT_USE16, PSEUDO },
{ ".use32", DOT_USE32, PSEUDO },
{ ".word", DOT_DATA2, PSEUDO },
{ ".zerob", DOT_SPACE, PSEUDO },
{ ".zerow", DOT_SPACE, PSEUDO },
{ "aaa", AAA, WORD },
{ "aad", AAD, WORD },
{ "aam", AAM, WORD },
{ "aas", AAS, WORD },
{ "adc", ADC, WORD },
{ "add", ADD, WORD },
{ "and", AND, WORD },
{ "arpl", ARPL, WORD },
{ "bc", JB, JUMP },
{ "beq", JE, JUMP },
{ "bge", JGE, JUMP },
{ "bgt", JG, JUMP },
{ "bhi", JA, JUMP },
{ "bhis", JAE, JUMP },
{ "ble", JLE, JUMP },
{ "blo", JB, JUMP },
{ "blos", JBE, JUMP },
{ "blt", JL, JUMP },
{ "bnc", JAE, JUMP },
{ "bne", JNE, JUMP },
{ "bound", BOUND, WORD },
{ "br", JMP, JUMP },
{ "bsf", BSF, WORD },
{ "bsr", BSR, WORD },
{ "bswap", BSWAP, WORD },
{ "bt", BT, WORD },
{ "btc", BTC, WORD },
{ "btr", BTR, WORD },
{ "bts", BTS, WORD },
{ "bz", JE, JUMP },
{ "call", CALL, JUMP },
{ "callf", CALLF, JUMP },
{ "cbw", CBW, WORD },
{ "cdq", CWD, WORD },
{ "clc", CLC, WORD },
{ "cld", CLD, WORD },
{ "cli", CLI, WORD },
{ "clts", CLTS, WORD },
{ "cmc", CMC, WORD },
{ "cmp", CMP, WORD },
{ "cmps", CMPS, WORD },
{ "cmpsb", CMPS, BYTE },
{ "cmpxchg", CMPXCHG, WORD },
{ "cwd", CWD, WORD },
{ "cwde", CBW, WORD },
{ "daa", DAA, WORD },
{ "das", DAS, WORD },
{ "dd", DOT_DATA4, PSEUDO },
{ "dec", DEC, WORD },
{ "div", DIV, WORD },
{ "enter", ENTER, WORD },
{ "export", DOT_DEFINE, PSEUDO },
{ "f2xm1", F2XM1, WORD },
{ "fabs", FABS, WORD },
{ "fadd", FADD, WORD },
{ "faddd", FADDD, WORD },
{ "faddp", FADDP, WORD },
{ "fadds", FADDS, WORD },
{ "fbld", FBLD, WORD },
{ "fbstp", FBSTP, WORD },
{ "fchs", FCHS, WORD },
{ "fclex", FCLEX, WORD },
{ "fcomd", FCOMD, WORD },
{ "fcompd", FCOMPD, WORD },
{ "fcompp", FCOMPP, WORD },
{ "fcomps", FCOMPS, WORD },
{ "fcoms", FCOMS, WORD },
{ "fcos", FCOS, WORD },
{ "fdecstp", FDECSTP, WORD },
{ "fdivd", FDIVD, WORD },
{ "fdivp", FDIVP, WORD },
{ "fdivrd", FDIVRD, WORD },
{ "fdivrp", FDIVRP, WORD },
{ "fdivrs", FDIVRS, WORD },
{ "fdivs", FDIVS, WORD },
{ "ffree", FFREE, WORD },
{ "fiaddl", FIADDL, WORD },
{ "fiadds", FIADDS, WORD },
{ "ficom", FICOM, WORD },
{ "ficomp", FICOMP, WORD },
{ "fidivl", FIDIVL, WORD },
{ "fidivrl", FIDIVRL, WORD },
{ "fidivrs", FIDIVRS, WORD },
{ "fidivs", FIDIVS, WORD },
{ "fildl", FILDL, WORD },
{ "fildq", FILDQ, WORD },
{ "filds", FILDS, WORD },
{ "fimull", FIMULL, WORD },
{ "fimuls", FIMULS, WORD },
{ "fincstp", FINCSTP, WORD },
{ "finit", FINIT, WORD },
{ "fistl", FISTL, WORD },
{ "fistp", FISTP, WORD },
{ "fists", FISTS, WORD },
{ "fisubl", FISUBL, WORD },
{ "fisubrl", FISUBRL, WORD },
{ "fisubrs", FISUBRS, WORD },
{ "fisubs", FISUBS, WORD },
{ "fld1", FLD1, WORD },
{ "fldcw", FLDCW, WORD },
{ "fldd", FLDD, WORD },
{ "fldenv", FLDENV, WORD },
{ "fldl2e", FLDL2E, WORD },
{ "fldl2t", FLDL2T, WORD },
{ "fldlg2", FLDLG2, WORD },
{ "fldln2", FLDLN2, WORD },
{ "fldpi", FLDPI, WORD },
{ "flds", FLDS, WORD },
{ "fldx", FLDX, WORD },
{ "fldz", FLDZ, WORD },
{ "fmuld", FMULD, WORD },
{ "fmulp", FMULP, WORD },
{ "fmuls", FMULS, WORD },
{ "fnop", FNOP, WORD },
{ "fpatan", FPATAN, WORD },
{ "fprem", FPREM, WORD },
{ "fprem1", FPREM1, WORD },
{ "fptan", FPTAN, WORD },
{ "frndint", FRNDINT, WORD },
{ "frstor", FRSTOR, WORD },
{ "fsave", FSAVE, WORD },
{ "fscale", FSCALE, WORD },
{ "fsin", FSIN, WORD },
{ "fsincos", FSINCOS, WORD },
{ "fsqrt", FSQRT, WORD },
{ "fstcw", FSTCW, WORD },
{ "fstd", FSTD, WORD },
{ "fstenv", FSTENV, WORD },
{ "fstpd", FSTPD, WORD },
{ "fstps", FSTPS, WORD },
{ "fstpx", FSTPX, WORD },
{ "fsts", FSTS, WORD },
{ "fstsw", FSTSW, WORD },
{ "fsubd", FSUBD, WORD },
{ "fsubp", FSUBP, WORD },
{ "fsubpr", FSUBPR, WORD },
{ "fsubrd", FSUBRD, WORD },
{ "fsubrs", FSUBRS, WORD },
{ "fsubs", FSUBS, WORD },
{ "ftst", FTST, WORD },
{ "fucom", FUCOM, WORD },
{ "fucomp", FUCOMP, WORD },
{ "fucompp", FUCOMPP, WORD },
{ "fxam", FXAM, WORD },
{ "fxch", FXCH, WORD },
{ "fxtract", FXTRACT, WORD },
{ "fyl2x", FYL2X, WORD },
{ "fyl2xp1", FYL2XP1, WORD },
{ "hlt", HLT, WORD },
{ "idiv", IDIV, WORD },
{ "imul", IMUL, WORD },
{ "in", IN, WORD },
{ "inb", IN, BYTE },
{ "inc", INC, WORD },
{ "ins", INS, WORD },
{ "insb", INS, BYTE },
{ "int", INT, WORD },
{ "into", INTO, JUMP },
{ "invd", INVD, WORD },
{ "invlpg", INVLPG, WORD },
{ "iret", IRET, JUMP },
{ "iretd", IRETD, JUMP },
{ "j", JMP, JUMP },
{ "ja", JA, JUMP },
{ "jae", JAE, JUMP },
{ "jb", JB, JUMP },
{ "jbe", JBE, JUMP },
{ "jc", JB, JUMP },
{ "jcxz", JCXZ, JUMP },
{ "je", JE, JUMP },
{ "jecxz", JCXZ, JUMP },
{ "jeq", JE, JUMP },
{ "jg", JG, JUMP },
{ "jge", JGE, JUMP },
{ "jgt", JG, JUMP },
{ "jhi", JA, JUMP },
{ "jhis", JAE, JUMP },
{ "jl", JL, JUMP },
{ "jle", JLE, JUMP },
{ "jlo", JB, JUMP },
{ "jlos", JBE, JUMP },
{ "jlt", JL, JUMP },
{ "jmp", JMP, JUMP },
{ "jmpf", JMPF, JUMP },
{ "jna", JBE, JUMP },
{ "jnae", JB, JUMP },
{ "jnb", JAE, JUMP },
{ "jnbe", JA, JUMP },
{ "jnc", JAE, JUMP },
{ "jne", JNE, JUMP },
{ "jng", JLE, JUMP },
{ "jnge", JL, JUMP },
{ "jnl", JGE, JUMP },
{ "jnle", JG, JUMP },
{ "jno", JNO, JUMP },
{ "jnp", JNP, JUMP },
{ "jns", JNS, JUMP },
{ "jnz", JNE, JUMP },
{ "jo", JO, JUMP },
{ "jp", JP, JUMP },
{ "js", JS, JUMP },
{ "jz", JE, JUMP },
{ "lahf", LAHF, WORD },
{ "lar", LAR, WORD },
{ "lds", LDS, WORD },
{ "lea", LEA, WORD },
{ "leave", LEAVE, WORD },
{ "les", LES, WORD },
{ "lfs", LFS, WORD },
{ "lgdt", LGDT, WORD },
{ "lgs", LGS, WORD },
{ "lidt", LIDT, WORD },
{ "lldt", LLDT, WORD },
{ "lmsw", LMSW, WORD },
{ "lock", LOCK, WORD },
{ "lods", LODS, WORD },
{ "lodsb", LODS, BYTE },
{ "loop", LOOP, JUMP },
{ "loope", LOOPE, JUMP },
{ "loopne", LOOPNE, JUMP },
{ "loopnz", LOOPNE, JUMP },
{ "loopz", LOOPE, JUMP },
{ "lsl", LSL, WORD },
{ "lss", LSS, WORD },
{ "ltr", LTR, WORD },
{ "mov", MOV, WORD },
{ "movs", MOVS, WORD },
{ "movsb", MOVS, BYTE },
{ "movsx", MOVSX, WORD },
{ "movzx", MOVZX, WORD },
{ "mul", MUL, WORD },
{ "neg", NEG, WORD },
{ "nop", NOP, WORD },
{ "not", NOT, WORD },
{ "or", OR, WORD },
{ "out", OUT, WORD },
{ "outb", OUT, BYTE },
{ "outs", OUTS, WORD },
{ "outsb", OUTS, BYTE },
{ "pop", POP, WORD },
{ "popa", POPA, WORD },
{ "popad", POPA, WORD },
{ "popf", POPF, WORD },
{ "popfd", POPF, WORD },
{ "push", PUSH, WORD },
{ "pusha", PUSHA, WORD },
{ "pushad", PUSHA, WORD },
{ "pushf", PUSHF, WORD },
{ "pushfd", PUSHF, WORD },
{ "rcl", RCL, WORD },
{ "rcr", RCR, WORD },
{ "ret", RET, JUMP },
{ "retf", RETF, JUMP },
{ "rol", ROL, WORD },
{ "ror", ROR, WORD },
{ "sahf", SAHF, WORD },
{ "sal", SAL, WORD },
{ "sar", SAR, WORD },
{ "sbb", SBB, WORD },
{ "scas", SCAS, WORD },
{ "seta", SETA, BYTE },
{ "setae", SETAE, BYTE },
{ "setb", SETB, BYTE },
{ "setbe", SETBE, BYTE },
{ "sete", SETE, BYTE },
{ "setg", SETG, BYTE },
{ "setge", SETGE, BYTE },
{ "setl", SETL, BYTE },
{ "setna", SETBE, BYTE },
{ "setnae", SETB, BYTE },
{ "setnb", SETAE, BYTE },
{ "setnbe", SETA, BYTE },
{ "setne", SETNE, BYTE },
{ "setng", SETLE, BYTE },
{ "setnge", SETL, BYTE },
{ "setnl", SETGE, BYTE },
{ "setnle", SETG, BYTE },
{ "setno", SETNO, BYTE },
{ "setnp", SETNP, BYTE },
{ "setns", SETNS, BYTE },
{ "seto", SETO, BYTE },
{ "setp", SETP, BYTE },
{ "sets", SETS, BYTE },
{ "setz", SETE, BYTE },
{ "sgdt", SGDT, WORD },
{ "shl", SHL, WORD },
{ "shld", SHLD, WORD },
{ "shr", SHR, WORD },
{ "shrd", SHRD, WORD },
{ "sidt", SIDT, WORD },
{ "sldt", SLDT, WORD },
{ "smsw", SMSW, WORD },
{ "stc", STC, WORD },
{ "std", STD, WORD },
{ "sti", STI, WORD },
{ "stos", STOS, WORD },
{ "stosb", STOS, BYTE },
{ "str", STR, WORD },
{ "sub", SUB, WORD },
{ "test", TEST, WORD },
{ "verr", VERR, WORD },
{ "verw", VERW, WORD },
{ "wait", WAIT, WORD },
{ "wbinvd", WBINVD, WORD },
{ "xadd", XADD, WORD },
{ "xchg", XCHG, WORD },
{ "xlat", XLAT, WORD },
{ "xor", XOR, WORD },
};
void bas_parse_init(char *file)
/* Prepare parsing of an BAS assembly file. */
{
tok_init(file, '!');
}
static void zap(void)
/* An error, zap the rest of the line. */
{
token_t *t;
while ((t= get_token(0))->type != T_EOF && t->symbol != ';')
skip_token(1);
}
static mnemonic_t *search_mnem(char *name)
/* Binary search for a mnemonic. (That's why the table is sorted.) */
{
int low, mid, high;
int cmp;
mnemonic_t *m;
low= 0;
high= arraysize(mnemtab)-1;
while (low <= high) {
mid= (low + high) / 2;
m= &mnemtab[mid];
if ((cmp= strcmp(name, m->name)) == 0) return m;
if (cmp < 0) high= mid-1; else low= mid+1;
}
return nil;
}
static expression_t *bas_get_C_expression(int *pn)
/* Read a "C-like" expression. Note that we don't worry about precedence,
* the expression is printed later like it is read. If the target language
* does not have all the operators (like ~) then this has to be repaired by
* changing the source file. (No problem, you still have one source file
* to maintain, not two.)
*/
{
expression_t *e, *a1, *a2;
token_t *t;
if ((t= get_token(*pn))->symbol == '(') {
/* ( expr ): grouping. */
(*pn)++;
if ((a1= bas_get_C_expression(pn)) == nil) return nil;
if (get_token(*pn)->symbol != ')') {
parse_err(1, t, "missing )\n");
del_expr(a1);
return nil;
}
(*pn)++;
e= new_expr();
e->operator= '[';
e->middle= a1;
} else
if (t->type == T_WORD || t->type == T_STRING) {
/* Label, number, or string. */
e= new_expr();
e->operator= t->type == T_WORD ? 'W' : 'S';
e->name= allocate(nil, (t->len+1) * sizeof(e->name[0]));
memcpy(e->name, t->name, t->len+1);
e->len= t->len;
(*pn)++;
} else
if (t->symbol == '+' || t->symbol == '-' || t->symbol == '~') {
/* Unary operator. */
(*pn)++;
if ((a1= bas_get_C_expression(pn)) == nil) return nil;
e= new_expr();
e->operator= t->symbol;
e->middle= a1;
} else
if (t->symbol == '$' && get_token(*pn + 1)->type == T_WORD) {
/* A hexadecimal number. */
t= get_token(*pn + 1);
e= new_expr();
e->operator= 'W';
e->name= allocate(nil, (t->len+3) * sizeof(e->name[0]));
strcpy(e->name, "0x");
memcpy(e->name+2, t->name, t->len+1);
e->len= t->len+2;
(*pn)+= 2;
} else {
parse_err(1, t, "expression syntax error\n");
return nil;
}
switch ((t= get_token(*pn))->symbol) {
case '+':
case '-':
case '*':
case '/':
case '%':
case '&':
case '|':
case '^':
case S_LEFTSHIFT:
case S_RIGHTSHIFT:
(*pn)++;
a1= e;
if ((a2= bas_get_C_expression(pn)) == nil) {
del_expr(a1);
return nil;
}
e= new_expr();
e->operator= t->symbol;
e->left= a1;
e->right= a2;
}
return e;
}
/* We want to know the sizes of the first two operands. */
static optype_t optypes[2];
static int op_idx;
static expression_t *bas_get_operand(int *pn)
/* Get something like: [memory], offset[base+index*scale], or simpler. */
{
expression_t *e, *offset, *base, *index;
token_t *t;
int c;
optype_t optype;
/* Prefixed by 'byte', 'word' or 'dword'? */
if ((t= get_token(*pn))->type == T_WORD && (
strcmp(t->name, "byte") == 0
|| strcmp(t->name, "word") == 0
|| strcmp(t->name, "dword") == 0)
) {
switch (t->name[0]) {
case 'b': optype= BYTE; break;
case 'w': optype= use16() ? WORD : OWORD; break;
case 'd': optype= use32() ? WORD : OWORD; break;
}
if (op_idx < arraysize(optypes)) optypes[op_idx++]= optype;
(*pn)++;
/* It may even be "byte ptr"... */
if ((t= get_token(*pn))->type == T_WORD
&& strcmp(t->name, "ptr") == 0) {
(*pn)++;
}
}
/* Is it [memory]? */
if (get_token(*pn)->symbol == '['
&& ((t= get_token(*pn + 1))->type != T_WORD
|| !isregister(t->name))
) {
/* A memory dereference. */
(*pn)++;
if ((offset= bas_get_C_expression(pn)) == nil) return nil;
if (get_token(*pn)->symbol != ']') {
parse_err(1, t, "operand syntax error\n");
del_expr(offset);
return nil;
}
(*pn)++;
e= new_expr();
e->operator= '(';
e->middle= offset;
return e;
}
/* #something? *something? */
if ((c= get_token(*pn)->symbol) == '#' || c == '*') {
/* '#' and '*' are often used to introduce some constant. */
(*pn)++;
}
/* Offset? */
if (get_token(*pn)->symbol != '[') {
/* There is an offset. */
if ((offset= bas_get_C_expression(pn)) == nil) return nil;
} else {
/* No offset. */
offset= nil;
}
/* [base]? [base+? base-? */
c= 0;
if (get_token(*pn)->symbol == '['
&& (t= get_token(*pn + 1))->type == T_WORD
&& isregister(t->name)
&& ((c= get_token(*pn + 2)->symbol) == ']' || c=='+' || c=='-')
) {
/* A base register expression. */
base= new_expr();
base->operator= 'B';
base->name= copystr(t->name);
(*pn)+= c == ']' ? 3 : 2;
} else {
/* No base register expression. */
base= nil;
}
/* +offset]? -offset]? */
if (offset == nil
&& (c == '+' || c == '-')
&& (t= get_token(*pn + 1))->type == T_WORD
&& !isregister(t->name)
) {
(*pn)++;
if ((offset= bas_get_C_expression(pn)) == nil) return nil;
if (get_token(*pn)->symbol != ']') {
parse_err(1, t, "operand syntax error\n");
del_expr(offset);
del_expr(base);
return nil;
}
(*pn)++;
c= 0;
}
/* [index*scale]? +index*scale]? */
if (c == '+' || get_token(*pn)->symbol == '[') {
/* An index most likely. */
token_t *m= nil;
if (!( /* This must be true: */
(t= get_token(*pn + 1))->type == T_WORD
&& isregister(t->name)
&& (get_token(*pn + 2)->symbol == ']' || (
get_token(*pn + 2)->symbol == '*'
&& (m= get_token(*pn + 3))->type == T_WORD
&& strchr("1248", m->name[0]) != nil
&& m->name[1] == 0
&& get_token(*pn + 4)->symbol == ']'
))
)) {
/* Alas it isn't */
parse_err(1, t, "operand syntax error\n");
del_expr(offset);
del_expr(base);
return nil;
}
/* Found an index. */
index= new_expr();
index->operator= m == nil ? '1' : m->name[0];
index->name= copystr(t->name);
(*pn)+= (m == nil ? 3 : 5);
} else {
/* No index. */
index= nil;
}
if (base == nil && index == nil) {
/* Return a lone offset as is. */
e= offset;
/* Lone registers tell operand size. */
if (offset->operator == 'W' && isregister(offset->name)) {
switch (isregister(offset->name)) {
case 1: optype= BYTE; break;
case 2: optype= use16() ? WORD : OWORD; break;
case 4: optype= use32() ? WORD : OWORD; break;
}
if (op_idx < arraysize(optypes))
optypes[op_idx++]= optype;
}
} else {
e= new_expr();
e->operator= 'O';
e->left= offset;
e->middle= base;
e->right= index;
}
return e;
}
static expression_t *bas_get_oplist(int *pn)
/* Get a comma (or colon for jmpf and callf) separated list of instruction
* operands.
*/
{
expression_t *e, *o1, *o2;
token_t *t;
if ((e= bas_get_operand(pn)) == nil) return nil;
if ((t= get_token(*pn))->symbol == ',' || t->symbol == ':') {
o1= e;
(*pn)++;
if ((o2= bas_get_oplist(pn)) == nil) {
del_expr(o1);
return nil;
}
e= new_expr();
e->operator= ',';
e->left= o1;
e->right= o2;
}
return e;
}
static asm86_t *bas_get_statement(void)
/* Get a pseudo op or machine instruction with arguments. */
{
token_t *t= get_token(0);
asm86_t *a;
mnemonic_t *m;
int n;
int prefix_seen;
assert(t->type == T_WORD);
if (strcmp(t->name, ".sect") == 0) {
/* .sect .text etc. Accept only four segment names. */
skip_token(1);
t= get_token(0);
if (t->type != T_WORD || (
strcmp(t->name, ".text") != 0
&& strcmp(t->name, ".rom") != 0
&& strcmp(t->name, ".data") != 0
&& strcmp(t->name, ".bss") != 0
&& strcmp(t->name, ".end") != 0
)) {
parse_err(1, t, "weird section name to .sect\n");
return nil;
}
}
a= new_asm86();
/* Process instruction prefixes. */
for (prefix_seen= 0;; prefix_seen= 1) {
if (strcmp(t->name, "rep") == 0
|| strcmp(t->name, "repe") == 0
|| strcmp(t->name, "repne") == 0
|| strcmp(t->name, "repz") == 0
|| strcmp(t->name, "repnz") == 0
) {
if (a->rep != ONCE) {
parse_err(1, t,
"can't have more than one rep\n");
}
switch (t->name[3]) {
case 0: a->rep= REP; break;
case 'e':
case 'z': a->rep= REPE; break;
case 'n': a->rep= REPNE; break;
}
} else
if (strcmp(t->name, "seg") == 0
&& get_token(1)->type == T_WORD) {
if (a->seg != DEFSEG) {
parse_err(1, t,
"can't have more than one segment prefix\n");
}
switch (get_token(1)->name[0]) {
case 'c': a->seg= CSEG; break;
case 'd': a->seg= DSEG; break;
case 'e': a->seg= ESEG; break;
case 'f': a->seg= FSEG; break;
case 'g': a->seg= GSEG; break;
case 's': a->seg= SSEG; break;
}
skip_token(1);
} else
if (!prefix_seen) {
/* No prefix here, get out! */
break;
} else {
/* No more prefixes, next must be an instruction. */
if (t->type != T_WORD
|| (m= search_mnem(t->name)) == nil
|| m->optype == PSEUDO
) {
parse_err(1, t,
"machine instruction expected after instruction prefix\n");
del_asm86(a);
return nil;
}
break;
}
/* Skip the prefix and extra newlines. */
do {
skip_token(1);
} while ((t= get_token(0))->symbol == ';');
}
/* All the readahead being done upsets the line counter. */
a->line= t->line;
/* Read a machine instruction or pseudo op. */
if ((m= search_mnem(t->name)) == nil) {
parse_err(1, t, "unknown instruction '%s'\n", t->name);
del_asm86(a);
return nil;
}
a->opcode= m->opcode;
a->optype= m->optype;
if (a->opcode == CBW || a->opcode == CWD) {
a->optype= (strcmp(t->name, "cbw") == 0
|| strcmp(t->name, "cwd") == 0) == use16() ? WORD : OWORD;
}
for (op_idx= 0; op_idx < arraysize(optypes); op_idx++)
optypes[op_idx]= m->optype;
op_idx= 0;
n= 1;
if (get_token(1)->symbol != ';'
&& (a->args= bas_get_oplist(&n)) == nil) {
del_asm86(a);
return nil;
}
if (m->optype == WORD) {
/* Does one of the operands overide the optype? */
for (op_idx= 0; op_idx < arraysize(optypes); op_idx++) {
if (optypes[op_idx] != m->optype)
a->optype= optypes[op_idx];
}
}
if (get_token(n)->symbol != ';') {
parse_err(1, t, "garbage at end of instruction\n");
del_asm86(a);
return nil;
}
switch (a->opcode) {
case DOT_ALIGN:
/* Restrict .align to have a single numeric argument, some
* assemblers think of the argument as a power of two, so
* we need to be able to change the value.
*/
if (strcmp(t->name, ".even") == 0 && a->args == nil) {
/* .even becomes .align 2. */
expression_t *e;
a->args= e= new_expr();
e->operator= 'W';
e->name= copystr("2");
e->len= 2;
}
if (a->args == nil || a->args->operator != 'W'
|| !isanumber(a->args->name)) {
parse_err(1, t,
".align is restricted to one numeric argument\n");
del_asm86(a);
return nil;
}
break;
case MOVSX:
case MOVZX:
/* Types of both operands tell the instruction type. */
a->optype= optypes[0];
if (optypes[1] == BYTE) {
a->opcode= a->opcode == MOVSX ? MOVSXB : MOVZXB;
}
break;
case SAL:
case SAR:
case SHL:
case SHR:
case RCL:
case RCR:
case ROL:
case ROR:
/* Only the first operand tells the operand size. */
a->optype= optypes[0];
break;
default:;
}
skip_token(n+1);
return a;
}
asm86_t *bas_get_instruction(void)
{
asm86_t *a= nil;
expression_t *e;
token_t *t;
while ((t= get_token(0))->symbol == ';')
skip_token(1);
if (t->type == T_EOF) return nil;
if (t->symbol == '#') {
/* Preprocessor line and file change. */
if ((t= get_token(1))->type != T_WORD || !isanumber(t->name)
|| get_token(2)->type != T_STRING
) {
parse_err(1, t, "file not preprocessed?\n");
zap();
} else {
set_file(get_token(2)->name,
strtol(get_token(1)->name, nil, 0) - 1);
/* GNU CPP adds extra cruft, simply zap the line. */
zap();
}
a= bas_get_instruction();
} else
if (t->type == T_WORD && get_token(1)->symbol == ':') {
/* A label definition. */
a= new_asm86();
a->line= t->line;
a->opcode= DOT_LABEL;
a->optype= PSEUDO;
a->args= e= new_expr();
e->operator= ':';
e->name= copystr(t->name);
skip_token(2);
} else
if (t->type == T_WORD && get_token(1)->symbol == '=') {
int n= 2;
if ((e= bas_get_C_expression(&n)) == nil) {
zap();
a= bas_get_instruction();
} else
if (get_token(n)->symbol != ';') {
parse_err(1, t, "garbage after assignment\n");
zap();
a= bas_get_instruction();
} else {
a= new_asm86();
a->line= t->line;
a->opcode= DOT_EQU;
a->optype= PSEUDO;
a->args= new_expr();
a->args->operator= '=';
a->args->name= copystr(t->name);
a->args->middle= e;
skip_token(n+1);
}
} else
if (t->type == T_WORD && get_token(1)->type == T_WORD
&& strcmp(get_token(1)->name, "lcomm") == 0) {
/* Local common block definition. */
int n= 2;
if ((e= bas_get_C_expression(&n)) == nil) {
zap();
a= bas_get_instruction();
} else
if (get_token(n)->symbol != ';') {
parse_err(1, t, "garbage after lcomm\n");
zap();
a= bas_get_instruction();
} else {
a= new_asm86();
a->line= t->line;
a->opcode= DOT_LCOMM;
a->optype= PSEUDO;
a->args= new_expr();
a->args->operator= ',';
a->args->right= e;
a->args->left= e= new_expr();
e->operator= 'W';
e->name= copystr(t->name);
e->len= strlen(e->name)+1;
skip_token(n+1);
}
} else
if (t->type == T_WORD) {
if ((a= bas_get_statement()) == nil) {
zap();
a= bas_get_instruction();
}
} else {
parse_err(1, t, "syntax error\n");
zap();
a= bas_get_instruction();
}
if (a->optype == OWORD) {
a->optype= WORD;
a->oaz|= OPZ;
}
return a;
}

View File

@ -1,879 +0,0 @@
/* parse_ack.c - parse GNU assembly Author: R.S. Veldema
* <rveldema@cs.vu.nl>
* 26 Aug 1996
*/
#define nil 0
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <assert.h>
#include "asmconv.h"
#include "token.h"
#include "asm86.h"
#include "languages.h"
typedef struct mnemonic { /* GNU as86 mnemonics translation table. */
char *name;
opcode_t opcode;
optype_t optype;
} mnemonic_t;
static mnemonic_t mnemtab[] = { /* This array is sorted. */
{ ".align", DOT_ALIGN, PSEUDO },
{ ".ascii", DOT_ASCII, PSEUDO },
{ ".asciz", DOT_ASCIZ, PSEUDO },
{ ".assert", DOT_ASSERT, PSEUDO },
{ ".base", DOT_BASE, PSEUDO },
{ ".bss", DOT_BSS, PSEUDO },
{ ".byte", DOT_DATA1, PSEUDO },
{ ".comm", DOT_COMM, PSEUDO },
{ ".data", DOT_DATA, PSEUDO },
{ ".data1", DOT_DATA1, PSEUDO },
{ ".data2", DOT_DATA2, PSEUDO },
{ ".data4", DOT_DATA4, PSEUDO },
{ ".end", DOT_END, PSEUDO },
{ ".extern", DOT_EXTERN, PSEUDO },
{ ".file", DOT_FILE, PSEUDO },
{ ".globl", DOT_DEFINE, PSEUDO },
{ ".lcomm", DOT_LCOMM, PSEUDO },
{ ".line", DOT_LINE, PSEUDO },
{ ".list", DOT_LIST, PSEUDO },
{ ".long", DOT_DATA4, PSEUDO },
{ ".nolist", DOT_NOLIST, PSEUDO },
{ ".rom", DOT_ROM, PSEUDO },
{ ".space", DOT_SPACE, PSEUDO },
{ ".symb", DOT_SYMB, PSEUDO },
{ ".text", DOT_TEXT, PSEUDO },
{ ".word", DOT_DATA2, PSEUDO },
{ "aaa", AAA, WORD },
{ "aad", AAD, WORD },
{ "aam", AAM, WORD },
{ "aas", AAS, WORD },
{ "adcb", ADC, BYTE },
{ "adcl", ADC, WORD },
{ "adcw", ADC, OWORD },
{ "addb", ADD, BYTE },
{ "addl", ADD, WORD },
{ "addw", ADD, OWORD },
{ "andb", AND, BYTE },
{ "andl", AND, WORD },
{ "andw", AND, OWORD },
{ "arpl", ARPL, WORD },
{ "bound", BOUND, WORD },
{ "bsf", BSF, WORD },
{ "bsr", BSR, WORD },
{ "bswap", BSWAP, WORD },
{ "btc", BTC, WORD },
{ "btl", BT, WORD },
{ "btr", BTR, WORD },
{ "bts", BTS, WORD },
{ "btw", BT, OWORD },
{ "call", CALL, JUMP },
{ "callf", CALLF, JUMP },
{ "cbtw", CBW, OWORD },
{ "cbw", CBW, WORD },
{ "cdq", CWD, WORD },
{ "clc", CLC, WORD },
{ "cld", CLD, WORD },
{ "cli", CLI, WORD },
{ "cltd", CWD, WORD },
{ "clts", CLTS, WORD },
{ "cmc", CMC, WORD },
{ "cmpb", CMP, BYTE },
{ "cmpl", CMP, WORD },
{ "cmps", CMPS, WORD },
{ "cmpsb", CMPS, BYTE },
{ "cmpw", CMP, OWORD },
{ "cmpxchg", CMPXCHG, WORD },
{ "cwd", CWD, WORD },
{ "cwde", CBW, WORD },
{ "cwtd", CWD, OWORD },
{ "cwtl", CBW, WORD },
{ "daa", DAA, WORD },
{ "das", DAS, WORD },
{ "decb", DEC, BYTE },
{ "decl", DEC, WORD },
{ "decw", DEC, OWORD },
{ "divb", DIV, BYTE },
{ "divl", DIV, WORD },
{ "divw", DIV, OWORD },
{ "enter", ENTER, WORD },
{ "f2xm1", F2XM1, WORD },
{ "fabs", FABS, WORD },
{ "fadd", FADD, WORD },
{ "faddd", FADDD, WORD },
{ "faddp", FADDP, WORD },
{ "fadds", FADDS, WORD },
{ "fbld", FBLD, WORD },
{ "fbstp", FBSTP, WORD },
{ "fchs", FCHS, WORD },
{ "fcomd", FCOMD, WORD },
{ "fcompd", FCOMPD, WORD },
{ "fcompp", FCOMPP, WORD },
{ "fcomps", FCOMPS, WORD },
{ "fcoms", FCOMS, WORD },
{ "fcos", FCOS, WORD },
{ "fdecstp", FDECSTP, WORD },
{ "fdivd", FDIVD, WORD },
{ "fdivp", FDIVP, WORD },
{ "fdivrd", FDIVRD, WORD },
{ "fdivrp", FDIVRP, WORD },
{ "fdivrs", FDIVRS, WORD },
{ "fdivs", FDIVS, WORD },
{ "ffree", FFREE, WORD },
{ "fiaddl", FIADDL, WORD },
{ "fiadds", FIADDS, WORD },
{ "ficom", FICOM, WORD },
{ "ficomp", FICOMP, WORD },
{ "fidivl", FIDIVL, WORD },
{ "fidivrl", FIDIVRL, WORD },
{ "fidivrs", FIDIVRS, WORD },
{ "fidivs", FIDIVS, WORD },
{ "fildl", FILDL, WORD },
{ "fildq", FILDQ, WORD },
{ "filds", FILDS, WORD },
{ "fimull", FIMULL, WORD },
{ "fimuls", FIMULS, WORD },
{ "fincstp", FINCSTP, WORD },
{ "fistl", FISTL, WORD },
{ "fistp", FISTP, WORD },
{ "fists", FISTS, WORD },
{ "fisubl", FISUBL, WORD },
{ "fisubrl", FISUBRL, WORD },
{ "fisubrs", FISUBRS, WORD },
{ "fisubs", FISUBS, WORD },
{ "fld1", FLD1, WORD },
{ "fldcw", FLDCW, WORD },
{ "fldd", FLDD, WORD },
{ "fldenv", FLDENV, WORD },
{ "fldl2e", FLDL2E, WORD },
{ "fldl2t", FLDL2T, WORD },
{ "fldlg2", FLDLG2, WORD },
{ "fldln2", FLDLN2, WORD },
{ "fldpi", FLDPI, WORD },
{ "flds", FLDS, WORD },
{ "fldx", FLDX, WORD },
{ "fldz", FLDZ, WORD },
{ "fmuld", FMULD, WORD },
{ "fmulp", FMULP, WORD },
{ "fmuls", FMULS, WORD },
{ "fnclex", FCLEX, WORD },
{ "fninit", FINIT, WORD },
{ "fnop", FNOP, WORD },
{ "fnsave", FSAVE, WORD },
{ "fnstcw", FSTCW, WORD },
{ "fnstenv", FSTENV, WORD },
{ "fpatan", FPATAN, WORD },
{ "fprem", FPREM, WORD },
{ "fprem1", FPREM1, WORD },
{ "fptan", FPTAN, WORD },
{ "frndint", FRNDINT, WORD },
{ "frstor", FRSTOR, WORD },
{ "fscale", FSCALE, WORD },
{ "fsin", FSIN, WORD },
{ "fsincos", FSINCOS, WORD },
{ "fsqrt", FSQRT, WORD },
{ "fstd", FSTD, WORD },
{ "fstpd", FSTPD, WORD },
{ "fstps", FSTPS, WORD },
{ "fstpx", FSTPX, WORD },
{ "fsts", FSTS, WORD },
{ "fstsw", FSTSW, WORD },
{ "fsubd", FSUBD, WORD },
{ "fsubp", FSUBP, WORD },
{ "fsubpr", FSUBPR, WORD },
{ "fsubrd", FSUBRD, WORD },
{ "fsubrs", FSUBRS, WORD },
{ "fsubs", FSUBS, WORD },
{ "ftst", FTST, WORD },
{ "fucom", FUCOM, WORD },
{ "fucomp", FUCOMP, WORD },
{ "fucompp", FUCOMPP, WORD },
{ "fxam", FXAM, WORD },
{ "fxch", FXCH, WORD },
{ "fxtract", FXTRACT, WORD },
{ "fyl2x", FYL2X, WORD },
{ "fyl2xp1", FYL2XP1, WORD },
{ "hlt", HLT, WORD },
{ "idivb", IDIV, BYTE },
{ "idivl", IDIV, WORD },
{ "idivw", IDIV, OWORD },
{ "imulb", IMUL, BYTE },
{ "imull", IMUL, WORD },
{ "imulw", IMUL, OWORD },
{ "inb", IN, BYTE },
{ "incb", INC, BYTE },
{ "incl", INC, WORD },
{ "incw", INC, OWORD },
{ "inl", IN, WORD },
{ "insb", INS, BYTE },
{ "insl", INS, WORD },
{ "insw", INS, OWORD },
{ "int", INT, WORD },
{ "into", INTO, JUMP },
{ "invd", INVD, WORD },
{ "invlpg", INVLPG, WORD },
{ "inw", IN, OWORD },
{ "iret", IRET, JUMP },
{ "iretd", IRETD, JUMP },
{ "ja", JA, JUMP },
{ "jae", JAE, JUMP },
{ "jb", JB, JUMP },
{ "jbe", JBE, JUMP },
{ "jc", JB, JUMP },
{ "jcxz", JCXZ, JUMP },
{ "je", JE, JUMP },
{ "jecxz", JCXZ, JUMP },
{ "jg", JG, JUMP },
{ "jge", JGE, JUMP },
{ "jl", JL, JUMP },
{ "jle", JLE, JUMP },
{ "jmp", JMP, JUMP },
{ "jmpf", JMPF, JUMP },
{ "jna", JBE, JUMP },
{ "jnae", JB, JUMP },
{ "jnb", JAE, JUMP },
{ "jnbe", JA, JUMP },
{ "jnc", JAE, JUMP },
{ "jne", JNE, JUMP },
{ "jng", JLE, JUMP },
{ "jnge", JL, JUMP },
{ "jnl", JGE, JUMP },
{ "jnle", JG, JUMP },
{ "jno", JNO, JUMP },
{ "jnp", JNP, JUMP },
{ "jns", JNS, JUMP },
{ "jnz", JNE, JUMP },
{ "jo", JO, JUMP },
{ "jp", JP, JUMP },
{ "js", JS, JUMP },
{ "jz", JE, JUMP },
{ "lahf", LAHF, WORD },
{ "lar", LAR, WORD },
{ "lds", LDS, WORD },
{ "leal", LEA, WORD },
{ "leave", LEAVE, WORD },
{ "leaw", LEA, OWORD },
{ "les", LES, WORD },
{ "lfs", LFS, WORD },
{ "lgdt", LGDT, WORD },
{ "lgs", LGS, WORD },
{ "lidt", LIDT, WORD },
{ "lldt", LLDT, WORD },
{ "lmsw", LMSW, WORD },
{ "lock", LOCK, WORD },
{ "lods", LODS, WORD },
{ "lodsb", LODS, BYTE },
{ "loop", LOOP, JUMP },
{ "loope", LOOPE, JUMP },
{ "loopne", LOOPNE, JUMP },
{ "loopnz", LOOPNE, JUMP },
{ "loopz", LOOPE, JUMP },
{ "lsl", LSL, WORD },
{ "lss", LSS, WORD },
{ "ltr", LTR, WORD },
{ "movb", MOV, BYTE },
{ "movl", MOV, WORD },
{ "movsb", MOVS, BYTE },
{ "movsbl", MOVSXB, WORD },
{ "movsbw", MOVSXB, OWORD },
{ "movsl", MOVS, WORD },
{ "movsw", MOVS, OWORD },
{ "movswl", MOVSX, WORD },
{ "movw", MOV, OWORD },
{ "movzbl", MOVZXB, WORD },
{ "movzbw", MOVZXB, OWORD },
{ "movzwl", MOVZX, WORD },
{ "mulb", MUL, BYTE },
{ "mull", MUL, WORD },
{ "mulw", MUL, OWORD },
{ "negb", NEG, BYTE },
{ "negl", NEG, WORD },
{ "negw", NEG, OWORD },
{ "nop", NOP, WORD },
{ "notb", NOT, BYTE },
{ "notl", NOT, WORD },
{ "notw", NOT, OWORD },
{ "orb", OR, BYTE },
{ "orl", OR, WORD },
{ "orw", OR, OWORD },
{ "outb", OUT, BYTE },
{ "outl", OUT, WORD },
{ "outsb", OUTS, BYTE },
{ "outsl", OUTS, WORD },
{ "outsw", OUTS, OWORD },
{ "outw", OUT, OWORD },
{ "pop", POP, WORD },
{ "popa", POPA, WORD },
{ "popad", POPA, WORD },
{ "popf", POPF, WORD },
{ "popl", POP, WORD },
{ "push", PUSH, WORD },
{ "pusha", PUSHA, WORD },
{ "pushad", PUSHA, WORD },
{ "pushf", PUSHF, WORD },
{ "pushl", PUSH, WORD },
{ "rclb", RCL, BYTE },
{ "rcll", RCL, WORD },
{ "rclw", RCL, OWORD },
{ "rcrb", RCR, BYTE },
{ "rcrl", RCR, WORD },
{ "rcrw", RCR, OWORD },
{ "ret", RET, JUMP },
{ "retf", RETF, JUMP },
{ "rolb", ROL, BYTE },
{ "roll", ROL, WORD },
{ "rolw", ROL, OWORD },
{ "rorb", ROR, BYTE },
{ "rorl", ROR, WORD },
{ "rorw", ROR, OWORD },
{ "sahf", SAHF, WORD },
{ "salb", SAL, BYTE },
{ "sall", SAL, WORD },
{ "salw", SAL, OWORD },
{ "sarb", SAR, BYTE },
{ "sarl", SAR, WORD },
{ "sarw", SAR, OWORD },
{ "sbbb", SBB, BYTE },
{ "sbbl", SBB, WORD },
{ "sbbw", SBB, OWORD },
{ "scasb", SCAS, BYTE },
{ "scasl", SCAS, WORD },
{ "scasw", SCAS, OWORD },
{ "seta", SETA, BYTE },
{ "setae", SETAE, BYTE },
{ "setb", SETB, BYTE },
{ "setbe", SETBE, BYTE },
{ "sete", SETE, BYTE },
{ "setg", SETG, BYTE },
{ "setge", SETGE, BYTE },
{ "setl", SETL, BYTE },
{ "setna", SETBE, BYTE },
{ "setnae", SETB, BYTE },
{ "setnb", SETAE, BYTE },
{ "setnbe", SETA, BYTE },
{ "setne", SETNE, BYTE },
{ "setng", SETLE, BYTE },
{ "setnge", SETL, BYTE },
{ "setnl", SETGE, BYTE },
{ "setnle", SETG, BYTE },
{ "setno", SETNO, BYTE },
{ "setnp", SETNP, BYTE },
{ "setns", SETNS, BYTE },
{ "seto", SETO, BYTE },
{ "setp", SETP, BYTE },
{ "sets", SETS, BYTE },
{ "setz", SETE, BYTE },
{ "sgdt", SGDT, WORD },
{ "shlb", SHL, BYTE },
{ "shldl", SHLD, WORD },
{ "shll", SHL, WORD },
{ "shlw", SHL, OWORD },
{ "shrb", SHR, BYTE },
{ "shrdl", SHRD, WORD },
{ "shrl", SHR, WORD },
{ "shrw", SHR, OWORD },
{ "sidt", SIDT, WORD },
{ "sldt", SLDT, WORD },
{ "smsw", SMSW, WORD },
{ "stc", STC, WORD },
{ "std", STD, WORD },
{ "sti", STI, WORD },
{ "stosb", STOS, BYTE },
{ "stosl", STOS, WORD },
{ "stosw", STOS, OWORD },
{ "str", STR, WORD },
{ "subb", SUB, BYTE },
{ "subl", SUB, WORD },
{ "subw", SUB, OWORD },
{ "testb", TEST, BYTE },
{ "testl", TEST, WORD },
{ "testw", TEST, OWORD },
{ "verr", VERR, WORD },
{ "verw", VERW, WORD },
{ "wait", WAIT, WORD },
{ "wbinvd", WBINVD, WORD },
{ "xadd", XADD, WORD },
{ "xchgb", XCHG, BYTE },
{ "xchgl", XCHG, WORD },
{ "xchgw", XCHG, OWORD },
{ "xlat", XLAT, WORD },
{ "xorb", XOR, BYTE },
{ "xorl", XOR, WORD },
{ "xorw", XOR, OWORD },
};
void gnu_parse_init(char *file)
/* Prepare parsing of an GNU assembly file. */
{
tok_init(file, '#');
}
static void zap(void)
/* An error, zap the rest of the line. */
{
token_t *t;
while ((t= get_token(0))->type != T_EOF && t->symbol != ';')
skip_token(1);
}
static mnemonic_t *search_mnem(char *name)
/* Binary search for a mnemonic. (That's why the table is sorted.) */
{
int low, mid, high;
int cmp;
mnemonic_t *m;
low= 0;
high= arraysize(mnemtab)-1;
while (low <= high) {
mid= (low + high) / 2;
m= &mnemtab[mid];
if ((cmp= strcmp(name, m->name)) == 0) return m;
if (cmp < 0) high= mid-1; else low= mid+1;
}
return nil;
}
static expression_t *gnu_get_C_expression(int *pn)
/* Read a "C-like" expression. Note that we don't worry about precedence,
* the expression is printed later like it is read. If the target language
* does not have all the operators (like ~) then this has to be repaired by
* changing the source file. (No problem, you still have one source file
* to maintain, not two.)
*/
{
expression_t *e, *a1, *a2;
token_t *t;
if ((t= get_token(*pn))->symbol == '(') {
/* ( expr ): grouping. */
(*pn)++;
if ((a1= gnu_get_C_expression(pn)) == nil) return nil;
if (get_token(*pn)->symbol != ')') {
parse_err(1, t, "missing )\n");
del_expr(a1);
return nil;
}
(*pn)++;
e= new_expr();
e->operator= '[';
e->middle= a1;
} else
if (t->type == T_WORD || t->type == T_STRING) {
/* Label, number, or string. */
e= new_expr();
e->operator= t->type == T_WORD ? 'W' : 'S';
e->name= allocate(nil, (t->len+1) * sizeof(e->name[0]));
memcpy(e->name, t->name , t->len+1);
e->len= t->len;
(*pn)++;
} else
if (t->symbol == '+' || t->symbol == '-' || t->symbol == '~') {
/* Unary operator. */
(*pn)++;
if ((a1= gnu_get_C_expression(pn)) == nil) return nil;
e= new_expr();
e->operator= t->symbol;
e->middle= a1;
} else {
parse_err(1, t, "expression syntax error\n");
return nil;
}
switch ((t= get_token(*pn))->symbol) {
case '%':
case '+':
case '-':
case '*':
case '/':
case '&':
case '|':
case '^':
case S_LEFTSHIFT:
case S_RIGHTSHIFT:
(*pn)++;
a1= e;
if ((a2= gnu_get_C_expression(pn)) == nil) {
del_expr(a1);
return nil;
}
e= new_expr();
e->operator= t->symbol;
e->left= a1;
e->right= a2;
}
return e;
}
static expression_t *gnu_get_operand(int *pn, int deref)
/* Get something like: $immed, memory, offset(%base,%index,scale), or simpler. */
{
expression_t *e, *offset, *base, *index;
token_t *t;
int c;
if (get_token(*pn)->symbol == '$') {
/* An immediate value. */
(*pn)++;
return gnu_get_C_expression(pn);
}
if (get_token(*pn)->symbol == '*') {
/* Indirection. */
(*pn)++;
if ((offset= gnu_get_operand(pn, deref)) == nil) return nil;
e= new_expr();
e->operator= '(';
e->middle= offset;
return e;
}
if ((get_token(*pn)->symbol == '%')
&& (t= get_token(*pn + 1))->type == T_WORD
&& isregister(t->name)
) {
/* A register operand. */
(*pn)+= 2;
e= new_expr();
e->operator= 'W';
e->name= copystr(t->name);
return e;
}
/* Offset? */
if (get_token(*pn)->symbol != '('
|| get_token(*pn + 1)->symbol != '%') {
/* There is an offset. */
if ((offset= gnu_get_C_expression(pn)) == nil) return nil;
} else {
/* No offset. */
offset= nil;
}
/* (%base,%index,scale) ? */
base= index= nil;
if (get_token(*pn)->symbol == '(') {
(*pn)++;
/* %base ? */
if (get_token(*pn)->symbol == '%'
&& (t= get_token(*pn + 1))->type == T_WORD
&& isregister(t->name)
) {
/* A base register expression. */
base= new_expr();
base->operator= 'B';
base->name= copystr(t->name);
(*pn)+= 2;
}
if (get_token(*pn)->symbol == ',') (*pn)++;
/* %index ? */
if (get_token(*pn)->symbol == '%'
&& (t= get_token(*pn + 1))->type == T_WORD
&& isregister(t->name)
) {
/* A index register expression. */
index= new_expr();
index->operator= '1'; /* for now */
index->name= copystr(t->name);
(*pn)+= 2;
}
if (get_token(*pn)->symbol == ',') (*pn)++;
/* scale ? */
if ((base != nil || index != nil)
&& (t= get_token(*pn))->type == T_WORD
&& strchr("1248", t->name[0]) != nil
&& t->name[1] == 0
) {
if (index == nil) {
/* Base is really an index register. */
index= base;
base= nil;
}
index->operator= t->name[0];
(*pn)++;
}
if (get_token(*pn)->symbol == ')') {
/* Ending paren. */
(*pn)++;
} else {
/* Alas. */
parse_err(1, t, "operand syntax error\n");
del_expr(offset);
del_expr(base);
del_expr(index);
return nil;
}
}
if (base == nil && index == nil) {
if (deref) {
/* Return a lone offset as (offset). */
e= new_expr();
e->operator= '(';
e->middle= offset;
} else {
/* Return a lone offset as is. */
e= offset;
}
} else {
e= new_expr();
e->operator= 'O';
e->left= offset;
e->middle= base;
e->right= index;
}
return e;
}
static expression_t *gnu_get_oplist(int *pn, int deref)
/* Get a comma (or colon for jmpf and callf) separated list of instruction
* operands.
*/
{
expression_t *e, *o1, *o2;
token_t *t;
if ((e= gnu_get_operand(pn, deref)) == nil) return nil;
if ((t= get_token(*pn))->symbol == ',' || t->symbol == ':') {
o1= e;
(*pn)++;
if ((o2= gnu_get_oplist(pn, deref)) == nil) {
del_expr(o1);
return nil;
}
e= new_expr();
e->operator= ',';
e->left= o1;
e->right= o2;
}
return e;
}
static asm86_t *gnu_get_statement(void)
/* Get a pseudo op or machine instruction with arguments. */
{
token_t *t= get_token(0);
asm86_t *a;
mnemonic_t *m;
int n;
int prefix_seen;
int deref;
assert(t->type == T_WORD);
a= new_asm86();
/* Process instruction prefixes. */
for (prefix_seen= 0;; prefix_seen= 1) {
if (strcmp(t->name, "rep") == 0
|| strcmp(t->name, "repe") == 0
|| strcmp(t->name, "repne") == 0
|| strcmp(t->name, "repz") == 0
|| strcmp(t->name, "repnz") == 0
) {
if (a->rep != ONCE) {
parse_err(1, t,
"can't have more than one rep\n");
}
switch (t->name[3]) {
case 0: a->rep= REP; break;
case 'e':
case 'z': a->rep= REPE; break;
case 'n': a->rep= REPNE; break;
}
} else
if (!prefix_seen) {
/* No prefix here, get out! */
break;
} else {
/* No more prefixes, next must be an instruction. */
if (t->type != T_WORD
|| (m= search_mnem(t->name)) == nil
|| m->optype == PSEUDO
) {
parse_err(1, t,
"machine instruction expected after instruction prefix\n");
del_asm86(a);
return nil;
}
break;
}
/* Skip the prefix and extra newlines. */
do {
skip_token(1);
} while ((t= get_token(0))->symbol == ';');
}
/* All the readahead being done upsets the line counter. */
a->line= t->line;
/* Read a machine instruction or pseudo op. */
if ((m= search_mnem(t->name)) == nil) {
parse_err(1, t, "unknown instruction '%s'\n", t->name);
del_asm86(a);
return nil;
}
a->opcode= m->opcode;
a->optype= m->optype;
a->oaz= 0;
if (a->optype == OWORD) {
a->oaz|= OPZ;
a->optype= WORD;
}
switch (a->opcode) {
case IN:
case OUT:
case INT:
deref= 0;
break;
default:
deref= (a->optype >= BYTE);
}
n= 1;
if (get_token(1)->symbol != ';'
&& (a->args= gnu_get_oplist(&n, deref)) == nil) {
del_asm86(a);
return nil;
}
if (get_token(n)->symbol != ';') {
parse_err(1, t, "garbage at end of instruction\n");
del_asm86(a);
return nil;
}
if (!is_pseudo(a->opcode)) {
/* GNU operand order is the other way around. */
expression_t *e, *t;
e= a->args;
while (e != nil && e->operator == ',') {
t= e->right; e->right= e->left; e->left= t;
e= e->left;
}
}
switch (a->opcode) {
case DOT_ALIGN:
/* Delete two argument .align, because ACK can't do it.
* Raise 2 to the power of .align's argument.
*/
if (a->args == nil || a->args->operator != 'W') {
del_asm86(a);
return nil;
}
if (a->args != nil && a->args->operator == 'W'
&& isanumber(a->args->name)
) {
unsigned n;
char num[sizeof(int) * CHAR_BIT / 3 + 1];
n= 1 << strtoul(a->args->name, nil, 0);
sprintf(num, "%u", n);
deallocate(a->args->name);
a->args->name= copystr(num);
}
break;
case JMPF:
case CALLF:
/*FALL THROUGH*/
case JMP:
case CALL:
break;
default:;
}
skip_token(n+1);
return a;
}
asm86_t *gnu_get_instruction(void)
{
asm86_t *a= nil;
expression_t *e;
token_t *t;
while ((t= get_token(0))->symbol == ';' || t->symbol == '/') {
zap(); /* if a comment started by a '/' */
skip_token(1);
}
if (t->type == T_EOF) return nil;
if (t->symbol == '#') {
/* Preprocessor line and file change. */
if ((t= get_token(1))->type != T_WORD || !isanumber(t->name)
|| get_token(2)->type != T_STRING
) {
parse_err(1, t, "file not preprocessed?\n");
zap();
} else {
set_file(get_token(2)->name,
strtol(get_token(1)->name, nil, 0) - 1);
/* GNU CPP adds extra cruft, simply zap the line. */
zap();
}
a= gnu_get_instruction();
} else
if (t->type == T_WORD && get_token(1)->symbol == ':') {
/* A label definition. */
a= new_asm86();
a->line= t->line;
a->opcode= DOT_LABEL;
a->optype= PSEUDO;
a->args= e= new_expr();
e->operator= ':';
e->name= copystr(t->name);
skip_token(2);
} else
if (t->type == T_WORD && get_token(1)->symbol == '=') {
int n= 2;
if ((e= gnu_get_C_expression(&n)) == nil) {
zap();
a= gnu_get_instruction();
} else
if (get_token(n)->symbol != ';') {
parse_err(1, t, "garbage after assignment\n");
zap();
a= gnu_get_instruction();
} else {
a= new_asm86();
a->line= t->line;
a->opcode= DOT_EQU;
a->optype= PSEUDO;
a->args= new_expr();
a->args->operator= '=';
a->args->name= copystr(t->name);
a->args->middle= e;
skip_token(n+1);
}
} else
if (t->type == T_WORD) {
if ((a= gnu_get_statement()) == nil) {
zap();
a= gnu_get_instruction();
}
} else {
parse_err(1, t, "syntax error\n");
zap();
a= gnu_get_instruction();
}
return a;
}

View File

@ -1,107 +0,0 @@
asmprog:
comment ?
statement
asmprog ; asmprog
asmprog comment ? \n asmprog
letter:
[._a-zA-Z]
digit:
[0-9]
identifier:
letter (letter | digit)*
digit [bf]
string:
'C-like string sequence'
"C-like string sequence"
number:
C-like number
comment:
! .*
statement:
label-definition statement
empty
assignment
instruction
pseudo-instruction
label-definition:
identifier :
digit :
assignment:
identifier = expression
instruction:
iX86-instruction
pseudo-instruction:
.extern identifier (, identifier)*
.define identifier (, identifier)*
.data1 expression (, expression)*
.data2 expression (, expression)*
.data4 expression (, expression)*
.ascii string
.asciz string
.align expression
.space expression
.comm identifier , expression
.sect identifier
.base expression
.assert expression
.symb XXX
.line XXX
.file XXX
.nolist
.list
iX86-pseudo
expression:
C-like expression with [ and ] for grouping
iX86-instruction:
prefix
prefix iX86-instruction
identifier
identifier iX86operand
identifier iX86operand , iX86operand
identifier iX86operand : iX86operand
prefix:
o16
o32
a16
a32
rep
repz
repnz
repe
repne
cseg | dseg | eseg | fseg | gseg | sseg
iX86operand:
register
( register )
expression
( expression )
expression ( register )
expression ( register * [1248] )
expression ? ( register ) ( register )
expression ? ( register ) ( register * [1248] )
register:
al | bl | cl | dl | ah | bh | ch | dh
ax | bx | cx | dx | si | di | bp | sp
eax | ebx | ecx | edx | esi | edi | ebp | esp
cs | ds | es | fs | gs | ss
cr0 | cr1 | cr2 | cr3
iX86-pseudo:
.use16
.use32

View File

@ -1,29 +0,0 @@
/* token.h - token definition Author: Kees J. Bot
* 13 Dec 1993
*/
typedef enum toktype {
T_EOF,
T_CHAR,
T_WORD,
T_STRING
} toktype_t;
typedef struct token {
struct token *next;
long line;
toktype_t type;
int symbol; /* Single character symbol. */
char *name; /* Word, number, etc. */
size_t len; /* Length of string. */
} token_t;
#define S_LEFTSHIFT 0x100 /* << */
#define S_RIGHTSHIFT 0x101 /* >> */
void set_file(char *file, long line);
void get_file(char **file, long *line);
void parse_err(int err, token_t *where, const char *fmt, ...);
void tok_init(char *file, int comment);
token_t *get_token(int n);
void skip_token(int n);

View File

@ -1,306 +0,0 @@
/* tokenize.c - split input into tokens Author: Kees J. Bot
* 13 Dec 1993
*/
#define nil 0
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "asmconv.h"
#include "token.h"
static FILE *tf;
static char *tfile;
static char *orig_tfile;
static int tcomment;
static int tc;
static long tline;
static token_t *tq;
static void readtc(void)
/* Read one character from the input file and put it in the global 'tc'. */
{
static int nl= 0;
if (nl) tline++;
if ((tc= getc(tf)) == EOF && ferror(tf)) fatal(orig_tfile);
nl= (tc == '\n');
}
void set_file(char *file, long line)
/* Set file name and line number, changed by a preprocessor trick. */
{
deallocate(tfile);
tfile= allocate(nil, (strlen(file) + 1) * sizeof(tfile[0]));
strcpy(tfile, file);
tline= line;
}
void get_file(char **file, long *line)
/* Get file name and line number. */
{
*file= tfile;
*line= tline;
}
void parse_err(int err, token_t *t, const char *fmt, ...)
/* Report a parsing error. */
{
va_list ap;
fprintf(stderr, "\"%s\", line %ld: ", tfile,
t == nil ? tline : t->line);
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
if (err) set_error();
}
void tok_init(char *file, int comment)
/* Open the file to tokenize and initialize the tokenizer. */
{
if (file == nil) {
file= "stdin";
tf= stdin;
} else {
if ((tf= fopen(file, "r")) == nil) fatal(file);
}
orig_tfile= file;
set_file(file, 1);
readtc();
tcomment= comment;
}
static int isspace(int c)
{
return between('\0', c, ' ') && c != '\n';
}
#define iscomment(c) ((c) == tcomment)
static int isidentchar(int c)
{
return between('a', c, 'z')
|| between('A', c, 'Z')
|| between('0', c, '9')
|| c == '.'
|| c == '_'
;
}
static token_t *new_token(void)
{
token_t *new;
new= allocate(nil, sizeof(*new));
new->next= nil;
new->line= tline;
new->name= nil;
new->symbol= -1;
return new;
}
static token_t *get_word(void)
/* Read one word, an identifier, a number, a label, or a mnemonic. */
{
token_t *w;
char *name;
size_t i, len;
i= 0;
len= 16;
name= allocate(nil, len * sizeof(name[0]));
while (isidentchar(tc)) {
name[i++]= tc;
readtc();
if (i == len) name= allocate(name, (len*= 2) * sizeof(name[0]));
}
name[i]= 0;
name= allocate(name, (i+1) * sizeof(name[0]));
w= new_token();
w->type= T_WORD;
w->name= name;
w->len= i;
return w;
}
static token_t *get_string(void)
/* Read a single or double quotes delimited string. */
{
token_t *s;
int quote;
char *str;
size_t i, len;
int n, j;
int seen;
quote= tc;
readtc();
i= 0;
len= 16;
str= allocate(nil, len * sizeof(str[0]));
while (tc != quote && tc != '\n' && tc != EOF) {
seen= -1;
if (tc == '\\') {
readtc();
if (tc == '\n' || tc == EOF) break;
switch (tc) {
case 'a': tc= '\a'; break;
case 'b': tc= '\b'; break;
case 'f': tc= '\f'; break;
case 'n': tc= '\n'; break;
case 'r': tc= '\r'; break;
case 't': tc= '\t'; break;
case 'v': tc= '\v'; break;
case 'x':
n= 0;
for (j= 0; j < 3; j++) {
readtc();
if (between('0', tc, '9'))
tc-= '0' + 0x0;
else
if (between('A', tc, 'A'))
tc-= 'A' + 0xA;
else
if (between('a', tc, 'a'))
tc-= 'a' + 0xa;
else {
seen= tc;
break;
}
n= n*0x10 + tc;
}
tc= n;
break;
default:
if (!between('0', tc, '9')) break;
n= 0;
for (j= 0; j < 3; j++) {
if (between('0', tc, '9'))
tc-= '0';
else {
seen= tc;
break;
}
n= n*010 + tc;
readtc();
}
tc= n;
}
}
str[i++]= tc;
if (i == len) str= allocate(str, (len*= 2) * sizeof(str[0]));
if (seen < 0) readtc(); else tc= seen;
}
if (tc == quote) {
readtc();
} else {
parse_err(1, nil, "string contains newline\n");
}
str[i]= 0;
str= allocate(str, (i+1) * sizeof(str[0]));
s= new_token();
s->type= T_STRING;
s->name= str;
s->len= i;
return s;
}
static int old_n= 0; /* To speed up n, n+1, n+2, ... accesses. */
static token_t **old_ptq= &tq;
token_t *get_token(int n)
/* Return the n-th token on the input queue. */
{
token_t *t, **ptq;
assert(n >= 0);
if (0 && n >= old_n) {
/* Go forward from the previous point. */
n-= old_n;
old_n+= n;
ptq= old_ptq;
} else {
/* Restart from the head of the queue. */
old_n= n;
ptq= &tq;
}
for (;;) {
if ((t= *ptq) == nil) {
/* Token queue doesn't have element <n>, read a
* new token from the input stream.
*/
while (isspace(tc) || iscomment(tc)) {
if (iscomment(tc)) {
while (tc != '\n' && tc != EOF)
readtc();
} else {
readtc();
}
}
if (tc == EOF) {
t= new_token();
t->type= T_EOF;
} else
if (isidentchar(tc)) {
t= get_word();
} else
if (tc == '\'' || tc == '"') {
t= get_string();
} else {
if (tc == '\n') tc= ';';
t= new_token();
t->type= T_CHAR;
t->symbol= tc;
readtc();
if (t->symbol == '<' && tc == '<') {
t->symbol= S_LEFTSHIFT;
readtc();
} else
if (t->symbol == '>' && tc == '>') {
t->symbol= S_RIGHTSHIFT;
readtc();
}
}
*ptq= t;
}
if (n == 0) break;
n--;
ptq= &t->next;
}
old_ptq= ptq;
return t;
}
void skip_token(int n)
/* Remove n tokens from the input queue. One is not allowed to skip unread
* tokens.
*/
{
token_t *junk;
assert(n >= 0);
while (n > 0) {
assert(tq != nil);
junk= tq;
tq= tq->next;
deallocate(junk->name);
deallocate(junk);
n--;
}
/* Reset the old reference. */
old_n= 0;
old_ptq= &tq;
}

View File

@ -1,4 +0,0 @@
SCRIPTS= binpackage.sh
MAN=
.include <bsd.prog.mk>

View File

@ -1,78 +0,0 @@
#!/bin/sh
PATH=/bin:/sbin:/usr/bin:/usr/sbin
PI=.postinstall
INFO=.minixpackage
set -e
# No trailing slashes in the directory, because we want to base the
# package filename on it.
dir=`echo "$1" | sed 's/\/*$//'`
if [ $# -ne 2 ]
then echo "Usage: $0 sourcedir packagedir"
exit 1
fi
if [ ! -d "$dir" ]
then echo "Error: $dir isn't a directory."
exit 1
fi
here=`pwd`
case "$dir" in
/*) srcdir="$dir" ;;
*) srcdir="$here/$dir" ;;
esac
case $2 in
/*) pdir="$2" ;;
*) pdir="$here/$2" ;;
esac
packagestart=$srcdir/now
findlist=$srcdir/findlist
tar=$srcdir/"`basename ${dir}`".tar
tarbz=$tar.bz2
mkdir $pdir 2>/dev/null || true
rc=$dir/.binpackage
if [ -f $rc ]
then . $rc
fi
prunedirs="$srcdir dev tmp usr/bigports usr/src usr/tmp usr/log usr/adm usr/run home etc/utmp var/run var/log /var/spool"
for d in $prunedirs
do pruneexpr="$pruneexpr $n -path /$d -prune"
n="-o "
done
touch $packagestart
sleep 1
cd $dir
if [ ! -f build -a ! -f build.minix ]
then echo "Error: No build or build.minix script in $dir."
exit 1
fi
if [ -f build.minix ]
then sh -e build.minix
else sh -e build
fi
echo " * Building package"
echo "Minix package $dir built `date`." >$INFO
(
echo $INFO
if [ -f $PI ]
then echo $PI
fi
find / \( $pruneexpr \) -o -cnewer $packagestart -print | fgrep -v /.svn
) | pax -w -d | bzip2 >$tarbz
rm -f $packagestart $findlist $tarcmd
mv $tarbz $pdir
exit 0

View File

@ -1,4 +0,0 @@
SCRIPTS= binpackages.sh
MAN=
.include <bsd.prog.mk>

View File

@ -1,13 +0,0 @@
#!/bin/sh
pdir=Packages
for d in */build
do
dir="`echo $d | sed 's/\/build$//'`"
if [ ! -f $pdir/$dir.tar.gz ]
then
echo " * $dir"
binpackage $dir $pdir
fi
done

View File

@ -1,4 +0,0 @@
PROG= chmem
MAN=
.include <bsd.prog.mk>

View File

@ -1,148 +0,0 @@
/* chmem - set total memory size for execution Author: Andy Tanenbaum */
#include <minix/config.h>
#include <sys/types.h>
#include <a.out.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#define MAX_8086 0x10000L /* maximum allocation size for 8086 */
#define MAX_386 0x7FFFFFFFL /* etc */
#define MAX_68K 0x7FFFFFFFL
#define MAX_SPARC 0x20000000L /* No more than 512MB on a SparcStation! */
char *progname;
_PROTOTYPE(int main, (int argc, char **argv));
_PROTOTYPE(void error, (char *s1, char *s2));
_PROTOTYPE(void usage, (void));
int main(argc, argv)
int argc;
char *argv[];
{
/* The 8088 architecture does not make it possible to catch stacks that grow
* big. The only way to deal with this problem is to let the stack grow down
* towards the data segment and the data segment grow up towards the stack.
* Normally, a total of 64K is allocated for the two of them, but if the
* programmer knows that a smaller amount is sufficient, he can change it
* using chmem.
*
* chmem =4096 prog sets the total space for stack + data growth to 4096
* chmem +200 prog increments the total space for stack + data growth by 200
*/
char *p;
int fd = -1, separate;
size_t s;
long lsize, olddynam, newdynam, newtot, overflow;
struct exec exec;
char cpu;
long max;
int last_failed = 0, any_failed = 0;
progname = argv[0];
if (argc < 3) usage();
p = argv[1];
if (*p != '=' && *p != '+' && *p != '-') usage();
lsize = atol(p + 1);
s = sizeof(struct exec);
if (lsize < 0) {
error(p + 1, "is negative");
exit(1);
}
argc -= 1;
argv += 1;
while (--argc) {
if(last_failed) any_failed = 1;
/* Unless we reach the end of this loop, this one failed. */
last_failed = 1;
++argv;
if(fd != -1) close(fd);
fd = open(*argv, O_RDWR);
if (fd < 0) {
error("can't open", *argv);
continue;
}
if (read(fd, (char *) &exec, s) != s) {
error("can't read header in", *argv);
continue;
}
if (BADMAG(exec)) {
error(*argv, "is not executable");
continue;
}
separate = (exec.a_flags & A_SEP ? 1 : 0);
cpu = exec.a_cpu;
#if (CHIP == M68000)
if (cpu == A_I8086) cpu = A_M68K;
#endif
switch (cpu) {
case A_I8086: max = MAX_8086; break;
case A_I80386: max = MAX_386; break;
case A_M68K: max = MAX_68K; break;
case A_SPARC: max = MAX_SPARC; break;
default:
error("bad CPU type in", *argv);
continue;
}
if (lsize > max) {
error("size is too large for", *argv);
continue;
}
olddynam = exec.a_total - exec.a_data - exec.a_bss;
if (separate == 0) olddynam -= exec.a_text;
if (*p == '=')
newdynam = lsize;
else if (*p == '+')
newdynam = olddynam + lsize;
else if (*p == '-')
newdynam = olddynam - lsize;
newtot = exec.a_data + exec.a_bss + newdynam;
if (separate == 0) newtot += exec.a_text;
overflow = (newtot > max ? newtot - max : 0);
newdynam -= overflow;
newtot -= overflow;
exec.a_total = newtot;
lseek(fd, (long) 0, SEEK_SET);
if (write(fd, (char *) &exec, s) != s) {
error("can't modify", *argv);
continue;
}
printf("%s: Stack+malloc area changed from %ld to %ld bytes.\n",
*argv, olddynam, newdynam);
/* This one didn't fail. */
last_failed = 0;
}
return(any_failed || last_failed ? 1 : 0);
}
void error(s1, s2)
char *s1;
char *s2;
{
fprintf(stderr, "%s: %s ", progname, s1);
if (errno != 0)
perror(s2);
else
fprintf(stderr, "%s\n", s2);
errno = 0;
}
void usage()
{
fprintf(stderr, "Usage: %s {=+-} amount file\n", progname);
exit(1);
}

View File

@ -3,12 +3,7 @@
PROG= cut
.if ${COMPILER_TYPE} != "gnu"
LDADD+= -lminixutil
DPADD+= ${LIBMINIXUTIL}
.else
LDADD+= -lutil
DPADD+= ${LIBUTIL}
.endif
.include <bsd.prog.mk>

View File

@ -1,11 +0,0 @@
.include <bsd.own.mk>
PROG= date
SRCS= date.c logwtmp.c
TZDIR= /usr/share/zoneinfo
CPPFLAGS+= -DHAVE_ADJTIME=0 -DTZDIR=\"$(TZDIR)\"
BINDIR= /bin
.PATH: ${MINIXSRCDIR}/lib/libc/stdtime
.include <bsd.prog.mk>

View File

@ -1,9 +0,0 @@
# Makefile for dis386
PROGS= dis386e dis386o
SRCS.dis386e=dise.c misc.c unasm.c
SRCS.dis386o=diso.c misc.c unasm.c
MAN.dis386e=
MAN.dis386o=
.include <bsd.prog.mk>

View File

@ -1,56 +0,0 @@
/* const.h - constants for db.
*
* $Id: const.h,v 1.0 1990/10/06 12:00:00 cwr Exp cwr $
*/
/* general constants */
#define FALSE 0
#undef NULL
#define NULL 0
#define TRUE 1
/* C tricks */
#define EXTERN extern
#define FORWARD static
#define PRIVATE static
#define PUBLIC
/* ASCII codes */
#define CAN 24
#define CR 13
#define EOF (-1)
#define LF 10
#define XOFF 19
/* hardware processor-specific for 8088 through 80386 */
#ifndef HCLICK_SIZE
#define HCLICK_SIZE 0x10
#endif
#define IF 0x0200 /* interrupt disable bit in flags */
#define INT_BREAKPOINT 0xCC /* byte for breakpoint interrupt */
#define LINEARADR(seg, off) \
(HCLICK_SIZE * (physoff_t) (segment_t) (seg) + (off))
#define TF 0x0100 /* trap bit in flags */
/* hardware processor-specific for 80386 and emulated for others */
#define BS 0x4000 /* single-step bit in dr6 */
/* use hardware codes for segments for simplest decoding */
#define CSEG 0x2E /* 8088 through 80386 */
#define DSEG 0x3E
#define ESEG 0x26
#define FSEG 0x64
#define GSEG 0x65 /* 80386 only */
#define SSEG 0x36
/* software machine-specific for PC family */
#define BIOS_DATA_SEG 0x40
# define KB_FLAG 0x17 /* offset to 16-bits of keyboard shift flags */
/* switches to handle non-conforming compilers */
#define UCHAR_BUG /* compiler converts unsigned chars wrong */
#ifdef UCHAR_BUG
# define UCHAR(x) ((x) & 0xFF)
#endif

Some files were not shown because too many files have changed in this diff Show More