Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP
Posting-Version: version B 2.10.2 9/18/84; site ut-sally.UUCP
Path: utzoo!watmath!clyde!burl!ulysses!gamma!epsilon!zeta!sabre!bellcore!decvax!genrad!panda!talcott!harvard!ut-sally!brian
From: brian@ut-sally.UUCP (Brian H. Powell)
Newsgroups: net.sources.mac
Subject: New SUMacC rmaker.shar
Message-ID: <2287@ut-sally.UUCP>
Date: Sun, 7-Jul-85 19:45:29 EDT
Article-I.D.: ut-sally.2287
Posted: Sun Jul 7 19:45:29 1985
Date-Received: Thu, 11-Jul-85 00:37:18 EDT
Distribution: net
Organization: U. Texas CS Dept., Austin, Texas
Lines: 1994
# This is a shell archive. Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by ut-sally!brian on Sun Jul 7 00:06:04 CDT 1985
# Contents: README rmaker.c rmaker.1 rmaker.doc crtdrvr.s crtproc.s
echo x - README
sed 's/^@//' > "README" <<'@//E*O*F README//'
As some of you have noticed, there is more than one version of the
SUMacC rmaker out there. This is an attempt to combine all versions.
Summary of changes to rmaker:
Work done by Croft:
fix fwrite bug and add INIT and PACK resource types.
Work done by Maio/Schilit:
no NULL in DRVR name if device driver.
Work done by Moy:
Implement CDEF, MDEF, WDEF and modify DRVR for dynamic relocation.
Work done by van Rossum:
Added STR# resource types.
Work done by Crosswell:
Added POST (PostScript) resource type.
Work done by Horvath:
Added backslash escape sequences for strings.
Work done by Powell:
Combine all of above work.
Modify INIT and PACK to use dynamic relocation.
Added FKEY and PROC resource types.
Fix minor bugs in backslash code.
_______________________________________________________________________________
The dynamic relocation work done by Moy requires the use of special
crt*.s files for DRVR, PROC, CDEF, MDEF, WDEF, INIT, PACK and FKEY types.
For DRVR's, use crtdrvr.s (which is included in the shar file) as an example.
For the others, use crtproc.s (also included) as an example.
@//E*O*F README//
chmod u=r,g=r,o=r README
echo x - rmaker.c
sed 's/^@//' > "rmaker.c" <<'@//E*O*F rmaker.c//'
/* rmaker.c 1.0 04/11/84 */
/*
* Resource compiler.
*/
/*
* Copyright (C) 1984, Stanford Univ. SUMEX project.
* May be used but not sold without permission.
*/
/*
* history
* 04/11/84 Croft Created.
* 04/16/84 Croft Reloc info now imbedded in long addresses.
* 06/18/84 Schilit Added DITL and ALRT.
* 07/06/84 Croft Added DLOG WIND MENU CNTL ICON ICN# CURS PAT.
* 07/21/84 Croft Added DRVR; multiple code segs (jks).
* 07/26/84 Schuster Added resource names.
*** Branch 1
* 01/10/85 Moy Implement [CMW]DEF. These and DRVR use dynamic
* relocation scheme.
*** Branch 2
* 09/18/84 Croft Fixed fwrite bug for resource names.
* 11/06/84 Croft Added INIT and PACK.
* 11/11/84 Maio/Schilit no NULL in DRVR name if device driver.
*** Branch 3
* 06/25/85 GvR Added STR#.
* 06/26/85 Crosswell Added POST (PostScript resource in
* Laser Prep file)
* 07/06/85 Horvath Add Backslash escapes in strings.
*** Reunion
* 06/27/85 Powell Combined branches 1, 2 and 3.
* 06/27/85 Powell Modify INIT and PACK to use dynamic relocation.
* 06/27/85 Powell Added FKEY.
* 06/29/85 Powell Added PROC.
* 07/06/85 Powell Fix tolower bug in backslash code.
Limit \ooo to three digits, \xhh to two.
*/
#include
#include
#include
#include
#include
#include
#define bh filhdr
struct bhdr bh; /* b.out header */
char *malloc();
char *index();
char *rindex();
unsigned short htons(); /* host to "net" byte order, short. */
unsigned long htonl();
char seg0[sizeof(struct jumphead) + sizeof(struct jumptab)] = {
0,0,0,0x28, 0,0,2,0, 0,0,0,8, 0,0,0,0x20,
0,0, 0x3F,0x3C, 0,1, 0xA9,0xF0
}; /* "standard" segment 0 jump header/table */
char seg1[sizeof(struct codehead)] = { 0,0, 0,1 };
#define CRTMAGIC 0x602C /* jump at beginning of crtmac.s */
#define CRTLEN 10 /* length of relocation table in crtmac.s */
#define RELMAGIC 0x6034 /* jump at beginning of crt*.s */
#define RELLEN 12 /* length of relocation table in crt*.s */
#define NRESCOMP 50 /* max number of resources per compile */
struct rescomp { /* resource being compiled */
char rc_type[8]; /* resource type (e.g. "CODE") */
char *rc_name; /* resource name */
int rc_id; /* resource id number */
int rc_att; /* attributes */
int rc_length; /* length in resource file */
char *rc_data; /* pointer to data */
int rc_datalen; /* length of data */
FILE *rc_file; /* file to read data from */
int rc_filelen; /* length of data in file */
int rc_bss; /* number of zero pad bytes */
char *rc_rel; /* relocation info */
int rc_rellen; /* length of relocation info */
} rescomp[NRESCOMP], *rcp;
struct resfile rf; /* compiled resource file header */
struct resmap rm; /* compiled resource map header */
struct restype rt[NRESCOMP]; /* compiled resource type list */
struct resid ri[NRESCOMP]; /* compiled resource id list */
#define NAMELEN 1024
char rn[NAMELEN]; /* compiled resource name list */
char debugtype[8]; /* debug type switch */
FILE *fout; /* file for compiler output */
FILE *fin; /* file for compiler commands */
char fineof; /* true after all commands read */
char line[256]; /* line buffer */
char *lp; /* current position in line */
int linenum; /* line number in command file */
char *relpnt; /* current position in longrun area */
char *relrel; /* current position in reloc area */
int rellen; /* length of longrun area */
int reloff; /* current relocation offset */
char token[128]; /* current token being parsed */
char data[8*1024]; /* area to build simple resource data */
char *datap; /* pointer to data area */
/* type format handlers */
extern handstr(), handhexa(), handcode(), handdrvr(), handproc();
extern handdlog(), handalrt(), handditl();
extern handwind(), handmenu(), handcntl(), handinit();
extern handstrl(), handpost();
struct typehand { /* type string to handler table */
char th_type[8]; /* e.g. "CODE" */
int (*th_handler)(); /* format handler function */
} typehand[] = {
"STR ", handstr,
"STR#", handstrl,
"HEXA", handhexa,
"CODE", handcode,
"DRVR", handdrvr,
"INIT", handproc,
"PACK", handproc,
"ALRT", handalrt,
"DITL", handditl,
"DLOG", handdlog,
"WIND", handwind,
"MENU", handmenu,
"CNTL", handcntl,
"ICON", handhexa,
"ICN#", handhexa,
"CURS", handhexa,
"PAT ", handhexa,
"CDEF", handproc,
"MDEF", handproc,
"WDEF", handproc,
"POST", handpost,
"FKEY", handproc,
"PROC", handproc,
0, 0
};
main(argc, argv)
char **argv;
{
for (argc--,argv++ ; argc > 0 ; argc--,argv++) {
if (argv[0][0] != '-')
break;
switch (argv[0][1]) {
case 'd':
argc--,argv++;
if (argc < 1) abort("syntax: -d TYPE");
strcpy(debugtype,argv[0]);
break;
}
}
if (argc != 1)
abort("usage: rmaker commandfilename");
if ((fin = fopen(argv[0], "r")) == NULL)
abort("can't open commandfile");
rmaker();
buildrf(); /* build resource file from rescomp */
exit(0);
}
rmaker()
{
register i;
char infile[32], *ip;
struct typehand *thp;
int haveoutfile = 0;
int items, id, att;
char littype[32], type[32], format[32];
rcp = &rescomp[0];
while (fineof == 0) {
if (getline() == 0)
continue; /* skip blank lines */
if (haveoutfile == 0) { /* if output file not yet open */
if ((fout = fopen(lp, "w")) == NULL)
abort("can't open output file %s", lp);
haveoutfile++;
continue;
}
littype[0] = type[0] = 0;
items = sscanf(lp, "%s %s = %s", littype, type, format);
if (items < 2 || strcmp(littype, "Type") != 0)
abort("bad Type line");
checktype(type);
strcpy(rcp->rc_type, type);
if (items == 3) {
checktype(format);
strcpy(type, format);
}
if (getline() == 0)
abort("bad id");
if (skipsp() == 0)
abort("bad id");
for (i=0 ; *lp != ',' && *lp != 0 ; lp++,i++)
infile[i] = *lp;
infile[i] = 0;
if (*lp != ',')
abort("bad id");
lp++;
id = att = 0;
items = sscanf(lp, " %d(%d) ", &id, &att);
ip = index(infile, '|');
if (ip) {
*ip++ = 0;
if ((rcp->rc_name = malloc(strlen(ip) + 1)) == 0)
abort("name malloc");
strcpy(rcp->rc_name, ip);
} else
rcp->rc_name = 0;
if (items < 1)
abort("bad id");
if (strlen(infile)) {
if ((rcp->rc_file = fopen(infile, "r")) == NULL)
abort("can't open input file %s", infile);
} else {
rcp->rc_file = 0;
}
rcp->rc_id = id;
rcp->rc_att = att;
/* search for type handler */
for (thp = &typehand[0] ; ; thp++) {
if (thp->th_handler == 0)
abort("type %s not implemented", type);
if (strcmp(thp->th_type, type) == 0)
break;
}
datap = data;
(*thp->th_handler)();
if (datap != data) {
int len = datap - data;
if (len & 1) {
len++;
*datap++ = 0;
}
if ((rcp->rc_data = malloc(len)) == 0)
abort("data malloc");
bcopy(data, rcp->rc_data, len);
rcp->rc_datalen = rcp->rc_length = len;
}
if (strcmp(type, debugtype) == 0)
printrcp();
rcp++;
if ((rcp - &rescomp[0]) > NRESCOMP - 3)
abort("too many resources");
}
if (rcp == &rescomp[0] || fout == 0)
abort("nothing to do");
}
/*
* Build resource file output from incore rescomp structure.
*/
buildrf()
{
register struct rescomp *rcpp;
register struct resid *rip;
register struct restype *rtp;
register char *rnp;
struct restype *rtpp;
int offdata, roundtomap, sizetypes, sizemap;
register i;
register char *cp;
numtypes_t numtypes;
lendata_t lendata;
/* XXX TODO: before scanning, sort rescomp by type/id */
rtp = &rt[0];
rip = &ri[0];
rnp = rn;
rcpp = &rescomp[0];
offdata = 0;
/*
* Scan through the resources making type and id lists. In this
* 1st pass, the rt_offids field is set to the offset from the
* start of the id's list. Below, the 2nd pass adds the size
* of the type list to this field.
*/
bcopy(rcpp->rc_type, rtp->rt_type, 4); /* preset 1st type */
for ( ; rcpp < rcp ; rcpp++) {
if (strncmp(rcpp->rc_type, rtp->rt_type, 4) != 0) {
rtp++; /* we've found a new type */
bcopy(rcpp->rc_type, rtp->rt_type, 4);
rtp->rt_offids = (rip - &ri[0]) * sizeof *rip;
}
rtp->rt_numids++;
rip->ri_id = htons(rcpp->rc_id); /* ensure final byte order */
if (rcpp->rc_name) {
rip->ri_offname = htons(rnp - rn);
i = strlen(rcpp->rc_name);
if (((rnp - rn) + i + 2) > NAMELEN)
abort("namemap exhausted");
/*
* desk accessories start with null, device
* drivers start with '.'.
*/
if (strncmp(rcpp->rc_type, "DRVR", 4) == 0
&& rcpp->rc_name[0] != '.') {
*rnp++ = (char)(i + 1);
*rnp++ = 0;
} else {
*rnp++ = (char) i;
}
bcopy(rcpp->rc_name, rnp, i);
rnp += i;
}
else
rip->ri_offname = htons(-1);
rip->ri_att = rcpp->rc_att;
rip->ri_offdata = htons(offdata & 0xFFFF);
rip->ri_offdatahi = ((offdata >> 16) & 0xFF);
rip++;
offdata += (rcpp->rc_length + sizeof lendata);
}
rtp++;
/*
* Write the file header and pad it out.
*/
rf.rf_offdata = htonl(OFFDATA);
offdata += OFFDATA;
roundtomap = (offdata & (ROUNDMAP-1));
if (roundtomap)
roundtomap = ROUNDMAP - roundtomap; /* # of pad bytes */
rf.rf_offmap = offdata + roundtomap;
rf.rf_lendata = htonl(rf.rf_offmap - OFFDATA);
rf.rf_offmap = htonl(rf.rf_offmap);
sizetypes = ((numtypes = rtp - &rt[0]) * sizeof *rtp);
if ((rnp - rn) & 1) /* to be conservative */
*rnp++ = 0;
sizemap = sizeof rm + sizetypes + sizeof numtypes
+ ((rip - &ri[0]) * sizeof *rip) + (rnp - rn);
rf.rf_lenmap = htonl(sizemap);
fwrite(&rf, sizeof rf, 1, fout);
i = OFFDATA - sizeof rf;
do { putc(0, fout); } while (--i);
/*
* correct type list.
*/
for (rtpp = &rt[0] ; rtpp < rtp ; rtpp++) {
rtpp->rt_offids = htons(rtpp->rt_offids
+ sizetypes + sizeof numtypes);
rtpp->rt_numids = htons(rtpp->rt_numids - 1);
}
/*
* For each resource, write data, file, and bss.
*/
for (rcpp = &rescomp[0] ; rcpp < rcp ; rcpp++) {
lendata = htonl(rcpp->rc_length);
fwrite(&lendata, sizeof lendata, 1, fout);
if ((cp = rcpp->rc_data))
for (i = rcpp->rc_datalen ; i > 0 ; i--)
putc(*cp++, fout);
if (rcpp->rc_file)
for (i = rcpp->rc_filelen ; i > 0 ; i--)
putc(getc(rcpp->rc_file), fout);
for (i = rcpp->rc_bss ; i > 0 ; i--)
putc(0, fout);
if ((cp = rcpp->rc_rel))
for (i = rcpp->rc_rellen ; i > 0 ; i--)
putc(*cp++, fout);
}
for (i = roundtomap ; i > 0 ; i--)
putc(0, fout);
/*
* Write the resource map.
*/
rm.rm_offtype = htons(sizeof rm);
rm.rm_offname = htons(sizemap - (rnp - rn));
fwrite(&rm, sizeof rm, 1, fout);
numtypes--;
numtypes = htons(numtypes);
fwrite(&numtypes,sizeof numtypes, 1, fout);
fwrite(&rt[0], sizeof *rtp, rtp - &rt[0], fout);
fwrite(&ri[0], sizeof *rip, rip - &ri[0], fout);
if (rnp - rn)
fwrite(rn, rnp - rn, 1, fout);
}
/*
* Get next command line.
* Returns 0 if end of block, 1 if normal line.
*/
getline()
{
register i;
again:
if ((fgets(line, sizeof line, fin)) == NULL) {
fineof++;
return (0);
}
linenum++;
if ((i = strlen(line)) <= 0)
return (0);
if (line[i-1] == '\n')
line[i-1] = 0;
lp = line;
if (*lp == 0)
return (0);
if (*lp == '*')
goto again;
return (1);
}
/*
* Abort with message.
*/
abort(s,a,b)
char *s;
{
fprintf(stderr, "rmaker: ");
fprintf(stderr, s, a, b);
if (linenum)
fprintf(stderr, "; line number %d", linenum);
fprintf(stderr, "\n");
exit(1);
}
/*
* Check for legal length type. Fix "STR ".
*/
checktype(s)
char *s;
{
register len;
len = strlen(s);
if (len < 3 || len > 4)
abort("bad type");
if (len == 3) {
s[3] = ' ';
s[4] = 0;
}
}
/*
* Copy bytes.
*/
bcopy(a, b, n)
register n;
register char *a, *b;
{
if (n <= 0)
return;
do { *b++ = *a++; } while (--n);
}
/*
* Store a short into the data area.
*/
datashort(i)
{
*(unsigned short *)datap = htons(i);
datap += sizeof (short);
}
/*
* Store a long into the data area.
*/
datalong(i)
{
*(unsigned long *)datap = htonl(i);
datap += sizeof (long);
}
/*
* Store string into data area. If "round" is set, round up length.
* Returns length of data.
*/
datastring(sp,round)
char *sp;
{
char *cp = datap; /* remember old value to store length */
int len;
register c;
int i;
for (datap++, len = 0 ; *sp ; len++) {
if ((c = *sp++) != '\\') {
*datap++ = c;
continue;
}
switch (c = *sp++) {
default:
*datap++ = c;
continue;
case 'b':
*datap++ = '\b';
continue;
case 'f':
*datap++ = '\f';
continue;
case 'n':
*datap++ = '\n';
continue;
case 'r':
*datap++ = '\r';
continue;
case 't':
*datap++ = '\t';
continue;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7': /* octal constant */
*datap = c - '0'; /* stop after */
for (i = 2 ; i <= 3 ; i++) { /* three digits */
if ((c = *sp) < '0' || c > '7') /* or */
break; /* non-octal digit */
c -= '0';
*datap <<= 3;
*datap |= (c & 0x7);
*++sp;
}
datap++;
break;
case 'x': /* hex constant */
*datap = 0;
for (i = 1 ; i <= 2; i++) { /* stop after two */
c = *sp; /* digits or */
if (!isxdigit (c)) /* non-hex digit */
break;
else if (isdigit(c))
c -= '0';
else
c -= isupper(c) ? 'A' - 10 : 'a' - 10;
*datap <<= 4;
*datap |= (c & 0xf);
*++sp;
}
datap++;
break;
}
}
*cp = len;
len++;
if (round && (len & 1)) {
len++;
*datap++ = 0;
}
return (len);
}
/*
* Scan next number from line and return it.
*/
scanfn(fmt)
char *fmt;
{
int val;
if (skipsp() == 0 || sscanf(lp,fmt,&val) != 1)
abort("no number found");
do {
lp++;
} while (*lp != ' ' && *lp != '/0'); /* skip to next number */
return (val);
}
/*
* Scan next string from "line" into "token"; return 0 if none left.
*/
scanft()
{
char *cp;
if (skipsp() == 0)
return (0);
cp = token;
while (*lp != ' ' && *lp != 0)
*cp++ = *lp++;
*cp = 0;
return (1);
}
/*
* Skip spaces. Return 0 if end of line.
*/
skipsp()
{
while (*lp == ' ' && *lp != 0)
lp++;
return(*lp);
}
/*
* Print the data portion of the current rcp record.
*/
printrcp()
{
char *cp;
int i;
unsigned int j;
printf("Type %s, ID %d, length %d, datalen %d\n",
rcp->rc_type, rcp->rc_id, rcp->rc_length, rcp->rc_datalen);
cp = rcp->rc_data; /* pick up the data pointer */
for (i=0 ; i < rcp->rc_datalen ; i++) {
j = *cp++ & 0xFF;
if ((i % 16) == 15)
printf("%02X\n",j);
else
printf("%02X ",j);
}
printf("\n");
}
#define VAX
#define nohtonl
#ifdef nohtonl /* if not in library */
#ifdef VAX
/*
* "Host" to "net" byte order swappers.
*/
unsigned short htons(a)
unsigned short a;
{
unsigned short result;
register char *sp = (char *)&a;
register char *dp = (char *)&result;
dp[1] = *sp++;
dp[0] = *sp;
return (result);
}
unsigned long htonl(a)
unsigned long a;
{
unsigned long result;
register char *sp = (char *)&a;
register char *dp = (char *)&result;
dp[3] = *sp++;
dp[2] = *sp++;
dp[1] = *sp++;
dp[0] = *sp;
return (result);
}
#else /* if running on a native 68K, don't need byte swapping */
unsigned short htons(a)
unsigned short a;
{
return (a);
}
unsigned long htonl(a)
unsigned long a;
{
return (a);
}
#endif VAX
#endif nohtonl
/*
* T Y P E H A N D L E R S
*/
/*
* Handle string format data.
*/
handstr()
{
if (getline() == 0)
abort("missing string");
datastring(lp,1);
}
/*
* Handle string list format data.
*/
handstrl()
{
int count;
char *backp = datap;
int nbytes;
/* Pad for count */
*datap++ = 0;
*datap++ = 0;
/* Process lines */
for (count = 0; ; ++count) {
if (getline() == 0)
break;
datastring(lp, 0);
}
if (count == 0)
abort("empty STR# string list");
/* Stuff count where it belongs */
*backp++ = count >> 8;
*backp++ = count & 0xFF;
/* Pad whole resource if odd byte count (assume this is necessary?) */
nbytes = datap - data;
if (nbytes & 1)
*datap++ = '\0';
}
/*
* Handle hexadecimal format data.
*/
handhexa()
{
char hex[4];
int val, items, len;
hex[2] = 0;
while (getline() != 0) {
for (len = strlen(lp) ; len > 0 ; ) {
if (*lp == ' ') {
lp++; len--;
continue;
}
strncpy(hex, lp, 2);
items = sscanf(hex, "%x", &val);
if (items != 1)
abort("bad digits");
*datap++ = val;
lp += 2; len -= 2;
if ((datap - data) >= sizeof data)
abort("too much data");
}
}
len = datap - data;
if (len & 1) {
len++;
*datap++ = 0;
}
}
/*
* Handle program (code) data.
*/
handcode()
{
register i;
struct reloc rl;
/*
* setup CODE, id=0 (jumptable)
*/
if (rcp->rc_id == 0) {
rcp[1] = rcp[0]; /* duplicate rescomp entry */
rcp->rc_att = ATT_PURGEABLE;
rcp->rc_datalen = rcp->rc_length = sizeof seg0;
rcp->rc_data = seg0;
rcp->rc_file = (FILE *)0;
rcp->rc_bss = 0;
rcp++;
}
/*
* setup CODE, id=1 (text/data)
*/
if (fread(&bh, sizeof bh, 1, rcp->rc_file) != 1
|| bh.fmagic != FMAGIC)
abort("bad b.out header");
if ((rcp->rc_data = malloc(rcp->rc_datalen = bh.tsize
+ bh.dsize + sizeof seg1)) == 0)
abort("code malloc");
rcp->rc_id++; /* normally id is now 1 */
seg1[3] = rcp->rc_id; /* put id in jump table */
bcopy(seg1, rcp->rc_data, sizeof seg1);
rcp->rc_data += sizeof seg1;
if (fread(rcp->rc_data, rcp->rc_datalen - sizeof seg1,
1, rcp->rc_file) != 1)
abort("code readerror");
rcp->rc_bss = bh.bsize;
rcp->rc_length = rcp->rc_datalen + rcp->rc_bss;
if (!rcp->rc_att) /* set default attributes if none supplied */
rcp->rc_att = ATT_PURGEABLE | ATT_LOCKED | ATT_PRELOAD;
if ((bh.rtsize + bh.rdsize) <= 0)
abort("b.out must have reloc info");
fseek(rcp->rc_file, RTEXTPOS, 0);
if (*(short *)rcp->rc_data != htons(CRTMAGIC))
abort("no crtmac.s prefix");
relpnt = rcp->rc_data + 2; /* start of longrun table */
rellen = CRTLEN; /* length of longrun table */
reloff = 0;
readrel(0, bh.rtsize/sizeof rl); /* reloc text */
readrel(bh.tsize, bh.rdsize/sizeof rl); /* reloc data */
*(rcp->rc_data+reloff) = 0377; /* signals end of reloc data */
rcp->rc_data -= sizeof seg1;
fclose(rcp->rc_file);
rcp->rc_file = 0;
fprintf(stderr, " text %d, data %d, bss %d, longruns %d\n",
bh.tsize, bh.dsize, bh.bsize, CRTLEN - rellen);
}
/*
* Read relocation data and run length encode it.
*/
readrel(off, nrel)
{
struct reloc rl;
register char *cp;
int run, newoff;
for ( ; nrel > 0 ; nrel--) {
if (fread(&rl, sizeof rl, 1, rcp->rc_file) != 1)
abort("error reading reloc");
if (rl.rsize != RLONG || (rl.rpos & 1)
|| rl.rsymbol || rl.rsegment == REXT)
abort("impossible relocation");
newoff = (rl.rpos + off);
run = (newoff - reloff) >> 1;
if (reloff == 0 || run >= 0377) {
*(long *)relpnt = htonl(newoff);
relpnt += sizeof (long);
if (--rellen <= 0)
abort("too many longruns");
} else {
*(rcp->rc_data+reloff) = run;
}
reloff = newoff;
}
}
/*
* DRVR, INIT, PACK, CDEF, MDEF, and WDEF all have essentially
* the same format. The only difference is that DRVR's require
* a different offset to the entry point.
*/
#define DRVROFF 50 /* offset of longruns in DRVR resource */
/* Interpretation of that last comment for
the rest of us: The entry point in
crtdrvr.s is the 50th byte. */
#define DRVRMAGIC
#define PROCOFF 0 /* zero offset for crtwdef.s entry point */
handdrvr()
{
relocate(DRVROFF);
}
handproc()
{
relocate(PROCOFF);
}
/*
* Relocate a resource.
*/
relocate(off)
{
register i;
struct reloc rl;
if (fread(&bh, sizeof bh, 1, rcp->rc_file) != 1
|| bh.fmagic != FMAGIC)
abort("bad b.out header");
if((rcp->rc_rellen = (bh.rtsize + bh.rdsize) / sizeof(rl)) & 1)
rcp->rc_rellen++;
if ((rcp->rc_data = malloc((rcp->rc_datalen = bh.tsize
+ bh.dsize) + rcp->rc_rellen)) == 0)
abort("text malloc");
rcp->rc_rel = rcp->rc_data + rcp->rc_datalen;
if (fread(rcp->rc_data, rcp->rc_datalen, 1, rcp->rc_file) != 1)
abort("text readerror");
rcp->rc_bss = bh.bsize;
rcp->rc_length = rcp->rc_datalen + rcp->rc_bss + rcp->rc_rellen;
if ((bh.rtsize + bh.rdsize) <= 0)
abort("b.out must have reloc info");
fseek(rcp->rc_file, RTEXTPOS, 0);
if (*(short *)(rcp->rc_data+off) != htons(RELMAGIC))
abort("no crtxxx.s prefix");
relpnt = rcp->rc_data + off + 2; /* start of longrun table */
rellen = RELLEN; /* length of longrun table */
*(long *)relpnt = htonl(rcp->rc_length
- rcp->rc_rellen); /* offset to reloc table */
relpnt += sizeof(long);
relrel = rcp->rc_rel; /* start of reloc table */
reloff = 0;
rdreloc(0, bh.rtsize/sizeof rl); /* reloc text */
rdreloc(bh.tsize, bh.rdsize/sizeof rl); /* reloc data */
*relrel = 0377; /* signals end of reloc data */
fclose(rcp->rc_file);
rcp->rc_file = 0;
fprintf(stderr, " %s text %d, data %d, bss %d, reloc %d, longruns %d\n",
rcp->rc_type, bh.tsize, bh.dsize, bh.bsize, rcp->rc_rellen, RELLEN - rellen);
}
/*
* Read relocation data and run length encode it in a dynamically relocatable
* form.
*/
rdreloc(off, nrel)
{
struct reloc rl;
register char *cp;
int run, newoff;
for ( ; nrel > 0 ; nrel--) {
if (fread(&rl, sizeof rl, 1, rcp->rc_file) != 1)
abort("error reading reloc");
if (rl.rsize != RLONG || (rl.rpos & 1)
|| rl.rsymbol || rl.rsegment == REXT)
abort("impossible relocation");
newoff = (rl.rpos + off);
run = (newoff - reloff) >> 1;
if (reloff == 0 || run >= 0377) {
*(long *)relpnt = htonl(newoff);
relpnt += sizeof (long);
if (--rellen <= 0)
abort("too many longruns");
if(reloff)
*relrel++ = 0;
} else {
*relrel++ = run;
}
reloff = newoff;
}
}
/*
* Handle dialog template (DLOG).
*/
/*
* This structure is defined in toolintf.h, but to avoid byte swap
* and alignment problems, we fill it "by hand".
*
* typedef struct {
* Rect boundsRect;
* short procID;
* char visible;
* char filler1;
* char goAwayFlag;
* char filler2;
* long refCon;
* short itemsID;
* Str255 title;
* } DialogTemplate;
*/
handdlog()
{
int vis,go,pid,ref;
register i;
if (getline() == 0)
abort("no dlog rectangle");
for (i=0 ; i<4 ; i++) /* parse 4 ints - rectangle */
datashort(scanfn("%d"));
if (getline() == 0)
abort("no dlog vis/proc");
scanft();
vis = (token[0] == 'V' ? 1 : 0);
pid = scanfn("%d");
scanft();
go = (token[0] == 'G' ? 1 : 0);
ref = scanfn("%d");
datashort(pid);
*datap++ = vis; *datap++ = 0;
*datap++ = go; *datap++ = 0;
datalong(ref);
if (getline() == 0)
abort("missing Item list ID");
datashort(scanfn("%d"));
if (getline() != 0)
datastring(lp,1);
else
datashort(0);
}
/*
* Handle alert template.
*/
/*
* This structure is defined in toolintf.h, but to avoid byte swap
* and alignment problems, we fill it "by hand".
*
* typedef struct {
* Rect boundsRect;
* short itemsID;
* short stages;
* } AlertTemplate;
*/
handalrt()
{
int i;
getline();
for (i=0 ; i<4 ; i++) /* parse 4 ints - rectangle */
datashort(scanfn("%d"));
getline();
datashort(scanfn("%d"));
getline();
datashort(scanfn("%x"));
}
/*
* Handle Dialog and Alert Item Lists (Type DITL)
*
*/
/*
* Structure of an item list.
*
* struct {
* long zero; placeholder for handle
* Rect itemrect;
* char itemtype;
* char itemlength;
* ... followed by variable length data
* }
*/
struct ditlkeys {
char *ditl_name;
int ditl_value;
} ditlkeys[] = {
"CtrlItem",ctrlItem, /* used in conjunction with: */
"BtnCtrl",btnCtrl, /* a button control */
"ChkCtrl",chkCtrl, /* checkbox */
"RadCtrl",radCtrl, /* etc... */
"ResCtrl",resCtrl,
"RadioItem",radCtrl+ctrlItem,
"ChkItem",chkCtrl+ctrlItem,
"StatText",statText,
"EditText",editText,
"IconItem",iconItem,
"PicItem",picItem,
"UserItem",userItem,
"ItemDisable",itemDisable,
"BtnItem",btnCtrl+ctrlItem, /* abbreviation */
"Enabled",0,
"Disabled",itemDisable, /* synonym */
"Disable",itemDisable, /* synonym */
"ItemDisabled",itemDisable, /* synonym */
0,0
};
handditl()
{
char *lenp;
int i,len;
int val,types;
register struct ditlkeys *dk;
/* first line is item count, drop in count-1 */
if (getline() == 0 || (val = scanfn("%d")) < 1)
abort("bad DITL item count");
datashort(val-1);
/* for each item */
for ( ; val > 0 ; val--) {
datalong(0);
if (getline() == 0) /* line with item types */
abort("Missing DITL item type");
types = 0;
while (scanft()) {
for (dk = &ditlkeys[0] ; dk->ditl_name ; dk++)
if (strcmp(dk->ditl_name,token) == 0)
goto found;
abort("bad DITL item type %s",token);
found:
types += dk->ditl_value;
}
if (getline() == 0)
abort("Missing DITL rectangle");
for ( i=0 ; i < 4 ; i++)
datashort(scanfn("%d"));
*datap++ = types;
if ((getline() == 0) && (types&(~itemDisable) != editText))
abort("Missing DITL data");
skipsp();
lenp = datap++; /* remember spot for length */
types &= ~itemDisable; /* don't care about this bit */
switch (types) {
case iconItem: /* 2 byte resource ID */
case picItem:
case ctrlItem+resCtrl:
datashort(scanfn("%d"));
*lenp = sizeof (short);
break;
case userItem:
*lenp = 0; /* is nothing */
break;
case ctrlItem+btnCtrl:
case ctrlItem+chkCtrl:
case ctrlItem+radCtrl:
case statText:
case editText:
len = strlen(lp);
strcpy(datap,lp);
datap += len;
if (len & 1) {
len++;
*datap++ = 0;
}
*lenp = len;
break;
}
if (getline() != 0)
abort("Expected blank line in DITL");
}
}
/*
* Handle window template (WIND).
*/
/*
* typedef struct {
* Rect boundsRect;
* short procID;
* char visible;
* char filler1;
* char goAwayFlag;
* char filler2;
* long refCon;
* Str255 title;
* } WindowTemplate;
*/
handwind()
{
int vis,go,pid,ref;
char title[128];
register i;
getline();
skipsp();
strcpy(title,lp);
getline();
for (i=0 ; i<4 ; i++) /* parse 4 ints - rectangle */
datashort(scanfn("%d"));
getline();
scanft();
vis = (token[0] == 'V' ? 1 : 0);
scanft();
go = (token[0] == 'G' ? 1 : 0);
getline();
pid = scanfn("%d");
getline();
ref = scanfn("%d");
datashort(pid);
*datap++ = vis; *datap++ = 0;
*datap++ = go; *datap++ = 0;
datalong(ref);
datastring(title,1);
}
/*
* Handle control template (CNTL).
*/
/*
* typedef struct {
* Rect boundsRect;
* short value;
* char visible;
* char filler1;
* short max;
* short min;
* short procID;
* long refCon;
* Str255 title;
* } ControlTemplate;
*/
handcntl()
{
int vis,min,max,pid,ref;
char title[128];
register i;
getline();
skipsp();
strcpy(title,lp);
getline();
for (i=0 ; i<4 ; i++) /* parse 4 ints - rectangle */
datashort(scanfn("%d"));
getline();
scanft();
vis = (token[0] == 'V' ? 1 : 0);
getline();
pid = scanfn("%d");
getline();
ref = scanfn("%d");
getline();
datashort(scanfn("%d"));
*datap++ = vis; *datap++ = 0;
min = scanfn("%d");
max = scanfn("%d");
datashort(max);
datashort(min);
datashort(pid);
datalong(ref);
datastring(title,1);
}
/*
* Handle menu template (MENU).
*/
/*
* typedef struct {
* short menuID;
* long fill1,fill2; placeholder
* long enableFlags;
* Str255 title;
* for each menu item:
* Str255 text;
* char icon#;
* char keyboardequiv;
* char mark;
* char textstyle;
* finally:
* char zero; end of items.
* }
*/
handmenu()
{
int iconid, styleid, cmdid, markid;
int *flagsp, flags, item;
register char *cp,*dp,*sp;
char itext[128];
static char styles[] = "BIUOS";
datashort(rcp->rc_id);
datalong(0);
datalong(0);
flagsp = (long *)datap; /* remember where the flags were */
flags = -1; /* enable all items */
datalong(-1); /* placeholder */
getline();
scanft();
datastring(token,0);
for (item = 1 ; getline() && item < 32 ; item++) {
skipsp();
iconid = styleid = cmdid = markid = 0;
for (cp = lp, dp = itext ; *cp ; cp++) {
switch (*cp) {
default:
*dp++ = *cp;
break;
case '(':
flags &= ~(1<- > 8;
*datap++ = count & 0xff;
while (count--) {
getline();
datastring(lp,0);
}
/* Pad whole resource if odd byte count (is this necessary?) */
nbytes = datap - data;
if (nbytes & 1)
*datap++ = '\0';
}
@//E*O*F rmaker.c//
chmod u=r,g=r,o=r rmaker.c
echo x - rmaker.1
sed 's/^@//' > "rmaker.1" <<'@//E*O*F rmaker.1//'
@.TH RMAKER local "10/20/84"
@.UC 4
@.SH NAME
rmaker \- resource maker (compiler) for Macintosh
@.SH SYNOPSIS
@.B rmaker
file.rc
@.br
@.B rmaker
[
@.B \-d
type
] file.rc
@.SH DESCRIPTION
@.I Rmaker
reads an ascii resource compiler input file "file.rc" and
produces a Macintosh executable binary "file.rsrc".
See the Inside Mac manual "Putting Together a Macintosh Application"
for a description of this format and process.
It is also helpful to look at one of the example '.rc' files in
the SUMacC 'mac/' source directory.
@.PP
Most of the commonly used resource types are implemented:
STR, STR#, HEXA, CODE, DRVR, ALRT, DITL, DLOG, WIND,
MENU, CNTL, ICON, ICN#, CURS, PAT, INIT, PACK, CDEF,
MDEF, WDEF, POST, FKEY, and PROC.
See the BUGS section below for exceptions.
@.PP
The optional \-d (debug) switch will list out in hex the contents
of all resources matching that four letter type.
@.PP
The usual backslash escape sequences are allowed in strings (\\[bfnrt] and
\\ooo where the "o"'s are octal digits.) Also, \\xhh is allowed where "h" is
a hexadecimal digit.
@.SH SEE ALSO
"Putting Together a Macintosh Application"
(note: this manual is no longer part of Inside Macintosh)
@.PP
"Format of the SUMacC Resource Compiler Input File" (basically
the same as IM, but specific details of the SUMacC rmaker are
covered.) This document is included in this release.
@.SH BUGS
If you have more than one resource of the same type, they must all
be grouped together in the file, and each resource must begin with the "Type"
statement.
@.PP
Types NOT implemented: PICT, PAT#, FREF, BNDL, FONT, GNRL.
You can always use an "inherited type" of HEXA (e.g. Type BNDL = HEXA)
to simulate unimplemented types. GNRL would be even better for this
(if someone would only implement it!)
@.PP
Rmaker input has no "standard" format. Where possible, the format of the
Lisa Rmaker has been used. In the case of STR#, the format is different
than that of the Mac Rmaker. See "Format of the SUMacC Resource Compiler
Input File."
@.PP
If you get the message "impossible relocation", it usually means your
b.out had some undefined external references; check the error output
from 'ld', you probably misspelled some global or routine name.
@.PP
If you get a message similar to "no crtxxx.s prefix", you have probably
linked with the wrong type of crt*.s file for your DRVR or PROC (WDEF, INIT,
etc.). The proper files are included in this release.
@//E*O*F rmaker.1//
chmod u=r,g=r,o=r rmaker.1
echo x - rmaker.doc
sed 's/^@//' > "rmaker.doc" <<'@//E*O*F rmaker.doc//'
_______________________________________________________________________________
FORMAT OF THE SUMACC RESOURCE COMPILER INPUT FILE
Modified 07/01/85 by Brian Powell Adapt for SUMacC
07/06/85 Brian Powell mention backslash escapes
_______________________________________________________________________________
You'll need to create a resource file for your application. This is
done with the Resource Compiler, and you'll have among your working
files an input file to the Resource Compiler. *** In the future,
you'll be able to use the Resource Editor. *** One convention for
naming this input file is to give it the name of your application
followed by ".rc" (Such as samp.rc)
One of the entries in the input file specifies the name to be given to
the output resource file; you'll enter the application name and ."rsrc".
Another entry tells which file the application code segments are to be read
from. (As discussed in the Resource Manager manual, the code segments are
actually resources of the application.) You'll enter the name of the
Linker output file specified in the Exec file for building your
application, as described in the next section.
If you don't want to include any resources other than the code
segments, you can have a simple input file like this:
* samp.rc -- Resource input for sample application
* Written by Macintosh User Education 1/13/84
samp.rsrc
Type SAMP = STR
,0
Samp Version 1.0 -- January 13, 1984
Type CODE
samp.o,0
This tells the Resource Compiler to write the resulting resource file
to samp.rsrc and to read the application code segments from
samp.o in the working directory. It also specifies the file's signature
and version data, which the Finder needs. *** (Documentation on the
signature and version data is forthcoming.) ***
It's a good idea to begin the input file with a comment that describes
its contents and shows its author, creation date, and other such
information. Any line beginning with an asterisk (*) is ignored ***
(except within a menu, for now) ***. The Resource Compiler also
ignores the following:
- leading spaces (except before the text of a string resource)
- embedded spaces (except in file names, titles, or other text
strings)
- blank lines (except for those indicated as required)
The first line that isn't ignored specifies the name to be given to the
resulting resource file. Then, for each type of resource to be
defined, there are one or more "Type statements". A Type statement
consists of the word "Type" followed by the resource type (without
quotes) and, below that, an entry of following format for each
resource:
file name/resource name, resource ID (resource attributes)
type-specific data
The punctuation shown here is typed as part of the format. You must
always provide a resource ID. Specifications other than the resource
ID may or may not be required, depending on the resource type:
- Either there will be some type-specific data defining the resource
or you'll give a file name indicating where the resources will be
read from. You can specify a directory; if not, the working
directory is assumed. Even in the absence of a file name, you must
include the comma before the resource ID.
- You specify a resource name along with the file name for fonts and
drivers. The Menu Manager procedures AddResMenu and InsertResMenu
will put these resource names in menus. Enter the names in the
combination of uppercase and lowercase that you want to appear in
the menus.
- Resource attributes in parentheses are optional for all types.
They're given as a number equal to the value of the resource
attributes byte, and 0 is assumed if none is specified. (See the
Resource Manager manual for details.) For example, for a resource
that's purgeable but has no other attributes set, the input will
be "(32)"; for one that's purgeable and in the system heap, it
will be "(96)".
The formats for the different types of resources are best explained by
example. Some examples are given below along with comments that
provide further explanation. Here are some points to remember:
- In every case, resource attributes in parentheses may be specified
after the resource ID.
- All numbers are base 10 except where hexadecimal is indicated.
- The Type statements must be grouped by type in the input file.
- In general, all strings may include backslash escape characters.
(\b, \f, \n, \r, \t, \377, \x7a, etc.)
Type WIND Window template
,1 Resource ID
Status Report Window title
40 80 120 300 BoundsRect (top left bottom right)
Visible GoAway For FALSE, use Invisible or NoGoAway
0 ProcID (window definition ID)
0 RefCon (reference value)
Type MENU Menu (standard, enabled)
,2 Resource ID (menu ID)
Edit Menu title
Cut/X Menu items, one per line, with meta-
Paste/Z characters, ! alone for check mark
(- You cannot specify a blank item; use (-
Word Wrap! for a disabled continuous line.
Blank line required at end of menu
Type CNTL Control template
,1 Resource ID
Help Control title
55 20 75 90 BoundsRect
Visible For FALSE, use Invisible
0 ProcID (control definition ID)
1 refCon (reference value)
0 0 0 Value minimum maximum
Type DLOG Dialog template
,1 Resource ID
100 100 190 250 BoundsRect
Visible 1 GoAway 0 1 is procID, 0 is refCon
3 Resource ID of item list
Title (none in this case)
Type ALRT Alert template
,1 Resource ID
120 100 190 250 BoundsRect
5 Resource ID of item list
F721 Stages word in hexadecimal
Type DITL Item list in dialog or alert
,3 Resource ID
5 Number of items
BtnItem Enabled Also: ChkItem, RadioItem
60 10 80 70 Display rectangle
Start Title
Blank line required between items
CtrlItem Enabled Control defined in control template
60 10 80 100 Display rectangle
1 Resource ID of control template
StatText Disabled Also: EditText
10 93 26 130 Display Rectangle
Seed The text (may be blank if EditText)
IconItem Disabled Also: PicItem
10 24 42 56 Display rectangle
1 Resource ID of icon
UserItem Disabled Application-defined item
20 50 60 85 Display rectangle
Type ICON Icon
,1 Resource ID
0380 0000 The icon in hexadecimal (32 such lines)
. . . altogether)
1EC0 3180
Type ICN# Icon list
,128 Resource ID
0001 0000 The icons in hexadecimal (32 such lines
. . . altogether for each icon)
0002 8000
Blank line required after last icon
Type CURS Cursor
,300 Resource ID
7FFC . . . 287F The data: 64 hex dgits on one line
0FC0 . . . 1FF8 The mask: 64 hex digits on one line
0008 0008 The hotSpot in hexadecimal (v h)
Type PAT Pattern
,200 Resource ID
AADDAA66AADDAA66 The pattern in hexadecimal
Type STR String
,36 Resource ID
This is your string The string on one line (leading spaces
not ignored)
Type STR# String list
,1 Resource ID
This is string one the strings...
This is string two
This is string three
Blank line required following STR#
Type DRVR Desk accessory or other I/O driver
Monkey/Monkey,17 (32) File name/resource name, resource ID
[ SEE NOTE 1 BELOW ]
Type FREF = HEXA File reference *** see note 4 below ***
,128 Resource ID
4150504C File type APPL
0000 Local ID of icon
05544746494C File name "TgFil" (00 if none)
Type BNDL = HEXA Bundle *** see note 4 below ***
,128 Resource ID
53414D70 0000 Bundle owner SAMP 0
0001 Two types in bundle (ICN# and FREF)
49434E23 0000 ICN# number of resources minus 1
0000 0080 Local ID 0 maps to resource ID 128
46524546 0000 FREF number of resources minus 1
0000 0080 Local ID 0 maps to resource ID 128
Type HEXA Any butes specified here
,9 Resource ID
526FEEC942E78EA4 The bytes in hexadecimal (any number
0F4C total, any nuber per line)
Blank line required at end
Type CODE Application code segments
samp.o,0 Linker output file name, resource ID
[ SEE NOTE 3 BELOW ]
Type POST Postscript resource
,1 Resource ID
4 Number of strings
This is string one The strings...
This is string two
Third string
Bench warmer Apple's joke, not mine.
Notes:
1. The Resource Compiler adds a NUL character (ACII code 0) at the
beginning of the name you specify for a 'DRVR' type of resource
if it doesn't begin with a period ('.'). Therefore, device drivers
should start with a '.', and desk accessories with any other character.
This inclusion of a nonprinting character avoids confilict with
file names that are the same as the names of desk accessories.
3. For a 'CODE' type of resource, the resource ID you specify is
ignored. The Resource Compiler always creates two resources of
this type, with ID numbers 0 and 1, and will create additional
ones numbered sequentially from 2 if your program is divided
into segments.
4. *** Temporary: The file reference and bundle resources are for
extablishing an interface with the Finder and are not yet
documented; se Macintosh Technical Support for more information.
A future version of the Resource Compiler will recognize these
resource types and let you enter them in a more convenient format
than shown here. ***
The Type statement for a resource of type 'WDEF', 'MDEF', 'CDEF',
'FKEY' *** function key code ***, 'PACK', 'PROC', or 'INIT' has the
same format as for 'CODE': only a file name and a resource ID are
specified. The file contains the compiled code of the resource.
You can also define a new resource type that inherits the properties of
a standard type. For example,
Type XDEF = WDEF
defines the new type 'XDEF', which the Resource Compiler treats exactly
like 'WDEF'. The next line would contain a file name and resource ID
just as for a 'WDEF' resource. As another example, suppose you want to
define a resource type 'MINE' that consists of any bytes specified in
hexadecimal in the Resource Compiler input file; you can use
Type MINE = HEXA
followed by the resource ID and bytes on the subsequent lines.
If your application is going to write to the resulting resource file as
well as read it, you should place the Type statement for the code
segments at the end of the input file. In general, any resources that
the application might change and write out to the resource file should
be listed first in the input file, and any resources that won't be
changed (like the code segments) should be listed last. The reason for
this is that the Resource Compiler stores resources in the reverse of
the order that they're listed, and it's more efficient for the Resource
Manager to do file compaction if the changed resources are at the end
of the resource file.
@//E*O*F rmaker.doc//
chmod u=r,g=r,o=r rmaker.doc
echo x - crtdrvr.s
sed 's/^@//' > "crtdrvr.s" <<'@//E*O*F crtdrvr.s//'
|
| crtdrvr.s - dynamically relocating C runtime startoff for Mac desk accessory
|
| Copyright (C) 1984, Stanford Univ. SUMEX project
| May be used but not sold without permission.
|
| history
| 07/20/84 Croft Created.
| 10/24/84 Smith Customize for test
| 01/10/85 Moy Add dynamic rellocation
|
Open = 0
Prime = 4
Ctl = 8
Status = 12
Close = 16
.data
.text
.globl _savea5
.globl drvr
.globl drvrOpen,drvrPrime,drvrCtl,drvrStatus,drvrClose
| driver header
drvr:
.word 0x2400 | enable control, need time
.word 2 | 30 times a second
.word 0x0142 | mouseDown, update, activate events
.word 0 | no menu
doffset:
.word dopen-drvr
.word dprime-drvr
.word dctl-drvr
.word dstatus-drvr
.word dclose-drvr
.byte 6
| .ascii "\0Sleep"
.byte 0
.ascii "Sleep"
.blkb 25 | 32 bytes total for name
jra dopen | magic number
reloff: .long 0
.long 0,0,0,0,0,0,0,0,0,0 | longruns from rmaker
reladdr:.long 0
_savea5:.long 0
|
| driver entry points
|
dopen:
moveq #Open,d0
bras .L21
dprime:
moveq #Prime,d0
bras .L21
dctl:
moveq #Ctl,d0
bras .L21
dstatus:
moveq #Status,d0
bras .L21
dclose:
moveq #Close,d0
@.L21:
moveml #0x3ffc,sp@-
lea pc@([reladdr-.-2]),a2 | reloc addr
lea pc@([drvr-.-2]),a3 | reloc factor
movl a3,d1
andl #0xffffff,d1 | clear out trash in high byte
subl a2@,d1 | have we moved?
beqs call
addl d1,a2@ | adjust reladdr
lea pc@([reloff-.-2]),a3
addl d1,a3@ | adjust addr of reloc table
movl a3@+,a4 | get addr of reloc table
addl d1,a3@ | adjust 1st relocation
movl a3@+,a2 | pickup 1st relocation
|
| a2 = current reloc address
| a3 = next longrun address
| a4 = next reloc table address
| d1 = relocation factor
|
| for(;;) {
| *(u_long *)a2 += (u_long)d1;
| if ((i = (*a4++ & 0377)) == 0) {
| *a3 += d1;
| a2 = *a3++;
| continue;
| }
| if (i == 0377)
| goto start;
| a2 += (i << 1);
| }
@.L16:
addl d1,a2@
movb a4@+,d7
andl #255,d7
bnes .L19
addl d1,a3@
movl a3@+,a2
bras .L16
@.L19:
cmpl #255,d7
beqs .L18
roll #1,d7
addl d7,a2
bras .L16
|
| if shift button is pressed on entry, beep and hang around for an NMI.
|
@.L18:
btst #0,0x17b
beqs .L31 | if not pressed
movw #1,sp@- | sysbeep, duration 1
.word /A9C8
moveq #1,d2
@.L22:
tstl d2
bnes .L22 | hang, waiting for NMI
@.L31:
movl a5,_savea5
call:
movl a1,sp@-
movl a0,sp@-
movl #jmptab,a0
addl d0,a0
movl a0@,a0
jsr a0@
addql #8,sp
moveml sp@+,#0x3ffc
cmpl #0x40000000,d0
bnes done
clrl d0
rts
jiodone = 0x8fc
done:
movl jiodone,sp@-
rts
jmptab: .long drvrOpen
.long drvrPrime
.long drvrCtl
.long drvrStatus
.long drvrClose
@//E*O*F crtdrvr.s//
chmod u=r,g=r,o=r crtdrvr.s
echo x - crtproc.s
sed 's/^@//' > "crtproc.s" <<'@//E*O*F crtproc.s//'
|
| crtproc.s - dynamically relocating C runtime startoff for PROCs.
| This is a sample window definition procedure.
|
| Copyright (C) 1984, Stanford Univ. SUMEX project
| May be used but not sold without permission.
|
| history
| 01/10/85 Moy Created
| 07/01/85 Powell renamed from crtwdef.s to crtproc.s
|
.data
.text
.globl _savea5
.globl wdef
.globl MyWindow
wdef: jra .L21 | magic number
reloff: .long 0
.long 0,0,0,0,0,0,0,0,0,0 | longruns from rmaker
reladdr:.long 0
_savea5:.long 0
@.L21:
moveml #0x3ffc,sp@-
lea pc@([reladdr-.-2]),a2 | reloc addr
lea pc@([wdef-.-2]),a3 | reloc factor
movl a3,d1
andl #0xffffff,d1 | clear out trash in high byte
subl a2@,d1 | have we moved?
beqs call
addl d1,a2@ | adjust reladdr
lea pc@([reloff-.-2]),a3
addl d1,a3@ | adjust addr of reloc table
movl a3@+,a4 | get addr of reloc table
addl d1,a3@ | adjust 1st relocation
movl a3@+,a2 | pickup 1st relocation
|
| a2 = current reloc address
| a3 = next longrun address
| a4 = next reloc table address
| d1 = relocation factor
|
| for(;;) {
| *(u_long *)a2 += (u_long)d1;
| if ((i = (*a4++ & 0377)) == 0) {
| *a3 += d1;
| a2 = *a3++;
| continue;
| }
| if (i == 0377)
| goto start;
| a2 += (i << 1);
| }
@.L16:
addl d1,a2@
movb a4@+,d7
andl #255,d7
bnes .L19
addl d1,a3@
movl a3@+,a2
bras .L16
@.L19:
cmpl #255,d7
beqs .L20
roll #1,d7
addl d7,a2
bras .L16
@.L20:
movl a5,_savea5
call:
moveml sp@+,#0x3ffc
jmp MyWindow
@//E*O*F crtproc.s//
chmod u=r,g=r,o=r crtproc.s
exit 0