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