Macintosh: new rmaker.c
FJ Hirsch
fjh at bentley.UUCP
Tue Aug 28 23:20:50 AEST 1984
# Here is the new rmaker.c for you non-ARPA People. Thanks to Bill
# Croft for sending it to me!
# Fred.
#
#Date: Wed, 22 Aug 84 19:11:51 pdt
#
#! /bin/sh
: This is a shar archive. Extract with sh, not csh.
echo x - cmd/rmaker.c
cat > cmd/rmaker.c << '28336!Funky!Stuff!'
/* 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.
*/
#include <stdio.h>
#include <mac/res.h>
#include <mac/b.out.h>
#include <mac/quickdraw.h>
#include <mac/toolintf.h>
#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 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 */
} 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 */
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();
extern handdlog(), handalrt(), handditl();
extern handwind(), handmenu(), handcntl();
struct typehand { /* type string to handler table */
char th_type[8]; /* e.g. "CODE" */
int (*th_handler)(); /* format handler function */
} typehand[] = {
"STR ", handstr,
"HEXA", handhexa,
"CODE", handcode,
"DRVR", handdrvr,
"ALRT", handalrt,
"DITL", handditl,
"DLOG", handdlog,
"WIND", handwind,
"MENU", handmenu,
"CNTL", handcntl,
"ICON", handhexa,
"ICN#", handhexa,
"CURS", handhexa,
"PAT ", handhexa,
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");
if (strncmp(rcpp->rc_type, "DRVR", 4))
*rnp++ = (char) i;
else {
*rnp++ = (char)(i + 1);
*rnp++ = 0;
}
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);
}
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);
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;
for (datap++, len = 0 ; *sp ; len++)
*datap++ = *sp++;
*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 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;
}
}
/*
* Handle device driver (or desk accessory.).
*/
#define CRTOFF 50 /* offset of longruns in DRVR resource */
handdrvr()
{
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_data = malloc(rcp->rc_datalen = bh.tsize
+ bh.dsize)) == 0)
abort("drvr malloc");
if (fread(rcp->rc_data, rcp->rc_datalen, 1, rcp->rc_file) != 1)
abort("drvr readerror");
rcp->rc_bss = bh.bsize;
rcp->rc_length = rcp->rc_datalen + rcp->rc_bss;
if ((bh.rtsize + bh.rdsize) <= 0)
abort("b.out must have reloc info");
fseek(rcp->rc_file, RTEXTPOS, 0);
if (*(short *)(rcp->rc_data+CRTOFF) != htons(CRTMAGIC))
abort("no crtdrvr.s prefix");
relpnt = rcp->rc_data + CRTOFF + 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 */
fclose(rcp->rc_file);
rcp->rc_file = 0;
fprintf(stderr, " drvr text %d, data %d, bss %d, longruns %d\n",
bh.tsize, bh.dsize, bh.bsize, CRTLEN - rellen);
}
/*
* 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<<item);
break;
case '^':
cp++;
iconid = *cp;
break;
case '/':
cp++;
cmdid = *cp;
break;
case '!':
cp++;
markid = *cp;
break;
case '<':
cp++;
sp = index(styles, *cp);
if (sp == 0)
abort("BIUOS expected after <");
styleid |= (1 << (sp-styles));
break;
}
}
*dp++ = 0;
datastring(itext,0);
*datap++ = iconid;
*datap++ = cmdid;
*datap++ = markid;
*datap++ = styleid;
}
/* end of items */
*datap++ = 0;
*flagsp = htonl(flags);
}
28336!Funky!Stuff!
echo x - drvr/Makefile
cat > drvr/Makefile << '28336!Funky!Stuff!'
.SUFFIXES: .rsrc .b
.c.b:
cc68 -O -c $<
.s.b:
cc68 -c $<
.b.rsrc:
cc68 -z -m $<
rmaker $*.rc
all: rd.rsrc
rd.rsrc: rd.b rdlib.b crtdrvr.b rd.rc
ld68 -X -r -d -e drvr -T 0 crtdrvr.b rd.b rdlib.b -lmac -lc -x
rmaker $*.rc
clean:
rm *.b *.rsrc b.out *.dl
28336!Funky!Stuff!
echo x - drvr/crtdrvr.s
cat > drvr/crtdrvr.s << '28336!Funky!Stuff!'
|
| crtdrvr.s - self relocating C runtime startoff for Mac device driver.
|
| Copyright (C) 1984, Stanford Univ. SUMEX project
| May be used but not sold without permission.
|
| history
| 07/20/84 Croft Created.
|
.data
.text
.globl _savea5
.globl drvr
.globl drvrOpen,drvrPrime,drvrCtl,drvrStatus,drvrClose
| driver header
drvr:
.word 0x4f00 | locked, read, write, ctrl, status
.word 0
.word 0 | delay, emask
.word 0 | menu
doffset:
.word reloc-drvr | replaced by "dopen-drvr" after initialization
.word dprime-drvr
.word dctl-drvr
.word dstatus-drvr
.word dclose-drvr
.byte 8
.ascii ".cdriver "
.blkb 22 | 32 bytes total for name
reloc: jra .L21
.long 0,0,0,0,0,0,0,0,0,0 | longruns from rmaker
_savea5:.long 0
|
| a1 = next longrun address
| a2 = current reloc address
| d1 = relocation factor
|
.L21:
moveml #0xffff,sp at -
lea pc@([drvr-.-2]),a1 | reloc factor
movl a1,d1
lea pc@([reloc+2-.-2]),a1
movl a1 at +,a2 | pickup 1st relocation
addl d1,a2
.L16:
| for(;;) {
| i = *a2;
| *a2 = 0;
| *(u_long *)a2 += (u_long)d1;
| if (i == 0377)
| goto start;
| if (i == 0) {
| a2 = *a1++;
| a2 += d1;
| continue;
| }
| a2 += (i << 1);
| }
movb a2@,d7
andl #255,d7
clrb a2@
addl d1,a2@
cmpl #255,d7
beqs .L18
tstl d7
bnes .L19
movl a1 at +,a2
addl d1,a2
bras .L16
.L19:
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 at - | sysbeep, duration 1
.word /A9C8
moveq #1,d0
.L22:
tstl d0
bnes .L22 | hang, waiting for NMI
.L31:
movl a5,_savea5
movw doff2,doffset | above code is once-only
moveml sp at +,#0xffff
|
| driver entry points
|
dopen:
movl #drvrOpen,d0
bras call
dclose:
movl #drvrClose,d0
bras call
dctl:
movl #drvrCtl,d0
bras call
dstatus:
movl #drvrStatus,d0
bras call
dprime:
movl #drvrPrime,d0
call:
moveml #0x3ffc,sp at -
movl a1,sp at -
movl a0,sp at -
movl d0,a0
jsr a0@
addql #8,sp
moveml sp at +,#0x3ffc
cmpl #0x40000000,d0
bnes done
clrl d0
rts
jiodone = 0x8fc
done:
movl jiodone,sp at -
rts
doff2: .word dopen-drvr
28336!Funky!Stuff!
echo x - drvr/device.h
cat > drvr/device.h << '28336!Funky!Stuff!'
/* device.h 1.0 07/21/84 */
/*
* Device driver definitions.
*/
/*
* Copyright (C) 1984, Stanford Univ. SUMEX project.
* May be used but not sold without permission.
*/
/*
* history
* 07/21/84 Croft Created.
* 07/27/84 Schuster Added accessory status codes.
*/
/*
* Driver structure.
*/
struct drvr {
short drvrFlags; /* flags */
short drvrDelay; /* ticks between actions */
short drvrEMask; /* desk accessory event mask */
short drvrMenu; /* menu ID */
short drvrOpen; /* offset to open routine */
short drvrPrime; /* .. prime */
short drvrCtl; /* .. control */
short drvrStatus; /* .. status */
short drvrClose; /* .. close */
char drvrName[32]; /* driver name (pascal string) */
};
struct drvr drvr; /* global instance of my drvr struct */
/* flags in drvrFlags */
#define dReadEnable 0x100
#define dWritEnable 0x200
#define dCtlEnable 0x400
#define dStatEnable 0x800
#define dNeedGoodBye 0x1000
#define dNeedTime 0x2000
#define dNeedLock 0x4000
#define dOpened 0x20
#define dRAMBased 0x40
#define drvrActive 0x80
/*
* Device control entry structure.
*/
struct dce {
Handle dCtlDriver; /* pointer/handle to driver */
short dCtlFlags;
short dCtlQueue;
Ptr dCtlQHead; /* 1st entry in IO queue */
Ptr dCtlQTail;
long dCtlPosition; /* offset used by R/W calls */
Handle dCtlStorage; /* private storage */
short dCtlRefNum; /* driver's refnum */
long dCtlCurTicks; /* current tick count (kept by Device Mgr) */
WindowPtr dCtlWindow; /* window record (if any) */
short dCtlDelay; /* ticks between actions */
short dCtlEMask; /* event mask (desk acc) */
short dCtlMenu; /* menu ID */
};
/*
* Commands in (low byte of) ioTrap.
*/
#define aRdCmd 2
#define aWrCmd 3
#define aCtlCmd 4
#define aStsCmd 5
/*
* Special return codes from driver entry points.
*
* A zero or negative return from the driver routines causes an IOdone,
* with the return status in D0. The return values below (large
* positive numbers) cause the indicated action.
*/
#define IOrts 0x40000000
#define IOkill IOrts
#define IOdone 0
/*
* Control and status codes.
*/
#define KillCode 1
#define EjectCode 7
#define DrvStsCode 8
/*
* IO System Errors (should be in osintf.h)
*/
#define ControlErr -17
#define StatusErr -18
#define ReadErr -19
#define WritErr -20
#define BadUnitErr -21
#define UnitEmptyErr -22
#define OpenErr -23
#define ClosErr -24
#define DRemovErr -25
#define DInstErr -26
#define AbortErr -27
#define NotOpenErr -28
/*
* Control and Status codes for desk accessories.
*/
#define accEvent 64
#define accRun 65
#define accCursor 66
#define accMenu 67
#define accUndo 68
#define accCut 70
#define accCopy 71
#define accPaste 72
#define accClear 73
28336!Funky!Stuff!
echo x - drvr/rd.c
cat > drvr/rd.c << '28336!Funky!Stuff!'
/*
* MacIntosh RAM Disk Driver
* (c) Apple Computer 1983
*
* This is the unofficial Mac ramdisk driver. Most useful on 512K Macs
* Written in Dec '83 my MDB
*
* Routines:
*
* Open -- Zero the ram and create a directory
*
* Prime -- read and write calls. Get correct info from read or write param
* block, and get or put the bytes. All calls are synchronous, since
* ram doesn't have a lot of latency.
*
* Close -- Not closable at present
*/
/*
* history
* 12/xx/83 MDB Created.
* 07/21/84 Croft translated to C.
*/
#include "mac/quickdraw.h"
#include "mac/osintf.h"
#include "mac/toolintf.h"
#include "device.h"
/*
* for small mac, disk is kept in heap, so use bootconfig
* to up sysheap from 16K to 24K; sigh, but then MacPaint/MacTerm are too big.
*/
#define myramSize 0x2000 /* 8K */
#define asize 512 /* allocation block size */
#define dblocks 5 /* 0,1=boot;2,3=mdb;4=fdir */
#define ablocks myramSize/asize - dblocks
struct DR {
char drSigWord[2]; /* signature */
long drCrDate; /* creation date/time*/
long drLsBkUp; /* last backup */
short drAtrb; /* attributes */
short drNmFls; /* number of files in dir */
short drDirSt; /* 1st file directory block */
short drBlLn; /* length of file dir in blocks */
short drNmAlBlks; /* number of allocation blocks */
long drAlBlkSiz; /* alloc block size */
long drClpSiz; /* bytes to try to alloc as clump */
short drAlBlSt; /* 1st data block */
long drNxtFNum; /* next free file number */
short drFreeBks; /* number free blocks */
char drVN[28]; /* volume name */
};
struct DR myDir = {
0xd2, 0xd7, /* signature */
0,
0,
0,
0,
4, /* 1st file dir block */
1, /* # dir blocks */
ablocks, /* # alloc blocks */
asize, /* alloc block size */
asize, /* clump size */
5, /* 1st data block */
1, /* next file # */
ablocks, /* # free blocks */
"\07RamDisk"
};
Ptr myramBase, NewPtrSys();
/*
* driver Open.
*/
drvrOpen(pb,dce)
ioParam *pb;
struct dce *dce;
{
if ((myramBase = NewPtrSys(myramSize)) == 0)
return (MFulErr);
bzero(myramBase,myramSize);
bcopy(&myDir,myramBase+1024,sizeof myDir);
return (IOrts);
}
/*
* driver Close.
*/
drvrClose(pb,dce)
ioParam *pb;
struct dce *dce;
{
return (IOrts);
}
/*
* driver Prime.
*/
drvrPrime(pb,dce)
register ioParam *pb;
register struct dce *dce;
{
register char *cp;
register count;
cp = myramBase + (dce->dCtlPosition & (~0x1ff)); /* truncate offset */
count = pb->ioActCount = pb->ioReqCount;
count = (count + 0x1ff) & (~0x1ff); /* round to 512 mult */
switch (pb->ioTrap & 0xff) {
case aWrCmd:
bcopy(pb->ioBuffer, cp, count);
break;
case aRdCmd:
bcopy(cp, pb->ioBuffer, count);
break;
}
return (IOdone);
}
/*
* driver Control.
*/
drvrCtl(pb,dce)
register CntrlParam *pb;
register struct dce *dce;
{
switch (pb->CSCode) {
case KillCode:
return (IOkill);
case EjectCode:
default:
return (ControlErr);
}
}
/*
* driver Status.
*/
drvrStatus(pb,dce)
register CntrlParam *pb;
register struct dce *dce;
{
return (ControlErr);
}
28336!Funky!Stuff!
echo x - drvr/rd.rc
cat > drvr/rd.rc << '28336!Funky!Stuff!'
rd.rsrc
Type DRVR
b.out,31(64)
28336!Funky!Stuff!
echo x - drvr/rdinit.text
cat > drvr/rdinit.text << '28336!Funky!Stuff!'
; I'm lazy and hacked this together from some pieces on the workshop,
; should convert to SUMacC...
; File: rdInit.Text - init resource to bring in ramdisk driver at boot time
.NoList
.Include Tlasm/SysEqu.Text
.Include Tlasm/SysMacs.Text
.Include Tlasm/SysErr.Text
.Include Tlasm/ToolMacs.Text
.List
.NOMACROLIST
.Proc rdInit,0
rdInstall
; move.l #$11000,BufPtr
OpenIt
MOVEQ #<IOQElSize/2>-1,D0
@0 CLR.W -(SP) ; clear a parameter blk off the stack
DBRA D0, at 0
;
clr.w -(sp)
_button
tst.w (sp)+
bne initexit ;if user wants to skip the ramdisk
MOVE.L SP,A0
LEA rdName,A1
MOVE.L A1,IOFileName(A0)
_Open
BNE InitExit
CLR.L -(SP)
MOVE.L #'DRVR',-(SP)
move.w #31,-(sp)
_GetResource
_DetachResource
;
; add to drive queue
;
MOVEQ #DQElLnth,D0 ; get size of drive queue element
_NewPtr,SYS ; and allocate one
MOVE.W #0,DQFSID(A0) ; zero means local file system
MOVEQ #3,D0 ; call it drive number 3
SWAP D0
MOVE.W #-32,D0 ; my refnum
_AddDrive
LEA Mparams,A0 ; point to params
_MountVol ; mount as a volume
InitExit
ADD #IOQElSize,SP
LEA rdInstall,A0
_RecoverHandle
_DisposHandle
RTS
rdName .Byte 8
.Ascii '.ramdisk '
.Align 2
Mparams .BLOCK 12,0 ; header
.WORD 0,0 ; completion routine (NIL)
.WORD 0 ; ioresult
.WORD 0,0 ; misc don't-cares
.WORD 3 ; drive num
.end
28336!Funky!Stuff!
echo x - drvr/rdinitr.text
cat > drvr/rdinitr.text << '28336!Funky!Stuff!'
* ramstart resource definition file
*
*
rdinit.Rsrc
Type INIT = PACK
rdinit,3
28336!Funky!Stuff!
echo x - drvr/rdlib.s
cat > drvr/rdlib.s << '28336!Funky!Stuff!'
.insrt "../h/sysequ.h"
.insrt "../h/toolmacs.h"
.text
.globl NewPtrSys
NewPtrSys:
movl sp@(4),d0
.word __newptr+_sys_
movl a0,d0
rts
.globl bcopy
bcopy:
movl sp@(4),a0
movl sp@(8),a1
movl sp@(12),d0
subql #1,d0
.L1:
movb a0 at +,a1 at +
dbra d0,.L1
rts
.globl bzero
bzero:
movl sp@(4),a0
movl sp@(8),d0
subql #1,d0
.L2:
clrb a0 at +
dbra d0,.L2
rts
28336!Funky!Stuff!
--
<*> Fred Hirsch <*> AT&T Bell Laboratories <*> ihnp4!bentley!fjh <*>
More information about the Comp.sources.unix
mailing list