brian@ut-sally.UUCP (Brian H. Powell) (12/25/85)
# 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:22:08 CST 1985
# Contents: Changes Bugs data.c rmaker.h crtdrvr.s crtproc.s rmaker.1
# rmaker.doc samp.rc test.rc
echo x - Changes
sed 's/^@//' > "Changes" <<'@//E*O*F Changes//'
General improvements:
Resources are now sorted by type & id. Previously, if you
didn't group all of your resources together, some of them
would silently disappear.
Tabs are now considered whitespace.
Whitespace is now allowed between the resource ID and the attributes,
eg:
Type FOO
,1 (20)
\ escapes are recognized in all strings and titles.
\HH is replaced by ascii code HH (where HH are 2 hex digits)
\ followed by "anything else" is replace by "anything else".
Thus,
\\ is a backslash
\' and \" permit quotes to be put in quoted string in type GNRL
\<space> can be used to introduce a leading space in a title
\<newline> turns into a blank line in STR# and POST string lists
The syntax for including resources from other files has been modified
to be compatible with IM.
e.g.:
Type FOO
filename!resource name,1 (32)
Portability:
Htons and htonl are now machine independent.
Fixed up many complaints from lint. Unfortunately, I got
bored and didn't finish the job, so there are still lots
of places where type 'int' is assumed to be 32 bits.
Type DITL:
ResCItem keyword now recognized.
Used to require 2 blank lines after a UserItem. Now only 1.
Case is no longer significant in recognizing keywords.
BtnItem, btnitem, etc are all acceptable.
At least 1 item type keyword must now be present for each item.
\ escape sequences are now interpreted within item titles.
Type WIND, DLOG, CNTL:
There used to be no checking for the validity of keywords
GoAway, NoGoAway, Visible, and Invisible. Previously,
"goaway" was interpreted the same as "NoGoAway".
Now the keywords are checked, and case is no longer significant.
Type DLOG ignores leading whitespace in the dialog title.
Type MENU:
Now allows an optional menu definition id before the title.
Type PICT added.
Type PICT
picture-file,1
Type FILE added.
Reads a file into a resource. Replacement for Type ANYB,
which is inconvenient to use in the normal case when you want
to read the entire file.
Type FILE
file-name,1
Type GNRL added.
Input is free format, with one or more tokens per line,
except for strings following .S or .P.
Input is terminated by the first blank line.
.I
succeeding number tokens are to be interpreted as
decimal 16 bit integers
.L
following numbers are decimal, 32 bit
.C
following numbers are decimal, 8 bit
.H
following numbers are hexadecimal
'string'
output the contained ascii characters
"string"
output the string in Pascal format, with a length byte
.F filename
interpolate the contents of the named file
.S
following lines contain strings without length bytes,
up to a blank line or a line whose first
non-blank character is '.'
.P
following lines contain pascal strings (with length byte)
Notes:
This implementation of GNRL is upward compatible with the Apple
syntax, except that .B is unsupported (replaced by .F).
To put a ' or " into a quoted string, use \' or \".
To put an empty string into .S or .P, use a line containing only "\"
If the first non-blank character of a string after .S or .P
is ".", then you need to write "\."
There is an implicit .I at the beginning of the input.
If all of your numbers are 16 bit decimal format, you
don't need to use .I anywhere. For example,
Type BNDL = GNRL
,128
'SAMP' 0
1
'ICN#' 0
1 128
'FREF' 0
1 128
or if you restrict yourself to Apple syntax,
Type BNDL = GNRL
,128
.S
SAMP
.I
0
1
.S
ICN#
.I
0
1
128
.S
FREF
.I
0
1
128
Type FREF added.
Type BNDL added.
@//E*O*F Changes//
chmod u=rw,g=rw,o=r Changes
echo x - Bugs
sed 's/^@//' > "Bugs" <<'@//E*O*F Bugs//'
A blank line is not tolerated after the item count in type DITL.
In general, the Lisa Workshop rmaker is much more tolerant about
blank lines, which are ignored everywhere except where they are
specifically required.
The usage:
Type FOO
,1
...whatever...
,2
...whatever...
is not recognized.
Type GNRL does not support .B format.
Then again, with .F, who cares.
If a trailing blank is present on a type line, eg
Type STR <- trailing blank
then Sumacc will abort. This is because of a bug in scanf().
Perhaps it would be appropriate to strip trailing whitespace
off each input line in getline().
Unimplemented types: PAT# FONT ANYB
(Type FILE has been provided to perform the function of ANYB)
Type ICN# is implemented the same as HEXA. I.M. says it is supposed
to start with a field giving the number of icons.
Types PAT, ICON and CURS do not check to see that their data
contains the correct number of bytes.
@//E*O*F Bugs//
chmod u=rw,g=rw,o=r Bugs
echo x - data.c
sed 's/^@//' > "data.c" <<'@//E*O*F data.c//'
/*
* data.c
*
* Routines for preparing binary data for the output file.
*/
#include "rmaker.h"
/*
* "Host" to "Mac" byte order swappers.
* (on the Mac, the high order byte of a word is stored first in memory,
* the low order byte is stored last.)
*/
unsigned short htons(a)
short a;
{
unsigned short result;
register char *dp = (char *)&result;
dp[0] = a >> 8;
dp[1] = a;
return result;
}
unsigned long htonl(a)
long a;
{
unsigned long result;
register char *dp = (char *)&result;
dp[0] = a >> 24;
dp[1] = a >> 16;
dp[2] = a >> 8;
dp[3] = a;
return result;
}
/*
* "Mac" to "host" byte order swapper
*/
unsigned short mtohs(a)
unsigned short a;
{
unsigned char *sp = (unsigned char *)&a;
unsigned short result = (sp[0] << 8) + sp[1];
return result;
}
reserve(bytesneeded)
int bytesneeded;
{
int bytesleft = sizeof data - (datap - data);
if (bytesleft < bytesneeded)
abort("Out of space in 'data' array. Make it bigger.");
}
/*
* Store a byte into the data area.
*/
databyte(n)
int n;
{
reserve(sizeof (char));
*datap++ = n;
}
/*
* Store a short into the data area.
*/
datashort(i)
short i;
{
reserve(sizeof (short));
*(unsigned short *)datap = htons(i);
datap += sizeof (short);
}
/*
* Store a long into the data area.
*/
datalong(i)
long i;
{
reserve(sizeof (long));
*(unsigned long *)datap = htonl(i);
datap += sizeof (long);
}
/*
* Store string into data area, expanding escape sequences.
* The PASCAL flag means store an initial length byte.
* The ROUND flag means pad the string to an even number of bytes.
*/
datastring(sp, flags)
char *sp;
int flags;
{
char *lenp;
int len;
if (flags & PASCAL)
lenp = datap++;
for (len = 0 ; *sp ; len++) {
/*
* \HH where HH are two hex digits emits ASCII code HH;
* \anything-else emits anything-else.
*/
if (*sp == '\\') {
if (ishex(sp[1]) && ishex(sp[2])) {
*datap++ = tohex(sp[1])*16 + tohex(sp[2]);
sp += 3;
} else
++sp;
} else
*datap++ = *sp++;
}
if (flags & ROUND && len & 1) {
*datap++ = 0;
++len;
}
if (flags & PASCAL)
*lenp = len;
return len;
}
ishex(c)
char c;
{
return c >= '0' && c <= '9' || c >= 'A' && c <= 'F' ||
c >= 'a' && c <= 'f';
}
tohex(c)
char c;
{
if (c >= 'a') return c - 'a' + 10;
if (c >= 'A') return c - 'A' + 10;
return c - '0';
}
/*
* Read a file and add it to the data area.
*/
datafile(f)
FILE *f;
{
struct stat statBuf;
if (fstat(fileno(f), &statBuf) < 0)
abort("fstat failed"); /* can't happen */
reserve(statBuf.st_size);
if (fread(datap, sizeof (char), statBuf.st_size, f) != statBuf.st_size)
abort("can't read file"); /* can't happen */
datap += statBuf.st_size;
}
@//E*O*F data.c//
chmod u=rw,g=rw,o=r data.c
echo x - rmaker.h
sed 's/^@//' > "rmaker.h" <<'@//E*O*F rmaker.h//'
#include <stdio.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <mac/res.h>
#include <mac/quickdraw.h>
#include <mac/toolintf.h>
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 */
long 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 */
} *rcp;
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 token[128]; /* current token being scanned */
char data[8*1024]; /* area to build simple resource data */
char *datap; /* pointer to data area */
FILE *fin; /* file for compiler commands */
/* Keyword/value pair for scankeys() */
struct keylist {
char *keyname;
int keyvalue;
};
/* Flags for datastring() */
#define PASCAL 01
#define ROUND 02
char *malloc();
char *index();
unsigned short htons(); /* host to "net" byte order, short. */
unsigned long htonl();
@//E*O*F rmaker.h//
chmod u=rw,g=rw,o=r rmaker.h
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=rw,g=rw,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=rw,g=rw,o=r crtproc.s
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,
PICT, FILE, BNDL, GNRL, FREF,
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
Backslash escape sequences are allowed in strings in the form \\hh where
"hh" are two hexadecimal digits.
@.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
Types NOT implemented: PAT#, FONT, ANYB.
You can always use an "inherited type" of HEXA (e.g. Type PAT# = HEXA)
to simulate unimplemented types.
(Type FILE has been provided to perform the function of ANYB)
@.PP
A blank line is not tolerated after the item count in type DITL.
In general, the Lisa Workshop rmaker is much more tolerant about
blank lines, which are ignored everywhere except where they are
specifically required.
@.PP
The usage:
@.TP
Type FOO
@.br
,1
@.br
<data>
@.br
,2
@.br
<data>
@.PP
is not recognized. (i.e., you must specify Type FOO for each.)
@.PP
Type GNRL does not support .B format.
Then again, with .F, who cares.
@.PP
If a trailing blank is present on a type line, e.g.
@.TP
Type STR <- trailing blank
@.PP
then Sumacc will abort. This is because of a bug in scanf().
Perhaps it would be appropriate to strip trailing whitespace
off each input line in getline().
@.PP
Type ICN# is implemented the same as HEXA. I.M. says it is supposed
to start with a field giving the number of icons.
@.PP
Types PAT, ICON and CURS do not check to see that their data
contains the correct number of bytes.
@.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=rw,g=rw,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/11/85 Brian Powell mention backslash escapes
12/23/85 Brian Powell Show input format changes
implemented by Doug Moen
_______________________________________________________________________________
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. *** For now, the filename
is ignored, and you must completely specify the data. ***
- 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.
- In general, all strings may include backslash escape characters.
(\XX where X is a hexadecimal digit.) \ followed by "anything else"
is replaced by "anything else". For example,
\\ is a backslash.
\' and \" permit quotes to be put in quoted strings in type GNRL.
\<space> can be used to introduce a leading space in a title.
\<newline> turns into a blank line in STR# and POST string lists.
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
ResCItem Enabled Control defined in control template
60 30 80 100 Display rectangle
128 Resource ID of control template
UserItem Disabled Application-defined item
20 50 60 85 Display rectangle
Type ICON An Icon
,1 Resource ID
0380 0000 0380 0000 0380 0000 0380 0000 The icon in hexadecimal
0380 0000 0380 0000 0380 0000 0380 0000
0380 0000 0380 0000 0380 0000 0380 0000
0380 0000 0380 0000 0380 0000 0380 0000
1EC0 3180 1EC0 3180 1EC0 3180 1EC0 3180
1EC0 3180 1EC0 3180 1EC0 3180 1EC0 3180
1EC0 3180 1EC0 3180 1EC0 3180 1EC0 3180
1EC0 3180 1EC0 3180 1EC0 3180 1EC0 3180
Type ICN# Icon list
,128 Resource ID
0380 0000 0380 0000 0380 0000 0380 0000 The icons in hexadecimal
0380 0000 0380 0000 0380 0000 0380 0000 (specify an id and 128 bytes
0380 0000 0380 0000 0380 0000 0380 0000 for each.)
0380 0000 0380 0000 0380 0000 0380 0000
1EC0 3180 1EC0 3180 1EC0 3180 1EC0 3180
1EC0 3180 1EC0 3180 1EC0 3180 1EC0 3180
1EC0 3180 1EC0 3180 1EC0 3180 1EC0 3180
1EC0 3180 1EC0 3180 1EC0 3180 1EC0 3180
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 (use "STR" instead of "STR ". (BUG))
,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 File reference
,128 Resource ID
APPL 0 TgFile File type, local ID of icon, filename
(the filename is optional)
Type HEXA Any bytes specified here
,9 Resource ID
526FEEC942E78EA4 The bytes in hexadecimal (any number
0F4C total, any nuber per line)
Blank line required at end
Type POST Postscript resource
,1 Resource ID
This is string one The strings...
This is string two
Third string
Bench warmer Apple's joke, not mine.
Type PICT A Picture (see the quickdraw documentation)
picture-file,1 File resource ID
Type FILE Reads a file into a resource. Replaces type
file-name,1 ANYB, but reads entire file.
* 3 different ways to do a bundle,
* illustrating types BNDL and GNRL
Type BNDL Bundle
,128 Resource ID
SAMP 0 Bundle owner SAMP 0
2 Two types in bundle (ICN# and FREF)
ICN# 1 ICN# number of resources
0 128 local ID 0 maps to resource ID 128
FREF 1 FREF number of resources
0 128 local ID 0 maps to resource ID 128
Type BNDL = GNRL Type General (more on GNRL below)
,129
'SAMP' 0 store data string
1 number of resources minus 1
'ICN#' 0 number of ICN#'s minus 1
0 128
'FREF' 0
0 128
Type BNDL = GNRL
,130
.S store data string
SAMP
.I store decimal integer
0
1
.S
ICN#
.I
0
0
128
.S
FREF
.I
0
0
128
Type CODE Application code segments
samp.o,0 Linker output file name, resource ID
[ SEE NOTE 3 BELOW ]
Notes:
1. The Resource Compiler adds a NUL character (ASCII 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.
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.
More on Type GNRL:
Input is free format, with one or more tokens per line,
except for strings following .S or .P.
Input is terminated by the first blank line.
.I
succeeding number tokens are to be interpreted as
decimal 16 bit integers
.L
following numbers are decimal, 32 bit
.C
following numbers are decimal, 8 bit
.H
following numbers are hexadecimal
'string'
output the contained ascii characters
"string"
output the string in Pascal format, with a length byte
.F filename
interpolate the contents of the named file
.S
following lines contain strings without length bytes,
up to a blank line or a line whose first
non-blank character is '.'
.P
following lines contain pascal strings (with length byte)
Notes:
This implementation of GNRL is upward compatible with the Apple
syntax, except that .B is unsupported (replaced by .F).
To put a ' or " into a quoted string, use \' or \".
To put an empty string into .S or .P, use a line containing only "\"
If the first non-blank character of a string after .S or .P
is ".", then you need to write "\."
There is an implicit .I at the beginning of the input.
If all of your numbers are 16 bit decimal format, you
don't need to use .I anywhere. For example,
Type BNDL = GNRL
,128
'SAMP' 0
1
'ICN#' 0
1 128
'FREF' 0
1 128
@//E*O*F rmaker.doc//
chmod u=rw,g=rw,o=r rmaker.doc
echo x - samp.rc
sed 's/^@//' > "samp.rc" <<'@//E*O*F samp.rc//'
* samp.rc -- Resource input for sample application
*
samp.rsrc
Type SAMP = STR
,0
Samp Version 1.0 -- January 13, 1984
* Type CODE
* samp.o,0
Type WIND
,1
Status Report
40 80 120 300
Visible GoAway
0
0
Type MENU
,2
Edit
Cut/X
Paste/Z
(-
Word Wrap!
Type CNTL
,1
Help
55 20 75 90
Visible
0
1
0 0 0
Type DLOG
,1
100 100 190 250
Visible 1 GoAway 0
3
Type ALRT
,1
120 100 190 250
5
F721
Type DITL
,3
5
BtnItem Enabled
60 10 80 70
Start
ResCItem Enabled
60 30 80 100
128
StatText Disabled
10 93 26 130
Seed
IconItem Disabled
10 24 42 56
128
UserItem Disabled
20 50 60 85
Type ICON
,1
0380 0000 0380 0000 0380 0000 0380 0000
0380 0000 0380 0000 0380 0000 0380 0000
0380 0000 0380 0000 0380 0000 0380 0000
0380 0000 0380 0000 0380 0000 0380 0000
1EC0 3180 1EC0 3180 1EC0 3180 1EC0 3180
1EC0 3180 1EC0 3180 1EC0 3180 1EC0 3180
1EC0 3180 1EC0 3180 1EC0 3180 1EC0 3180
1EC0 3180 1EC0 3180 1EC0 3180 1EC0 3180
Type ICN#
,128
0380 0000 0380 0000 0380 0000 0380 0000
0380 0000 0380 0000 0380 0000 0380 0000
0380 0000 0380 0000 0380 0000 0380 0000
0380 0000 0380 0000 0380 0000 0380 0000
1EC0 3180 1EC0 3180 1EC0 3180 1EC0 3180
1EC0 3180 1EC0 3180 1EC0 3180 1EC0 3180
1EC0 3180 1EC0 3180 1EC0 3180 1EC0 3180
1EC0 3180 1EC0 3180 1EC0 3180 1EC0 3180
Type CURS
,300
7FFC 287F 7FFC 287F 7FFC 287F 7FFC 287F
7FFC 287F 7FFC 287F 7FFC 287F 7FFC 287F
0FC0 1FF8 0FC0 1FF8 0FC0 1FF8 0FC0 1FF8
0FC0 1FF8 0FC0 1FF8 0FC0 1FF8 0FC0 1FF8
0008 0008
Type PAT
,200
AADDAA66AADDAA66
Type STR
,36
This is your string
Type STR#
,1
This is string one
This is string two
This is string three
* Type DRVR
* Monkey/Monkey,17 (32)
Type FREF
,128
APPL 0 TgFile
Type HEXA
,9
526FEEC942E78EA4
0F4C
Type POST
,1
4
This is string one
This is string two
Third string
Bench warmer
* 3 different ways to do a bundle,
* illustrating types BNDL and GNRL
Type BNDL
,128
SAMP 0
2
ICN# 1
0 128
FREF 1
0 128
Type BNDL = GNRL
,129
'SAMP' 0
1
'ICN#' 0
0 128
'FREF' 0
0 128
Type BNDL = GNRL
,130
.S
SAMP
.I
0
1
.S
ICN#
.I
0
0
128
.S
FREF
.I
0
0
128
@//E*O*F samp.rc//
chmod u=rw,g=rw,o=r samp.rc
echo x - test.rc
sed 's/^@//' > "test.rc" <<'@//E*O*F test.rc//'
test.rsrc
Type GNRL
|foobar,42
.C 100
.I 100
.L 100
.H afafaf
'foo'
"foo"
.F foo
@//E*O*F test.rc//
chmod u=rw,g=rw,o=r test.rc
exit 0brian@ut-sally.UUCP (Brian H. Powell) (12/25/85)
# 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 <mac/b.out.h>
#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<<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, PASCAL);
*datap++ = iconid;
*datap++ = cmdid;
*datap++ = markid;
*datap++ = styleid;
}
/* end of items */
*datap++ = 0;
*flagsp = htonl(flags);
}
handpict()
{
unsigned short pictSize;
if (fread((char *)&pictSize, sizeof pictSize, 1, rcp->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