Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.3 4.3bsd-beta 6/6/85; site ut-sally.UUCP Path: utzoo!watmath!clyde!burl!ulysses!gamma!epsilon!zeta!sabre!petrus!bellcore!decvax!decwrl!pyramid!ut-sally!brian From: brian@ut-sally.UUCP (Brian H. Powell) Newsgroups: net.sources.mac Subject: New SUMacC RMaker (part 2 of 2) Message-ID: <3875@ut-sally.UUCP> Date: Wed, 25-Dec-85 02:41:29 EST Article-I.D.: ut-sally.3875 Posted: Wed Dec 25 02:41:29 1985 Date-Received: Thu, 26-Dec-85 03:58:20 EST Organization: U. Texas CS Dept., Austin, Texas Lines: 1491 # 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 sally!brian on Wed Dec 25 01:21:22 CST 1985 # Contents: code.c hand.c rmaker.c scan.c echo x - code.c sed 's/^@//' > "code.c" <<'@//E*O*F code.c//' #include "rmaker.h" #include #define bh filhdr struct bhdr bh; /* b.out header */ 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 }; #ifndef CRTLEN #define CRTLEN 10 /* length of relocation table in crtmac.s */ #endif CRTLEN #define CRTMAGIC (0x6004+4*CRTLEN) /* jump at beginning of crtmac.s */ #ifndef RELLEN #define RELLEN 12 /* length of relocation table in crt*.s */ #endif #define RELMAGIC (0x6004+4*RELLEN) /* jump at beginning of crt*.s */ 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 */ /* * Handle program (code) data. */ handcode() { 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((char *)&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((char *)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(0L, 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) long off, nrel; { struct reloc rl; long run, newoff; for ( ; nrel > 0 ; nrel--) { if (fread((char *)&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) { struct reloc rl; if (fread((char *)&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((char *)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(0L, 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) long off, nrel; { struct reloc rl; long run, newoff; for ( ; nrel > 0 ; nrel--) { if (fread((char *)&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; } } @//E*O*F code.c// chmod u=rw,g=rw,o=r code.c echo x - hand.c sed 's/^@//' > "hand.c" <<'@//E*O*F hand.c//' /* * hand.c * Rmaker type handlers. */ #include "rmaker.h" struct keylist visible[] = { "visible", 1, "invisible", 0, 0, 0 }; struct keylist goaway[] = { "goaway", 1, "nogoaway", 0, 0, 0 }; /* * Handle string format data. */ handstr() { if (getline() == 0) abort("missing string"); datastring(lp, PASCAL); } /* * Handle string list format data. */ handstrl() { int count; char *backp = datap; /* Pad for count */ *datap++ = 0; *datap++ = 0; /* Process lines */ for (count = 0; ; ++count) { if (getline() == 0) break; datastring(lp, PASCAL); } if (count == 0) abort("empty STR# string list"); /* Stuff count where it belongs */ *backp++ = count >> 8; *backp++ = count & 0xFF; } /* * Handle hexadecimal format data. */ handhexa() { while (getline() != 0) while (skipsp() != 0) databyte(scanhex(2)); } /* * 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; long ref; register i; if (getline() == 0) abort("no dlog rectangle"); for (i=0 ; i<4 ; i++) /* parse 4 ints - rectangle */ datashort(scanshort()); if (getline() == 0) abort("no dlog vis/proc"); vis = scankeys(visible); pid = scanshort(); go = scankeys(goaway); ref = scanlong(); datashort(pid); *datap++ = vis; *datap++ = 0; *datap++ = go; *datap++ = 0; datalong(ref); if (getline() == 0) abort("missing Item list ID"); datashort(scanshort()); if (getline() != 0) { skipsp(); datastring(lp, PASCAL); } 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(scanshort()); getline(); datashort(scanshort()); getline(); datashort(scanhex(4)); } /* * 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 keylist ditlkeys[] = { /* Standard item types */ "btnitem", ctrlItem + btnCtrl, "chkitem", ctrlItem + chkCtrl, "radioitem", ctrlItem + radCtrl, "rescitem", ctrlItem + resCtrl, "stattext", statText, "edittext", editText, "iconitem", iconItem, "picitem", picItem, "useritem", userItem, /* * For backward compatibility with older versions of sumacc rmaker: * eg, "BtnItem" can be specified as "CtrlItem BtnCtrl" */ "ctrlitem", ctrlItem, /* used in conjunction with: */ "btnctrl", btnCtrl, /* a button control */ "chkctrl", chkCtrl, /* checkbox */ "radctrl", radCtrl, /* etc... */ "resctrl", resCtrl, "enabled", 0, "disabled", itemDisable, /* Synonyms for "Disabled", for backward compatibility */ "itemdisable", itemDisable, "disable", itemDisable, "itemdisabled", itemDisable, 0,0 }; handditl() { char *lenp; int i, val, types; /* first line is item count, drop in count-1 */ if (getline() == 0 || (val = scanshort()) < 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; do { types += scankeys(ditlkeys); } while (skipsp() != 0); if (getline() == 0) abort("Missing DITL rectangle"); for ( i=0 ; i < 4 ; i++) datashort(scanshort()); *datap++ = types; types &= ~itemDisable; /* don't care about this bit */ /* * data line is missing for userItem and optional for editText */ if (types != userItem && getline() == 0 && types != editText) abort("Missing DITL data"); skipsp(); lenp = datap++; /* remember spot for length */ switch (types) { case iconItem: /* 2 byte resource ID */ case picItem: case ctrlItem+resCtrl: datashort(scanshort()); *lenp = sizeof (short); break; case userItem: *lenp = 0; /* is nothing */ break; case ctrlItem+btnCtrl: case ctrlItem+chkCtrl: case ctrlItem+radCtrl: case statText: case editText: *lenp = datastring(lp, ROUND); 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; long ref; char title[128]; register i; getline(); skipsp(); strcpy(title,lp); getline(); for (i=0 ; i<4 ; i++) /* parse 4 ints - rectangle */ datashort(scanshort()); getline(); vis = scankeys(visible); go = scankeys(goaway); getline(); pid = scanshort(); getline(); ref = scanlong(); datashort(pid); *datap++ = vis; *datap++ = 0; *datap++ = go; *datap++ = 0; datalong(ref); datastring(title, PASCAL); } /* * 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; long ref; char title[128]; register i; getline(); skipsp(); strcpy(title,lp); getline(); for (i=0 ; i<4 ; i++) /* parse 4 ints - rectangle */ datashort(scanshort()); getline(); vis = scankeys(visible); getline(); pid = scanshort(); getline(); ref = scanlong(); getline(); datashort(scanshort()); *datap++ = vis; *datap++ = 0; min = scanshort(); max = scanshort(); datashort(max); datashort(min); datashort(pid); datalong(ref); datastring(title, PASCAL); } /* * Handle menu template (MENU). * * typedef struct { * short menuID; * long fill1; * short menuProc; menu definition procedure (normally 0) * short 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, item; long *flagsp, flags; register char *cp,*dp,*sp; char itext[128]; static char styles[] = "BIUOS"; datashort(rcp->rc_id); /* menu resource id */ datalong(0); /* * Read an optional line containing the resource id of * the menu definition procedure, */ getline(); skipsp(); if (isdigit(*lp)) { datashort(scanshort()); getline(); skipsp(); } else datashort(textMenuProc); datashort(0); flagsp = (long *)datap; /* remember where the flags were */ flags = -1; /* enable all items */ datalong(-1); /* placeholder for flags */ datastring(lp, PASCAL); /* The menu title */ 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<rc_file) != 1) abort("can't read picture file"); pictSize = mtohs(pictSize); if (pictSize > sizeof data) abort("picture too large. Increase size of 'data' variable"); rewind(rcp->rc_file); if (fread(data, sizeof (char), pictSize, rcp->rc_file) != pictSize) abort("can't read picture file"); datap += pictSize; fprintf(stderr, "picture %d: %d bytes\n", rcp->rc_id, pictSize); } handfile() { datafile(rcp->rc_file); } handgnrl() { FILE *f; int mode; if (getline() == 0) abort("GNRL: missing data"); mode = 'I'; for (;;) { if (skip() == 0) break; switch (*lp) { case '.': ++lp; if (islower(*lp)) *lp = toupper(*lp); switch (*lp) { default: abort("unknown format code .%c", *lp); break; case 'C': case 'I': case 'L': case 'H': mode = *lp++; break; case 'F': ++lp; if (skip() == 0) abort(".F: missing filename"); gettoken(); f = fopen(token, "r"); if (f == NULL) abort(".F: can't open %s", token); datafile(f); fclose(f); break; case 'S': for (;;) { if (getline() == 0) return; if (skipsp() == '.') break; datastring(line, 0); } break; case 'P': for (;;) { if (getline() == 0) return; if (skipsp() == '.') break; datastring(line, PASCAL); } break; } break; case '"': getstring(); datastring(token, PASCAL); break; case '\'': getstring(); datastring(token, 0); break; default: switch (mode) { case 'C': databyte(scanshort()); break; case 'I': datashort(scanshort()); break; case 'L': datalong(scanlong()); break; case 'H': databyte(scanhex(2)); break; } } } } /* * Handle FREF * * Input: * one line containing * file-type local-id optional-file-name * eg: * APPL 0 FileName * * Output: * 4 bytes - file type * 2 bytes - local resource id for icon list * n bytes - file name as pascal string (0 if filename missing) */ handfref() { if (getline() == 0) abort("FREF: missing data line"); gettoken(); checktype(token); strcpy(datap, token); datap += 4; datashort(scanshort()); skipsp(); datastring(lp, PASCAL); } /* * Handle BNDL * * Input: * signature-type signature-resource-id * number-of-types-in-bundle * For each resource type: * resource-type number-of-resources * For each resource: * local-id global-id * * Output: * 4 bytes - signature type * 2 bytes - signature resource id * 2 bytes - number of types - 1 * For each type: * 4 bytes - resource type * 2 bytes - number of resources - 1 * For each resource: * 2 bytes - local id * 2 bytes - actual id */ handbndl() { short ntypes, nresources; if (getline() == 0) abort("BNDL: missing signature data"); gettoken(); checktype(token); strcpy(datap, token); datap += 4; datashort(scanshort()); if (getline() == 0) abort("BNDL: missing number of types"); ntypes = scanshort(); datashort(ntypes - 1); while (ntypes-- > 0) { if (getline() == 0) abort("BNDL: missing resource type line"); gettoken(); checktype(token); strcpy(datap, token); datap += 4; nresources = scanshort(); datashort(nresources - 1); while (nresources-- > 0) { if (getline() == 0) abort("BNDL: missing resource id line"); datashort(scanshort()); datashort(scanshort()); } } } @//E*O*F hand.c// chmod u=rw,g=rw,o=r hand.c 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. * 07/09/85 GvR Allow CRTLEN and RELLEN to be overridden * on compilation with -D; made CRTMAGIC and * RELMAGIC self-adjusting; changed \ escapes * to hex (as in Inside Mac). * 11/09/85 GvR Changed POST to be identical to STR#. * 07/11/85 Doug Moen Added PICT and FILE. Fixed: Resources are now sorted by type & id. Fixed: tabs are now considered whitespace Fixed: htons, htonl are now machine independent removed lint. * 12/23/85 Powell Changed filename/resource name separator from '|' to '!'. (as in Inside Mac) */ #include "rmaker.h" #define NRESCOMP 50 /* max number of resources per compile */ struct rescomp rescomp[NRESCOMP]; 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 */ /* type format handlers */ extern handstr(), handstrl(), handhexa(); extern handcode(), handdrvr(), handproc(); extern handdlog(), handalrt(), handditl(); extern handwind(), handmenu(), handcntl(); extern handpict(), handfile(), handgnrl(); extern handfref(), handbndl(); 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", handstrl, "FKEY", handproc, "PROC", handproc, "PICT", handpict, "FILE", handfile, "GNRL", handgnrl, "FREF", handfref, "BNDL", handbndl, 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) { printf("items %d littype %s lp %s\n", items, littype, lp); abort("bad Type line"); /*DEBUG*/ } 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"); } /* * Used by qsort to sort resources by type, then id. */ compareRescomp(r1, r2) struct rescomp *r1, *r2; { int cmp = strncmp(r1->rc_type, r2->rc_type, 4); if (cmp != 0) return cmp; return r1->rc_id - r2->rc_id; } /* * 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; long sizemap; register i; register char *cp; numtypes_t numtypes; lendata_t lendata; /* Before scanning, sort rescomp by type/id */ qsort((char *)rescomp, rcp - rescomp, sizeof rescomp[0], compareRescomp); 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((long)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((char *)&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((char *)&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((char *)&rm, sizeof rm, 1, fout); numtypes--; numtypes = htons(numtypes); fwrite((char *)&numtypes,sizeof numtypes, 1, fout); fwrite((char *)&rt[0], sizeof *rtp, rtp - &rt[0], fout); fwrite((char *)&ri[0], sizeof *rip, rip - &ri[0], fout); if (rnp - rn) fwrite((char *)rn, rnp - rn, 1, fout); } /* * Abort with message. */ /* VARARGS1 */ 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); } /* * 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"); } @//E*O*F rmaker.c// chmod u=rw,g=rw,o=r rmaker.c echo x - scan.c sed 's/^@//' > "scan.c" <<'@//E*O*F scan.c//' /* * scan.c * * Routines for scanning and lexical analysis of the rmaker input file. */ #include "rmaker.h" /* * Get next line of input, skipping comments. * Returns 0 if blank line, otherwise 1. */ getline() { register n; do { if ((fgets(line, sizeof line, fin)) == NULL) { fineof++; return (0); } linenum++; } while (line[0] == '*'); /* remove newline at end */ n = strlen(line); if (n == 0) return 0; if (line[n-1] == '\n') line[n-1] = 0; /* determine if it's a blank line */ lp = line; n = skipsp(); lp = line; if (n == 0) return 0; return 1; } /* * Skip spaces. Return 0 if end of line. */ skipsp() { while (*lp == ' ' || *lp == '\t') lp++; return(*lp); } /* * Skip to the next non-blank character, * reading in another line if necessary. * Return 0 if new line is blank. */ skip() { if (skipsp()) return 1; if (getline()) return skipsp(); return 0; } /* * Scan the next token from "line" into "token". * Return 0 if none left. */ gettoken() { char *tp; if (skipsp() == 0) return 0; tp = token; while (*lp != ' ' && *lp != '\t' && *lp != 0) *tp++ = *lp++; *tp = 0; return 1; } /* * Scan quoted string into "token". */ getstring() { char quote = *lp++; char *tp = token; while (*lp != quote && *lp != 0) { *tp++ = *lp++; if (lp[-1] == '\\' && *lp != 0) *tp++ = *lp++; } if (*lp == quote) ++lp; *tp = 0; } /* * Scan for one of the keywords in 'keys'. * Abort if none found, otherwise return associated value. */ int scankeys(keys) struct keylist *keys; { char *tp; struct keylist *k; if (gettoken() == 0) abort("missing keyword"); /* convert token to lower case */ for (tp = token; *tp != 0; ++tp) if (isupper(*tp)) *tp = tolower(*tp); /* determine which keyword it is */ for (k = keys; k->keyname; ++k) if (strcmp(k->keyname, token) == 0) return k->keyvalue; abort("invalid keyword %s", token); /* NOTREACHED */ } /* * Scan a short integer from the line and return it. */ scanshort() { int val; if (gettoken() == 0 || sscanf(token, "%d", &val) != 1) abort("bad or missing number"); return val; } /* * Scan a long integer from the line and return it. */ long scanlong() { long val; if (gettoken() == 0 || sscanf(token, "%ld", &val) != 1) abort("bad or missing number"); return val; } /* * Scan an n digit hex constant from the line and return it. */ scanhex(ndigits) int ndigits; { char *tp = token; int val; if (skipsp() == 0) abort("missing hex constant"); while (ndigits-- > 0) { if (!isxdigit(*lp)) abort("bad hex constant"); *tp++ = *lp++; } *tp = 0; sscanf(token, "%x", &val); return val; } @//E*O*F scan.c// chmod u=rw,g=rw,o=r scan.c exit 0