koreth@ssyx.ucsc.edu (Steven Grimm) (06/15/88)
Submitted-by: uunet!van-bc!resrch!bobs (Robert J. Silliker)
Posting-number: Volume 1, Issue 57
Archive-name: rsctoc
[This takes a resource file and generates the equivalent
C source file. -sg]
#!/bin/sh
# shar: Shell Archiver (v1.22)
#
# Run the following text with /bin/sh to create:
# MAIN.C
# MAKEFILE
# README
# RSCTOC.DOC
#
sed 's/^X//' << 'SHAR_EOF' > MAIN.C &&
X/***************************************************/
X/* */
X/* RSCTOC V1.0 */
X/* */
X/* Copyright (c) 1988, by Robert Joseph Silliker */
X/* All Rights Reserved */
X/* Permission is granted for unrestricted */
X/* non-commercial use */
X/* */
X/***************************************************/
X
X#include <stdio.h>
X#include <fcntl.h>
X#include <osbind.h>
X#include <gemdefs.h>
X#include <obdefs.h>
X
Xstatic char *copyright[] = "RSCTOC V1.0\nCopyright (c) 1988, by\
X Robert Joseph Silliker\nAll Rights Reserved\n\
X Permission is granted for unrestricted non-commercial use\n";
X
Xlong _stksize = 16000;
X
XRSHDR *rschead; /* Pointer to the resource file header. */
Xchar *out_path = NULL; /* Path to output file. */
Xchar *rsc_path = NULL; /* Path to input file. */
XFILE *fp = stdout; /* Default output file. */
Xchar *prefix= ""; /* Prefix to the names of arrays. */
X
X#define MAXTREES 512 /* Maximum number of object trees per file. */
X
XOBJECT *objects; /* Pointer to the base of the objects. */
XOBJECT *trindex[MAXTREES]; /* One pointer per object tree. */
X
Xchar *progname = "rsctoc.ttp"; /* Program name (no argv[0]) */
X
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X int i;
X extern char *rsc_path, *out_path, *prefix;
X extern FILE *fp;
X
X if((argc != 2) && (argc != 4) && (argc != 6))
X usage("Incorrect number of arguments.");
X
X rsc_path = argv[1];
X
X for(i=2; i<argc; i+=2) { /* This lets option arguments like */
X if(!strcmp(argv[i], "-p")) /* rsctoc.ttp rsc_file -f file1 -f file2 */
X prefix = argv[i+1]; /* rsctoc.ttp rsc_file -p XXXX -p YYYY */
X else if(!strcmp(argv[i], "-o")) /* without a usage error. */
X out_path = argv[i+1];
X else
X usage("Illegal option.");
X }
X
X if(!init_prog()) {
X put_header();
X make_tedinfo();
X make_icon();
X make_bitblk();
X make_object();
X make_index();
X make_fix();
X }
X
X clean_up();
X}
X
X
X/*----------------------------------------*/
X/* Output the usage message and terminate */
X/* the program. */
X/*----------------------------------------*/
X
Xusage(s)
Xchar *s;
X{
X extern char *progname;
X
X if(s)
X fprintf(stderr, "%s: %s\n", progname, s);
X
X fprintf(stderr, "Usage: %s rsc_file [-p prefix] [-o outfile]\n", progname);
X
X exit(2);
X}
X
X
X/*-------------------------------------------*/
X/* Output an error message and terminate the */
X/* program gracefully if the caller sets the */
X/* terminate flag. The value of the flag */
X/* used to terminate is returned by the */
X/* program. */
X/*-------------------------------------------*/
X
Xmperror(terminate, s)
Xint terminate;
Xchar *s;
X{
X extern char *progname;
X
X fprintf(stderr, "%s: %s\n", progname, s);
X
X if(terminate) {
X clean_up();
X exit(terminate);
X }
X}
X
X
X/*-------------------------*/
X/* Initialize the program. */
X/*-------------------------*/
X
Xint init_prog()
X{
X int i;
X extern char *rsc_path, *out_path;
X extern FILE *fp;
X extern RSHDR *rschead;
X
X if(!myrsrc_load(rsc_path))
X mperror(1, "Error getting resource file.");
X
X if(out_path != NULL) {
X if((fp = fopen(out_path, "w")) == NULL)
X mperror(1, "Can't open output file.");
X }
X
X if(rschead->rsh_nobs <= 0)
X mperror(1, "No object trees to dump.");
X
X return(0);
X}
X
X
X/*--------------------------------------------*/
X/* Clean up open files, close the workstation */
X/* and close the aes application. */
X/*--------------------------------------------*/
X
Xclean_up()
X{
X extern FILE *fp;
X
X if((fp != stdout) && (fp != NULL))
X fclose(fp);
X}
X
X
X/*------------------------------*/
X/* Extract tedinfo information. */
X/*------------------------------*/
X
Xmake_tedinfo()
X{
X int i, first_one;
X register OBJECT *g;
X TEDINFO *t;
X extern char *prefix;
X extern FILE *fp;
X extern OBJECT *objects;
X extern RSHDR *rschead;
X
X fprintf(fp, "TEDINFO %srs_tedinfo[] = {\n", prefix);
X
X for(i=0, first_one=1, g=objects; i < rschead->rsh_nobs; i++, g++) {
X if(g->ob_type == G_FTEXT || g->ob_type == G_FBOXTEXT ||
X g->ob_type == G_TEXT || g->ob_type == G_BOXTEXT) {
X
X if(first_one) {
X first_one = 0;
X }
X else
X fprintf(fp, ",\n");
X
X t = (TEDINFO *)(g->ob_spec);
X
X if(strlen(t->te_ptext))
X fprintf(fp, " {\"%s\", ", t->te_ptext);
X else
X fprintf(fp, " {%sp_to_nul, ", prefix);
X
X if(strlen(t->te_ptmplt))
X fprintf(fp, "\"%s\", ", t->te_ptmplt);
X else
X fprintf(fp, "%sp_to_nul, ", prefix);
X
X if(strlen(t->te_pvalid))
X fprintf(fp, "\"%s\",\n ", t->te_pvalid);
X else
X fprintf(fp, "%sp_to_nul,\n ", prefix);
X
X fprintf(fp, "%3d, ", t->te_font);
X fprintf(fp, "%3d, ", t->te_junk1);
X fprintf(fp, "%3d, ", t->te_just);
X fprintf(fp, "%3d, ", t->te_color);
X fprintf(fp, "%3d, ", t->te_junk2);
X fprintf(fp, "%3d, ", t->te_thickness);
X fprintf(fp, "%3d, ", t->te_txtlen);
X fprintf(fp, "%3d}", t->te_tmplen);
X }
X }
X
X if(!first_one)
X fprintf(fp, "\n};\n\n");
X else
X fprintf(fp, " 0L\n};\n\n");
X}
X
X
X/*---------------------------*/
X/* Extract icon information. */
X/*---------------------------*/
X
Xmake_icon()
X{
X int i, j, k, numb;
X int first_one, *p;
X register OBJECT *g;
X extern char *prefix;
X ICONBLK *icon;
X extern FILE *fp;
X extern OBJECT *objects;
X extern RSHDR *rschead;
X
X for(i=0, numb=0, g=objects; i < rschead->rsh_nobs; i++, g++) {
X /*----------------------*/
X /* First do the images. */
X /*----------------------*/
X
X if(g->ob_type == G_ICON) {
X icon = (ICONBLK *)(g->ob_spec);
X
X fprintf(fp, "int %simask%03d[] = {", prefix, numb);
X k = icon->ib_hicon * (icon->ib_wicon/16);
X
X for(j=0, p=icon->ib_pmask; k > 0; j++, p++, k--) {
X if(!(j % 8))
X fprintf(fp, "\n ");
X fprintf(fp, "0x%04x", *p);
X
X if(k != 1)
X fprintf(fp, ",");
X }
X fprintf(fp, "\n};\n\n");
X
X fprintf(fp, "int %sidata%03d[] = {", prefix, numb);
X k = icon->ib_hicon * (icon->ib_wicon/16);
X
X for(j=0, p=icon->ib_pdata; k > 0; j++, p++, k--) {
X if(!(j % 8))
X fprintf(fp, "\n ");
X fprintf(fp, "0x%04x", *p);
X
X if(k != 1)
X fprintf(fp, ",");
X }
X
X fprintf(fp, "\n};\n\n");
X numb++;
X }
X }
X
X fprintf(fp, "ICONBLK %srs_iconblk[] = {\n", prefix);
X
X for(i=0, numb=0, g=objects, first_one=1; i < rschead->rsh_nobs; i++, g++) {
X /*-----------------------------*/
X /* Now do the icon structures. */
X /*-----------------------------*/
X
X if(g->ob_type == G_ICON) {
X
X if(first_one)
X first_one = 0;
X else
X fprintf(fp, ",\n");
X
X icon = (ICONBLK *)(g->ob_spec);
X
X fprintf(fp, " {%simask%03d, %sidata%03d, ", prefix, numb, prefix, numb);
X
X if(strlen(icon->ib_ptext))
X fprintf(fp, "\"%s\",\n", icon->ib_ptext);
X else
X fprintf(fp, "%sp_to_nul, \n", prefix);
X
X fprintf(fp, " 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x,\n",
X icon->ib_char, icon->ib_xchar, icon->ib_ychar,
X icon->ib_xicon, icon->ib_yicon, icon->ib_wicon);
X
X fprintf(fp, " 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x}",
X icon->ib_hicon, icon->ib_xtext, icon->ib_ytext,
X icon->ib_wtext, icon->ib_htext);
X numb++;
X }
X }
X
X if(!first_one)
X fprintf(fp, "\n};\n\n");
X else
X fprintf(fp, " 0L\n};\n\n");
X}
X
X
X
X/*-----------------------------*/
X/* Extract bitblk information. */
X/*-----------------------------*/
X
Xmake_bitblk()
X{
X int i, j, k, numb;
X int first_one, *p;
X register OBJECT *g;
X BITBLK *bitblk;
X extern char *prefix;
X extern FILE *fp;
X extern OBJECT *objects;
X extern RSHDR *rschead;
X
X for(i=0, numb=0, g=objects; i < rschead->rsh_nobs; i++, g++) {
X /*----------------------*/
X /* First do the images. */
X /*----------------------*/
X
X if(g->ob_type == G_IMAGE) {
X bitblk = (BITBLK *)(g->ob_spec);
X
X fprintf(fp, "int %sbblock%03d[] = {", prefix, numb);
X k = bitblk->bi_hl * (bitblk->bi_wb/2);
X
X for(j=0, p=bitblk->bi_pdata; k > 0; j++, p++, k--) {
X if(!(j % 8))
X fprintf(fp, "\n ");
X fprintf(fp, "0x%04x", *p);
X
X if(k != 1)
X fprintf(fp, ",");
X }
X fprintf(fp, "\n};\n\n");
X
X numb++;
X }
X }
X
X fprintf(fp, "BITBLK %srs_bitblk[] = {\n", prefix);
X
X for(i=0, numb=0, g=objects, first_one=1; i < rschead->rsh_nobs; i++, g++) {
X /*-------------------------------*/
X /* Now do the bitblk structures. */
X /*-------------------------------*/
X
X if(g->ob_type == G_IMAGE) {
X
X if(first_one)
X first_one = 0;
X else
X fprintf(fp, ",\n");
X
X bitblk = (BITBLK *)(g->ob_spec);
X
X fprintf(fp, " {%sbblock%03d, ", prefix, numb);
X
X fprintf(fp, " 0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x}",
X bitblk->bi_wb, bitblk->bi_hl, bitblk->bi_x,
X bitblk->bi_y, bitblk->bi_color);
X
X numb++;
X }
X }
X
X if(!first_one)
X fprintf(fp, "\n};\n\n");
X else
X fprintf(fp, " 0L\n};\n\n");
X}
X
X
X/*-----------------------------------------------*/
X/* Extract object information and change into C. */
X/*-----------------------------------------------*/
X
Xmake_object()
X{
X int i, ic, bb, ted;
X int first_one;
X register OBJECT *g;
X extern char *prefix;
X extern FILE *fp;
X extern OBJECT *objects;
X extern RSHDR *rschead;
X
X for(i=0,ic=0,bb=0,ted=0,g=objects,first_one=1; i<rschead->rsh_nobs;i++,g++) {
X if(first_one) {
X fprintf(fp, "OBJECT %srs_object[] = {\n", prefix);
X first_one = 0;
X }
X else
X fprintf(fp, ",\n");
X
X print_index_comment(g);
X
X fprintf(fp, " {%4d,%4d,%4d,0x%04x,0x%04x,0x%04x, ",
X g->ob_next, g->ob_head, g->ob_tail,
X g->ob_type, g->ob_flags, g->ob_state);
X
X if(g->ob_type == G_STRING || g->ob_type == G_TITLE
X || g->ob_type == G_BUTTON) {
X
X if(strlen(g->ob_spec))
X fprintf(fp, "\"%s\",", g->ob_spec);
X else
X fprintf(fp, "%sp_to_nul,", prefix);
X }
X else if(g->ob_type == G_FTEXT || g->ob_type == G_FBOXTEXT
X || g->ob_type == G_TEXT
X || g->ob_type == G_BOXTEXT) {
X fprintf(fp, "\&%srs_tedinfo[%d],", prefix, ted);
X ted++;
X }
X else if(g->ob_type == G_ICON) {
X fprintf(fp, "\&%srs_iconblk[%d],", prefix, ic);
X ic++;
X }
X else if(g->ob_type == G_IMAGE) {
X fprintf(fp, "\&%srs_bitblk[%d],", prefix, bb);
X bb++;
X }
X else
X fprintf(fp, "0x%08lxL,", g->ob_spec);
X
X fprintf(fp, "%4d,%4d,%4d,%4d}",
X g->ob_x, g->ob_y, g->ob_width, g->ob_height);
X }
X
X if(!first_one)
X fprintf(fp, "\n};\n\n");
X}
X
X
X/*-----------------------------------------------*/
X/* Build the array of tree pointers and generate */
X/* the structure size macros. */
X/*-----------------------------------------------*/
X
Xmake_index()
X{
X int i, index, first_one;
X extern char *prefix;
X extern FILE *fp;
X extern OBJECT *objects, *trindex[];
X extern RSHDR *rschead;
X
X for(i=0, first_one=1; i < rschead->rsh_ntree; i++) {
X if(first_one) {
X fprintf(fp, "OBJECT *%srs_trindex[] = {\n", prefix);
X first_one = 0;
X }
X else
X fprintf(fp, ",\n");
X
X index = (trindex[i] - objects);
X
X fprintf(fp, " &%srs_object[%d]", prefix, index);
X }
X if(!first_one)
X fprintf(fp, "\n};\n\n");
X
X fprintf(fp, "#define %sNUM_TI %d\n", prefix, rschead->rsh_nted);
X fprintf(fp, "#define %sNUM_IB %d\n", prefix, rschead->rsh_nib);
X fprintf(fp, "#define %sNUM_BB %d\n", prefix, rschead->rsh_nbb);
X fprintf(fp, "#define %sNUM_OBS %d\n", prefix, rschead->rsh_nobs);
X fprintf(fp, "#define %sNUM_TREE %d\n\n\n", prefix, rschead->rsh_ntree);
X}
X
X
X/*------------------------------------------------------*/
X/* Output the include #ifdef for the object definition */
X/* header file. Output a single NUL character pointer */
X/* into the C source. This will be used as the pointer */
X/* to an empty character string wherever strings have */
X/* zero length. */
X/*------------------------------------------------------*/
X
Xput_header()
X{
X extern FILE *fp;
X
X fprintf(fp, "#ifndef OBJECT\n");
X fprintf(fp, "#include <obdefs.h>\n");
X fprintf(fp, "#endif\n\n");
X fprintf(fp, "static char %sp_to_nul[1] = \"\";\n\n", prefix);
X}
X
X
X/*-------------------------------------------*/
X/* Output code that will fix up the objects. */
X/*-------------------------------------------*/
X
Xmake_fix()
X{
X extern char *prefix;
X extern FILE *fp;
X
X fprintf(fp, "%sfix_objects()\n{\n", prefix);
X fprintf(fp, " register int i;\n\n");
X fprintf(fp, " for(i=0; i<%sNUM_OBS; i++)\n", prefix);
X fprintf(fp, " rsrc_obfix(%srs_object, i);\n", prefix);
X fprintf(fp, "}\n\n");
X}
X
X
X/*--------------------------------*/
X/* Open and read in the rsc file. */
X/* Then call the routine to fix */
X/* the object pointers. */
X/*--------------------------------*/
X
Xchar *pbase; /* Pointer to base of file in memory */
X#define BLKSIZE 8192 /* Number of bytes per read call */
X /* Don't make this larger than 32767 */
X
Xmyrsrc_load(path)
Xchar *path;
X{
X long fsize, lseek();
X int rsc, size;
X char *p;
X extern char *pbase;
X
X if((rsc = open(path, O_RDONLY | O_BINARY)) < 0) {
X fprintf(stderr, "%s: Can't open '%s'.\n", progname, path);
X return(0);
X }
X
X if((fsize = lseek(rsc, 0L, 2)) < 0)
X return(0);
X
X lseek(rsc, 0L, 0);
X
X if(fsize < sizeof(RSHDR)) {
X fprintf(stderr, "%s: Resource file is too small.\n", progname);
X close(rsc);
X return(0);
X }
X
X p = pbase = (char *)(Malloc(fsize));
X if(pbase == NULL) {
X fprintf(stderr, "%s: Not enough memory.\n", progname);
X close(rsc);
X return(0);
X }
X
X do {
X size = (fsize >= BLKSIZE) ? BLKSIZE : (int)(fsize);
X if(read(rsc, p, size) != size) {
X fprintf(stderr, "%s: Read error on '$s'.\n", progname, path);
X Mfree(pbase);
X close(rsc);
X return(0);
X }
X p += size;
X fsize -= (long)(size);
X } while(fsize > 0L);
X
X close(rsc);
X
X fix_pointers();
X
X return(1);
X}
X
X
X/*------------------------------------------*/
X/* Routine to fix up the resource pointers. */
X/*------------------------------------------*/
X
Xfix_pointers()
X{
X int i;
X long *t;
X extern char *pbase;
X extern OBJECT *objects, *trindex[];
X extern RSHDR *rschead;
X
X /*----------------------------------------------------*/
X /* Initialize the pointer to the resource file header */
X /* and a pointer to the base of the object array. */
X /*----------------------------------------------------*/
X
X rschead = (RSHDR *)(pbase);
X objects = (OBJECT *)(pbase + rschead->rsh_object);
X
X t = (long *)(pbase + rschead->rsh_trindex); /* Get pointer to trindex */
X
X for(i=0; i<rschead->rsh_ntree; i++)
X trindex[i] = (OBJECT *)(pbase + *(t+i)); /* Build tree pointer */
X
X /*---------------------------------------------------*/
X /* Fix all the objects. No need to go into the maze */
X /* of head, tail, next because all objects are in a */
X /* nice array of size 'rsh_nobs'. */
X /*---------------------------------------------------*/
X
X for(i=0; i<rschead->rsh_nobs; i++)
X fix_one_object(objects + i);
X}
X
X
X/*-------------------------------------*/
X/* Fix up the pointers for one object. */
X/*-------------------------------------*/
X
Xfix_one_object(g)
Xregister OBJECT *g;
X{
X TEDINFO *t;
X ICONBLK *icon;
X BITBLK *bitblk;
X extern char *pbase;
X
X switch(g->ob_type) {
X case(G_STRING):
X case(G_TITLE):
X case(G_BUTTON):
X g->ob_spec = (char *)(pbase + (long)(g->ob_spec));
X break;
X case(G_FTEXT):
X case(G_FBOXTEXT):
X case(G_TEXT):
X case(G_BOXTEXT):
X t = (TEDINFO *)(pbase + (long)(g->ob_spec));
X g->ob_spec = (char *)(t);
X t->te_ptext = (char *)(pbase + (long)(t->te_ptext));
X t->te_ptmplt = (char *)(pbase + (long)(t->te_ptmplt));
X t->te_pvalid = (char *)(pbase + (long)(t->te_pvalid));
X break;
X case(G_ICON):
X icon = (ICONBLK *)(pbase + (long)(g->ob_spec));
X g->ob_spec = (char *)(icon);
X icon->ib_pmask = (int *)(pbase + (long)(icon->ib_pmask));
X icon->ib_pdata = (int *)(pbase + (long)(icon->ib_pdata));
X icon->ib_ptext = (char *)(pbase + (long)(icon->ib_ptext));
X break;
X case(G_IMAGE):
X bitblk = (BITBLK *)(pbase + (long)(g->ob_spec));
X g->ob_spec = (char *)(bitblk);
X bitblk->bi_pdata = (int *)(pbase + (long)(bitblk->bi_pdata));
X break;
X }
X}
X
X
X/*---------------------------------*/
X/* Print the rs_trindex[] comment. */
X/*---------------------------------*/
X
Xprint_index_comment(g)
XOBJECT *g;
X{
X register int i;
X extern OBJECT *trindex[];
X extern FILE *fp;
X extern RSHDR *rschead;
X
X for(i=0; i<rschead->rsh_ntree; i++) {
X if(trindex[i] == g)
X fprintf(fp, " /* Tree #%d*/\n", i);
X }
X}
X
X/* END OF FILE */
X
SHAR_EOF
chmod 0600 MAIN.C || echo "restore of MAIN.C fails"
sed 's/^X//' << 'SHAR_EOF' > MAKEFILE &&
X#----------------------------------------------------------------------------
X# Makefile to make the program 'rsctoc.ttp'
X#----------------------------------------------------------------------------
X
XOBJECT = rsctoc.ttp
XFILES1 = main.o
X
X$(OBJECT): $(FILES1)
X $(CC) $(FILES1) -o $(OBJECT)
X
Xclean:
X $(RM) $(FILES1)
X $(RM) $(OBJECT)
X
Xarc:
X arc a rsctoc main.c makefile rsctoc.doc readme
X
X#----------------------------------------------------------------------------
SHAR_EOF
chmod 0600 MAKEFILE || echo "restore of MAKEFILE fails"
sed 's/^X//' << 'SHAR_EOF' > README &&
X
XRsctoc is a program to generate C code out of a resource file. It has been
Xwritten to be compiled with the Megamax Laser C compiler. I do not know
Xhow much work it would be to compile it with another compiler.
X
XThe makefile that I use will not be of much use. I have provided it only
Xas a guide.
X
XBob Silliker
SHAR_EOF
chmod 0600 README || echo "restore of README fails"
sed 's/^X//' << 'SHAR_EOF' > RSCTOC.DOC &&
X RSCTOC VERSION 1.0 RSCTOC
X
X
X NAME
X rsctoc.ttp - a program to generate C source from a resource file.
X
X AUTHOR
X Bob Silliker
X
X COPYRIGHT
X Copyright (c) 1988 by Robert Joseph Silliker
X All Rights Reserved.
X Permission is granted for unrestricted non-commercial use.
X
X SYNOPSIS
X rsctoc.ttp rsc_file [-p prefix] [-o file]
X
X DESCRIPTION
X Rsctoc is a program to generate C code from a resource file on an
X Atari St computer. It will handle the following types; OBJECT,
X TEDINFO, ICONBLK and BITBLK. If the command is executed with only
X a path to the rsc_file then the C code will be displayed on the
X screen. To send the output to a file you can use the '-o file'
X option or to redirect the output with '>file'.
X
X The C code that is generated includes a small routine to fixup the
X objects by calling rsrc_obfix() on each object to convert the
X object's location size from character coordinates to pixel coordinates.
X The routine is that is called to fixup the objects is 'fix_objects()'
X and should be called once during program initialization (calling it
X more than once is interesting but not useful).
X
X The -p prefix option is used to add a short unique prefix to the names
X of the structures, routine and macros that rsctoc creates. This is
X very useful when creating library routines that have trees embedded
X in them (providing a means of preventing name conflicts).
X
X If rsctoc is executed in the following way
X
X rsctoc rsc_file -p my -o file
X
X Then the C code generated would have 'my' added to the start of the
X structures, routine and macros.
X
X rs_tedinfo would be myrs_tedinfo
X NUM_TI would be myNUM_TI
X fix_objects would be myfix_objects
X
X NOTES
X The program DOES NOT generate the arrays rs_strings[], rs_frstr[],
X rsfrimg[], or rs_imdope[] arrays. The program DOES generate the
X arrays rs_tedinfo[], rs_object[], rs_trindex[], rs_bitblk[],
X rs_iconblk[] arrays as well as defines the macros NUM_TI, NUMOBS,
X NUM_TREE, NUM_BB and NUM_IB (modified by the prefix of course).
X
X Any names that you assigned to objects, trees, images or icons can
X still be used in your program to access these elements. The program
X will only handle 512 trees (not objects, images or icons which are
X only limited by the resource file structure) in one input resource
X file.
X
X BUGS
X There are no known bugs in V1.0. (:->)
X If you find one fix it.
SHAR_EOF
chmod 0600 RSCTOC.DOC || echo "restore of RSCTOC.DOC fails"
exit 0