home *** CD-ROM | disk | FTP | other *** search
/ Atari FTP / ATARI_FTP_0693.zip / ATARI_FTP_0693 / Tex / Dvi / shdvi10b.zoo / src / flib.c < prev    next >
C/C++ Source or Header  |  1990-08-23  |  45KB  |  1,727 lines

  1. /*
  2.  *    Fontlibrary program.
  3.  *
  4.  *        used for our TeX-system to save disk space and for
  5.  *        speed up the loading of fonts for "showdvi" and "dviprint".
  6.  *
  7.  *    This program is freely redistributable. You may modify and use this
  8.  *    program to your heart's content, so long as you send modifications
  9.  *    to Georg Hessmann or Robert Stabl. It can be included in any 
  10.  *    distribution, commercial or otherwise, so long as the banner string
  11.  *    defined in the constant HEADER is not modified (except for the version
  12.  *    number and the machine type) and this banner is printed on programs
  13.  *    invocation, or can be printed on programs invocation with the -? option.
  14.  *
  15.  *    For further information read the README file.
  16.  *
  17.  *      31.01.90        (C) Copyright Georg Hessmann.
  18.  *
  19.  *      12.02.90 v1.01    new flib-format, rename command
  20.  *
  21.  *      14.02.90  (rbs) ported to Atari ST
  22.  *
  23.  *      25.04.90  (jrb) fixed up for Atari ST gcc
  24.  *
  25.  *    05.06.90 v1.02    little bug fixes, add flib links (hes/rbs)
  26.  *
  27.  *    10.06.90  (rbs) fixed bug for Turbo_C argv[0]
  28.  *
  29.  *    23.08.90 v1.03    bug fix in adding files to existing lib
  30.  *          (rbs)    (only in version for Turbo C)
  31.  */
  32.  
  33.  
  34. /* Is the compiler a ANSI-C compiler */
  35. #ifdef AMIGA
  36. #  ifdef LATTICE
  37. #    define ANSI
  38. #  endif
  39. #  ifdef AZTEC_C
  40. #    undef ANSI
  41. #  endif /* AZTEC_C */
  42. #  ifdef _DCC
  43. #    define ANSI
  44. #  endif /* _DCC */
  45. #else
  46. #  ifdef ATARI
  47. #    ifdef __GNUC__
  48. #      define ANSI
  49. #    endif /* __GNUC__ */
  50. #  endif /* ATARI */
  51. #endif /* AMIGA */
  52.  
  53. /* standard includes */
  54. #include <stdio.h>
  55. #ifdef ANSI
  56. #  include <stdlib.h>
  57. #  include <string.h>
  58. #  ifdef AMIGA
  59. #    ifndef _DCC
  60. #      include <dos.h>
  61. #    endif /* !_DCC */
  62. #  endif /* AMIGA */
  63. #  ifdef ATARI
  64. #    ifndef __GNUC__
  65. #        include <tos.h>
  66. #        include <ext.h>
  67. #    else
  68. #        include <unixlib.h>
  69. #        include <fcntl.h>
  70. #        define S_IWRITE    W_OK
  71. #        define S_IREAD     R_OK
  72. #    endif /* __GNUC__ */
  73. #  endif /* ATARI */
  74. #endif /* ANSI */
  75.  
  76. #ifndef ANSI
  77. char *strchr();
  78. char *strrchr();
  79. #endif
  80.  
  81. /* open mode for files */
  82. #ifdef ATARI
  83. #  define OPEN_FOR_READING "rb"
  84. #  define OPEN_FOR_WRITING "wb"
  85. #  define OPEN_FOR_APPEND  "rb+"
  86. #  ifndef __GNUC__
  87.      extern int access(char *, int);
  88. #  endif /* __GNUC__ */
  89. #else
  90. #  define OPEN_FOR_READING "r"
  91. #  define OPEN_FOR_WRITING "w"
  92. #  define OPEN_FOR_APPEND  "r+"
  93. #endif
  94.  
  95. /* prototyping on/off */
  96. #ifdef ANSI
  97. #  define Args(x)    x
  98. #else
  99. #  define Args(x)    ()
  100. #endif /* ANSI */
  101.  
  102.  
  103. #ifdef AZTEC_C
  104.    void *malloc        Args((unsigned));
  105.    void free        Args((char *));
  106.    char *strchr();
  107.    char *strrchr();
  108. #endif /* AZTEC_C */
  109.  
  110.  
  111. #ifdef AMIGA
  112. #  ifdef LATTICE
  113. #    define perror(x)    poserr(x)
  114. #  endif /* LATTICE */
  115. #  ifdef AZTEC_C
  116. #    define remove(x)    unlink(x)
  117.      /* warning: AztecC seems to have problems with the returncode from fseek */
  118. #  endif /* AZTEC_C */
  119. #else AMIGA
  120. #  ifndef ANSI
  121. #    define remove(x)    unlink(x)
  122. #  endif /* ANSI */
  123. #endif /* AMIGA */
  124.  
  125. #ifdef ATARI
  126. #  include <errno.h>
  127. #else
  128. extern int errno;
  129. #endif
  130.  
  131. /*    Structure of a fontlibrary :
  132.  *    +---------------------------------------+
  133.  *    |   magic number        4 Bytes    |
  134.  *    |   number of direntries    4 Bytes    |
  135.  *    |   [flib_dirent]*            |
  136.  *    |   [modules]*                |
  137.  *    +---------------------------------------+
  138.  */
  139.  
  140.  
  141.  
  142. /* important constants */
  143. #define OLD_LIBMAGIC    0xA797F033L        /* magic number */
  144. #define LIBMAGIC    (((long)'F'<<24) | ((long)'L'<<16) | ((long)'I'<<8) | (long)'B')
  145. #define LNKMAGIC    (((long)'F'<<24) | ((long)'L'<<16) | ((long)'N'<<8) | (long)'K')
  146. #define FILENAMELEN    14
  147. #define NEWFILENAMELEN    22
  148. #define TMPFLIB        "tmpflib.tmp"
  149. #define BUFSIZE        20480
  150. #define DOSNAMESIZE    100
  151. #define MAXLINKLEVELS    20
  152.  
  153. #ifdef AMIGA
  154. #  define MACHINE    "AMIGA"
  155. #else
  156. #  ifdef ATARI
  157. #    define MACHINE    "ATARI"
  158. #  else
  159. #    define MACHINE    "UNIX"
  160. #    include <sys/file.h>
  161. #    define S_IWRITE    W_OK
  162. #    define S_IREAD    R_OK
  163. #  endif /* ATARI */
  164. #endif /* AMIGA */
  165.  
  166. #define VERSION        "1.03"
  167. #ifdef ATARI
  168. #  define HEADER        "FontLib Manager - Version %s for %s \275 1990 Georg Hessmann/Robert Stabl\n"
  169. #else
  170. #  define HEADER        "FontLib Manager - Version %s for %s (c) 1990 Georg Hessmann\n"
  171. #endif
  172.  
  173. #define    OLD_VERSION    0
  174. #define NEW_VERSION    1
  175.  
  176.  
  177. static char buffer[BUFSIZE];    /* used to copy modules */
  178.  
  179.  
  180. #ifndef FALSE
  181. #  define FALSE        0
  182. #endif /* FALSE */
  183. #ifndef TRUE
  184. #  define TRUE        (!FALSE)
  185. #endif /* TRUE */
  186.  
  187. #define offset(ptr,member)    ((long)(&((ptr)->member))-(long)(ptr))
  188.  
  189.  
  190. /************ structure definitions ***************/
  191. /* fontlib directory structures */
  192. struct flib_dirent { char mname[FILENAMELEN];        /* old version */
  193.                      long size;        /* size of pk-module in bytes */
  194.                      long where;    /* position in flib-file */
  195.                    };
  196.  
  197. struct new_flib_dirent { char  mname[NEWFILENAMELEN];    /* new version */
  198.              unsigned short checksum;
  199.              long  size;        /* size of pk-module in bytes */
  200.              long  where;        /* position in flib-file */
  201.                        };
  202.  
  203. union direntry { struct flib_dirent    old;
  204.          struct new_flib_dirent    new;
  205.            };
  206.  
  207.  
  208. /* internal representation of the flib-directory */
  209. struct dirlist { struct new_flib_dirent dirent;
  210.                  struct dirlist *next;
  211.            };
  212.  
  213. struct dir { long        total;
  214.          long        alloc;
  215.          int        version;    /* old or new flib */
  216.          int        is_link;
  217.              struct dirlist *dirlist;
  218.              char        real_name[DOSNAMESIZE];
  219.        };
  220.  
  221.  
  222. /*********   P R O T O T Y P E S   ********/
  223.  
  224.     /* main function                        */
  225. void main                Args((int argc, char *argv[]));
  226.  
  227.  
  228. /********* local functions **********/
  229.     /* print the help                        */
  230. static void  usage            Args((char *pname));
  231.     /* parse the first argument                    */
  232. static int   decode_args        Args((int argc, char **argv,
  233.                           int *table,
  234.                           int *extract,
  235.                           int *create,
  236.                           int *delete,
  237.                           int *compress,
  238.                           int *verbose,
  239.                           int *rename,
  240.                           int *test,
  241.                           int *link,
  242.                           int *term_input));
  243.     /* delete flib with the name "name" and rename the tmpflib to "name" */
  244.     /* nr is the number of modules in the flib => nr == 0 --> no flib    */
  245. static int   insert_name_into_dir    Args((char *name,
  246.                           struct dirlist **dirl,
  247.                           int version));
  248.     /* is module from "test" in "inp1" or "inp2" ? */
  249. static struct dirlist *exist_entry    Args((struct dirlist *inp1,
  250.                           struct dirlist *inp2,
  251.                           struct dirlist *test));
  252.     /* create a dirlist structure entry whith the module-name "name"    */
  253. static int   read_new_modules        Args((int term_input,
  254.                           int argc,
  255.                           char **argv,
  256.                           struct dir *directory,
  257.                           struct dirlist **start_dirl,
  258.                           int verbose));
  259.     /* read a list of modules from argv or from stdin        */
  260. static FILE *open_flib            Args((char *name,
  261.                           char *mode,
  262.                           struct dir *directory,
  263.                           short levels));
  264.     /* open a flib and test the magic-number            */
  265. static int   read_dir            Args((FILE *f,
  266.                           struct dir *directory));
  267.     /* read the directory from the flib (file-pointer must be on the first dir)       */
  268.     /* only this directory entries a correct where "where != 0" the others are unused */
  269. static void  print_dir            Args((struct dir *directory,
  270.                           char *lib_name,
  271.                           int verbose));
  272.     /* print the contents of the directory                */
  273. static int   ex_module            Args((struct dir *directory,
  274.                           char *mname,
  275.                           FILE *flib, int verbose));
  276.     /* search a module in the flib and copy it to a new file    */
  277. static int   create_new_flib        Args((struct dir *directory,
  278.                           char *name,
  279.                           int verbose));
  280.     /* create a complete (new) flib, copy only files into the flib    */
  281. static int   copy_module        Args((char *name,
  282.                           FILE *flib,
  283.                           long *size,
  284.                           long *where,
  285.                           unsigned short *check));
  286.     /* create a new flib and prepare the directory part        */
  287. static FILE *copy_directory        Args((struct dir *directory,
  288.                           char *name,
  289.                           int verbose));
  290.     /* copy a module (file) to the actual position in flib        */
  291. static FILE *copy_old_flib        Args((struct dir *directory,
  292.                           FILE *flib,
  293.                           char *name,
  294.                           int verbose));
  295.     /* copy the modules (from flib) with "where != 0" to flib (tmplib) */
  296. static int   append_modules_to_flib    Args((struct dir *directory,
  297.                           FILE *flib,
  298.                           int verbose));
  299.     /* copy the modules (files) with "where == 0" to flib (tmplib)     */
  300. static int   del_module_from_dir    Args((struct dir *directory,
  301.                           char *name,
  302.                           int verbose));
  303.     /* find a module and delete it from the directory list        */
  304. static void  copy_tmpflib        Args((char *name,
  305.                           long nr));
  306.     /* copy file source to file drain                 */
  307. static int   copy_file            Args((char *source,
  308.                           char *drain));
  309.     /* save directory to file                    */
  310. static int   update_dir            Args((struct dir *directory,
  311.                           FILE *flib,
  312.                           int verbose));
  313.     /* change module-names in directory                */
  314. static int   rename_entries        Args((struct dir *directory,
  315.                           struct dirlist *dirl,
  316.                           int verbose));
  317.     /* test all checksums of the fontlibrary            */
  318. static void  test_flib            Args((FILE *flib,
  319.                           struct dir *directory,
  320.                           int verbose));
  321.     /* read the directory structure                    */
  322. static int   freaddir            Args((union direntry *dir,
  323.                           int version,
  324.                           FILE *f));
  325.     /* read a four byte number <hihi lohi hilo lolo>        */
  326. static int   freadlong            Args((long *buf,
  327.                           FILE *f));
  328.     /* read a two byte number <hi lo>                */
  329. static int   freadshort            Args((unsigned short *buf,
  330.                           FILE *f));
  331.     /* write the directory structure                */
  332. static int   fwritedir            Args((union direntry *dir,
  333.                           int version,
  334.                           FILE *f));
  335.     /* write a four byte number <hihi lohi hilo lolo>        */
  336. static int   fwritelong            Args((long buf,
  337.                           FILE *f));
  338.     /* write a two byte number <hi lo>                */
  339. static int   fwriteshort        Args((unsigned short buf,
  340.                           FILE *f));
  341.  
  342.  
  343.  
  344. /********************   M A I N   ********************/
  345. void main(argc, argv)
  346.   int argc;
  347.   char *argv[];
  348. {
  349.   FILE *flib;
  350.   struct dir directory;
  351.   char input[256];
  352.   int table, extract, create, delete, compress, verbose, rename, test, link, term_input;
  353.   int i;
  354. #ifdef ATARI
  355. # ifndef __GNUC__
  356.   char progname [] = "flib";
  357.  
  358.   argv[0] = (char *)progname;
  359. # endif
  360. #endif
  361.  
  362.   if (argc < 3) {
  363.     usage(argv[0]);
  364.     exit(5);
  365.   }
  366.   directory.total   = directory.alloc = 0;
  367.   directory.dirlist = NULL;
  368.   directory.version = NEW_VERSION;    /* default version */
  369.   flib = NULL;
  370.  
  371.   if (!decode_args(argc, argv, &table, &extract, &create, &delete, &compress,
  372.         &verbose, &rename, &test, &link, &term_input)) {
  373.     usage(argv[0]);
  374.     exit(5);
  375.   }
  376.  
  377.   if (verbose) {
  378.     printf(HEADER,VERSION,MACHINE);
  379.   }
  380.  
  381.   /**************** extract **************/
  382.   if (extract) {
  383.     if ((flib = open_flib(argv[2],OPEN_FOR_READING,&directory,(short)0)) == NULL) {
  384.         exit(5);
  385.     }
  386.     if (!read_dir(flib,&directory)) {
  387.         exit(5);
  388.     }
  389.     if (term_input) {
  390.         while (!feof(stdin)) {
  391.             if (gets(input) != NULL) {
  392.                 (void)ex_module(&directory,input,flib,verbose);
  393.             }
  394.         }
  395.     }
  396.     else {
  397.             if(argc == 3) { /* extract all if no modules specified ++jrb */
  398.             struct dirlist *dl;
  399.             for(dl = directory.dirlist; dl != NULL; dl = dl->next)
  400.             (void)ex_module(&directory,dl->dirent.mname,flib,
  401.                     verbose);
  402.         }
  403.         else { /* extract only modules specified */
  404.             for (i=3; i<argc; i++) {
  405.             (void)ex_module(&directory,argv[i],flib,verbose);
  406.             }
  407.         }
  408.     }
  409.     fclose(flib);
  410.     flib = NULL;
  411.   }
  412.   /**************** create **************/
  413.   if (create) {
  414. #if defined(AMIGA)
  415.     if (access(argv[2],6) == 0) {    /* read + write */
  416. #else
  417.     if (access(argv[2],S_IWRITE | S_IREAD) == 0) {    /* read + write */
  418. #endif
  419.         struct dirlist *dirl, *start_dirl;
  420.         FILE *tmplib;
  421.         int nr;
  422.  
  423.         if ((flib = open_flib(argv[2],OPEN_FOR_READING,&directory,(short)0)) == NULL) {
  424.             exit(5);
  425.         }
  426.         if (!read_dir(flib,&directory)) {
  427.             exit(5);
  428.         }
  429.         /* append the rest */
  430.         /* internal directory */
  431.         for (dirl = directory.dirlist;
  432.             dirl != NULL && dirl->next != NULL;
  433.             dirl = dirl->next);
  434.         nr = read_new_modules(term_input,argc,argv,
  435.                     &directory,&start_dirl,verbose);
  436.         if (dirl == NULL) {
  437.             directory.dirlist = start_dirl;
  438.             directory.total = nr;
  439.         }
  440.         else {
  441.             dirl->next = start_dirl;
  442.             directory.total += nr;
  443.         }
  444.         directory.alloc += nr;
  445.         /* copy old flib with the new directory */
  446.         if ((tmplib = copy_old_flib(&directory,flib,argv[2],verbose)) == NULL) {
  447.             exit(5);
  448.         }
  449.         /* append the new modules */
  450.         if (!append_modules_to_flib(&directory,tmplib,verbose)) {
  451.             exit(5);
  452.         }
  453.         fclose(tmplib);
  454.         fclose(flib);
  455.         flib = NULL;
  456.         copy_tmpflib(directory.real_name,directory.total);
  457.     }
  458.     else {
  459.         directory.total = read_new_modules(term_input,argc,argv,
  460.                 &directory,&(directory.dirlist),verbose);
  461.         if (!create_new_flib(&directory,argv[2],verbose)) {
  462.             exit(5);
  463.         }
  464.     }
  465.   }
  466.   /**************** delete **************/
  467.   if (delete) {
  468.     FILE *tmplib;
  469.  
  470.     if ((flib = open_flib(argv[2],OPEN_FOR_READING,&directory,(short)0)) == NULL) {
  471.         exit(5);
  472.     }
  473.     if (directory.version == OLD_VERSION) {
  474.         if (verbose) {
  475.             printf("This option only works with the new flib-version!\n");
  476.             printf("Convert first the flib with \"flib z %s\"\n",argv[2]);
  477.         }
  478.         else {
  479.             fprintf(stderr,"Wrong flib-version!\n");
  480.         }
  481.     }
  482.     if (!read_dir(flib,&directory)) {
  483.         exit(5);
  484.     }
  485.     if (term_input) {
  486.         while (!feof(stdin)) {
  487.             if (gets(input) != NULL) {
  488.                 (void)del_module_from_dir(&directory,input,verbose);
  489.             }
  490.         }
  491.     }
  492.     else {
  493.         if (argc==3) {
  494.             if (verbose) {
  495.                 printf("No module to delete!?!\n");
  496.             }
  497.             fclose(flib);
  498.             flib = NULL;
  499.             exit(0);
  500.         }
  501.         else {
  502.             for (i=3; i<argc; i++) {
  503.                 (void)del_module_from_dir(&directory,argv[i],verbose);
  504.             }
  505.         }
  506.     }
  507.     /* copy old flib with the new directory */
  508.     if ((tmplib = copy_old_flib(&directory,flib,argv[2],verbose)) == NULL) {
  509.         exit(5);
  510.     }
  511.     /* append the new modules */
  512.     if (!append_modules_to_flib(&directory,tmplib,verbose)) {
  513.         exit(5);
  514.     }
  515.     fclose(tmplib);
  516.     fclose(flib);
  517.     flib = NULL;
  518.     copy_tmpflib(directory.real_name,directory.total);
  519.   }
  520.   /**************** compress **************/
  521.   if (compress) {
  522.     FILE *tmplib;
  523.  
  524.     if ((flib = open_flib(argv[2],OPEN_FOR_READING,&directory,(short)0)) == NULL) {
  525.         exit(5);
  526.     }
  527.     if (!read_dir(flib,&directory)) {
  528.         exit(5);
  529.     }
  530.     if (directory.version != NEW_VERSION) {
  531.         directory.version = NEW_VERSION;
  532.         if (verbose) {
  533.             printf("Converting old to new version.\n");
  534.         }
  535.     }
  536.     if (verbose) {
  537.         printf("Old directory size: %ld, new directory size: %ld.\n",
  538.             directory.alloc, directory.total);
  539.     }
  540.     /* copy old flib */
  541.     if ((tmplib = copy_old_flib(&directory,flib,argv[2],verbose)) == NULL) {
  542.         exit(5);
  543.     }
  544.     update_dir(&directory, tmplib, verbose);
  545.     fclose(tmplib);
  546.     fclose(flib);
  547.     flib = NULL;
  548.     copy_tmpflib(directory.real_name,directory.total);
  549.   }
  550.   /**************** rename **************/
  551.   if (rename) {
  552.     struct dirlist *dirl;
  553.     int nr;
  554.  
  555.     if ((flib = open_flib(argv[2],OPEN_FOR_APPEND,&directory,(short)0)) == NULL) {
  556.         exit(5);
  557.     }
  558.     if (directory.version == OLD_VERSION) {
  559.         if (verbose) {
  560.             printf("This option only works with the new flib-version!\n");
  561.             printf("Convert first the flib with \"flib z %s\"\n",argv[2]);
  562.         }
  563.         else {
  564.             fprintf(stderr,"Wrong flib-version!\n");
  565.         }
  566.     }
  567.     nr = read_new_modules(term_input,argc,argv,&directory,&dirl,verbose);
  568.     if (!read_dir(flib,&directory)) {
  569.         exit(5);
  570.     }
  571.     if (!rename_entries(&directory,dirl,verbose)) {
  572.         exit(5);
  573.     }
  574.     update_dir(&directory, flib, verbose);
  575.     fclose(flib);
  576.     flib = NULL;
  577.   }
  578.   /**************** test ***************/
  579.   if (test) {
  580.     if ((flib = open_flib(argv[2],OPEN_FOR_READING,&directory,(short)0)) == NULL) {
  581.         exit(5);
  582.     }
  583.     if (directory.version == OLD_VERSION) {
  584.         if (verbose) {
  585.             printf("This option only works with the new flib-version!\n");
  586.             printf("Convert first the flib with \"flib z %s\"\n",argv[2]);
  587.         }
  588.         else {
  589.             fprintf(stderr,"Wrong flib-version!\n");
  590.         }
  591.     }
  592.     else {
  593.         if (directory.alloc == 0 && !read_dir(flib,&directory)) {
  594.             exit(5);
  595.         }
  596.         test_flib(flib,&directory,verbose);
  597.     }
  598.     fclose(flib);
  599.     flib = NULL;
  600.   }
  601.   /**************** link ***************/
  602.   if (link) {
  603.     char link_name[DOSNAMESIZE];
  604.  
  605.     if ((flib = fopen(argv[2],OPEN_FOR_WRITING)) == NULL) {
  606.     }
  607.     else {
  608.         if (!fwritelong(LNKMAGIC,flib)) {
  609.             perror("*** ");
  610.             fprintf(stderr,"*** Can't write to LNK-flib \"%s\"!\n",
  611.                 argv[2]);
  612.             exit(5);
  613.         }
  614.         link_name[0] = '<';
  615.         link_name[1] = '\0';
  616.         strcat(link_name,argv[3]);
  617.         strcat(link_name,">");
  618.         if (fwrite(link_name,sizeof(char),strlen(link_name),flib) != strlen(link_name)) {
  619.             perror("*** ");
  620.             fprintf(stderr,"*** Can't write to LNK-flib \"%s\"!\n",
  621.                 argv[2]);
  622.             exit(5);
  623.         }
  624.         fclose(flib);
  625.         flib = NULL;
  626.     }
  627.   }
  628.   /**************** table **************/
  629.   if (table) {
  630.     if (flib == NULL) {
  631.         if ((flib = open_flib(argv[2],OPEN_FOR_READING,&directory,(short)0)) == NULL) {
  632.             exit(5);
  633.         }
  634.         if (directory.alloc == 0 && !read_dir(flib,&directory)) {
  635.             exit(5);
  636.         }
  637.     }
  638.     print_dir(&directory,argv[2],verbose);
  639.     fclose(flib);
  640.   }
  641. }    /* main */
  642.  
  643.  
  644. /* print the help */
  645. static void usage(pname)
  646.   char *pname;
  647. {
  648.   fprintf(stderr,HEADER,VERSION,MACHINE);
  649.   fprintf(stderr,"usage: %s c|a|x|d|z|p|l|t[v] library [-|[modules]*]\n",pname);
  650.   fprintf(stderr,"\tc,a : create library / add (replace) module(s) to (in) library,\n");
  651.   fprintf(stderr,"\tx   : extract module(s) from library,\n");
  652.   fprintf(stderr,"\td   : delete module(s) in library,\n");
  653.   fprintf(stderr,"\tt   : print table,\n");
  654.   fprintf(stderr,"\tr   : rename module(s) in library,\n");
  655.   fprintf(stderr,"\tz   : create new flib from old flib,\n");
  656.   fprintf(stderr,"\tp   : test checksums of all modules,\n");
  657.   fprintf(stderr,"\tl   : create a flib link (second arg is the link destination),\n");
  658.   fprintf(stderr,"\tv   : verbose mode,\n");
  659.   fprintf(stderr,"\t?   : print this help,\n");
  660.   fprintf(stderr,"\t-   : read module name(s) from stdin.\n");
  661. }
  662.  
  663. /* parse the first argument */
  664. static int decode_args(argc, argv, table, extract, create,
  665.         delete, compress, verbose, rename, test, link, term_input)
  666.   int argc;
  667.   char **argv;
  668.   int *table, *extract, *create, *delete, *compress, *verbose,
  669.         *rename, *test, *link, *term_input;
  670. {
  671.   char *flags;
  672.   int c;
  673.  
  674.   *table = *extract = *create = *delete = *compress = *verbose =
  675.         *rename = *test = *link = *term_input = FALSE;
  676.   flags = argv[1];
  677.   if (*flags == '-') {
  678.     flags++;
  679.   }
  680.   c = 0;
  681.   for (; *flags != '\0'; flags++) {
  682.     switch (*flags) {
  683.         case 'c':
  684.         case 'a': *create   = TRUE; c++; break;
  685.         case 'x': *extract  = TRUE; c++; break;
  686.         case 'd': *delete   = TRUE; c++; break;
  687.         case 'z': *compress = TRUE; c++; break;
  688.         case 'r': *rename   = TRUE; c++; break;
  689.         case 'l': *link     = TRUE; c++; break;
  690.         case 'p': *test     = TRUE; break;
  691.         case 't': *table    = TRUE; break;
  692.         case 'v': *verbose  = TRUE; break;
  693.         case '?': return FALSE;
  694.         default : fprintf(stderr, "*** Unknown flag '%c'!\n",*flags);
  695.               return FALSE;
  696.     }
  697.   }
  698.   if (c >= 2) {
  699.     fprintf(stderr,"*** The flags 'c' 'x' 'd' 'z' 'r' 'l' are mutual exclusive!\n");
  700.     return FALSE;
  701.   }
  702.   if (!(*extract || *create || *delete || *table || *compress || *rename || *test || *link)) {
  703.     fprintf(stderr,"*** Missing one of the flags 'c' 'x' 'd' 'z' 't' 'p' 'l'!\n");
  704.     return FALSE;
  705.   }
  706.   if (*link && argc != 4) {
  707.     fprintf(stderr,"*** Incorrect number of arguments!\n");
  708.     return FALSE;
  709.   }
  710.   if (argc > 3 && strcmp(argv[3],"-") == 0) {
  711.     *term_input = TRUE;
  712.     if (*verbose && (*create || *extract || *delete || *rename)) {
  713.         printf("Reading module names from standard input.\n");
  714.     }
  715.   }
  716.   return TRUE;
  717. }
  718.  
  719. /* delete flib with the name "name" and rename the tmpflib to "name" */
  720. /* nr is the number of modules in the flib => nr == 0 --> no flib */
  721. static void copy_tmpflib(name, nr)
  722.   char *name;
  723.   long nr;
  724. {
  725.   if (remove(name) != 0) {
  726.     perror("*** ");
  727.     fprintf(stderr,"*** Can't remove flib \"%s\"!\n",name);
  728.   }
  729.   if (nr > 0) {
  730.     if (rename(TMPFLIB,name) != 0) {
  731.         if (!copy_file(TMPFLIB,name)) {
  732.             perror("*** ");
  733.             fprintf(stderr,"*** Can't rename temporary flib \"%s\" to \"%s\"!\n",
  734.                 TMPFLIB,name);
  735.         }
  736.         if (remove(TMPFLIB) != 0) {
  737.             perror("*** ");
  738.             fprintf(stderr,"*** Can't remove temporary flib \"%s\"!\n",TMPFLIB);
  739.         }
  740.     }
  741.   }
  742.   else {
  743.     if (remove(TMPFLIB) != 0) {
  744.         perror("*** ");
  745.         fprintf(stderr,"*** Can't remove temporary flib \"%s\"!\n",TMPFLIB);
  746.     }
  747.   }
  748. }
  749.  
  750. /* copy file source to file drain                 */
  751. static int copy_file(source, drain)
  752.   char *source;
  753.   char *drain;
  754. {
  755.   FILE *sf, *df;
  756.   long len;
  757.  
  758.   if ((sf = fopen(source,OPEN_FOR_READING)) == NULL) {
  759.     return FALSE;
  760.   }
  761.   if ((df = fopen(drain,OPEN_FOR_WRITING)) == NULL) {
  762.     fclose(sf);
  763.     return FALSE;
  764.   }
  765.   while ((len = fread(buffer,sizeof(char),BUFSIZE,sf)) == BUFSIZE) {
  766.     if (fwrite(buffer,sizeof(char),BUFSIZE,df) != BUFSIZE) {
  767.         fclose(sf);
  768.         fclose(df);
  769.         return FALSE;
  770.     }
  771.   }
  772.   if (len > 0) {
  773.     if (fwrite(buffer,sizeof(char),len,df) != len) {
  774.         fclose(sf);
  775.         fclose(df);
  776.         return FALSE;
  777.     }
  778.   }
  779.   fclose(sf);
  780.   fclose(df);
  781.   
  782.   return TRUE;
  783. }
  784.  
  785. /* create a dirlist structure entry with the module-name "name" */
  786. static int insert_name_into_dir(name,dirl,version)
  787.   char *name;
  788.   struct dirlist **dirl;
  789.   int version;
  790. {
  791.   int j;
  792.  
  793.   if ((version == NEW_VERSION && strlen(name) > NEWFILENAMELEN-1) ||
  794.         (version == OLD_VERSION && strlen(name) > FILENAMELEN-1)) {
  795.     fprintf(stderr,"*** Module name \"%s\" too long!\n",name);
  796.     return FALSE;
  797.   }
  798.   if ((*dirl = (struct dirlist *)
  799.         malloc(sizeof(struct dirlist))) == NULL) {
  800.     fprintf(stderr,"*** No memory for internal flib directory!\n");
  801.     exit(5);
  802.   }
  803.   for (j=0; j<NEWFILENAMELEN; j++) {    /* clear the string */
  804.     (*dirl)->dirent.mname[j] = '\0';
  805.   }
  806.   strcpy((*dirl)->dirent.mname,name);
  807.   (*dirl)->dirent.size  = 0L;
  808.   (*dirl)->dirent.where = 0L;
  809.   (*dirl)->next = NULL;
  810.   return TRUE;
  811. }
  812.  
  813. /* is module from "test" in "inp1" or "inp2" ? */
  814. static struct dirlist *exist_entry(inp1, inp2, test)
  815.   struct dirlist *inp1, *inp2;
  816.   struct dirlist *test;        /* only one entry in list */
  817. {
  818.   char *name = test->dirent.mname;
  819.  
  820.   for (; inp1 != NULL && strcmp(name,inp1->dirent.mname) != 0; inp1 = inp1->next);
  821.   if (inp1 != NULL) {
  822.     return inp1;
  823.   }
  824.   for (; inp2 != NULL && strcmp(name,inp2->dirent.mname) != 0; inp2 = inp2->next);
  825.   if (inp2 != NULL) {
  826.     return inp2;
  827.   }
  828.   return NULL;
  829. }
  830.  
  831. /* read a list of modules from argv or from stdin */
  832. static int read_new_modules(term_input,argc,argv,directory,start_dirl,verbose)
  833.   int term_input;
  834.   int argc;
  835.   char **argv;
  836.   struct dir *directory;
  837.   struct dirlist **start_dirl;
  838.   int verbose;
  839. {
  840.   int nr_modules, i;
  841.   struct dirlist *dirl, *old_dirl, *find_old;
  842.   char input[256];
  843.  
  844.   old_dirl = dirl = NULL;
  845.   nr_modules = 0;
  846.   *start_dirl = NULL;
  847.  
  848.   if (term_input) {
  849.     while (!feof(stdin)) {
  850.         if (gets(input) != NULL) {
  851.             if (insert_name_into_dir(input, &dirl,directory->version)) {
  852.                 if ((find_old = exist_entry(directory->dirlist,
  853.                         *start_dirl,dirl)) != NULL) {
  854.                     /* the module is already in the lib */
  855.                     /* replace it */
  856.                     find_old->dirent.where = 0L;
  857.                     /* now it must new inserted */
  858.                     if (verbose) {
  859.                         printf("Replacing module \"%s\".\n",
  860.                             find_old->dirent.mname);
  861.                     }
  862.                 }
  863.                 else {
  864.                     nr_modules++;
  865.                     if (old_dirl == NULL) {
  866.                         *start_dirl = dirl;
  867.                     }
  868.                     else {
  869.                         old_dirl->next = dirl;
  870.                     }
  871.                     old_dirl = dirl;
  872.                 }
  873.             }
  874.         }
  875.     }
  876.   }
  877.   else {
  878.     for (i=3; i<argc; i++) {
  879.         if (insert_name_into_dir(argv[i], &dirl, directory->version)) {
  880.             if ((find_old = exist_entry(directory->dirlist,
  881.                         *start_dirl,dirl)) != NULL) {
  882.                 /* the module is already in the lib */
  883.                 /* replace it */
  884.                 find_old->dirent.where = 0L;
  885.                 /* now it must new inserted */
  886.                 if (verbose) {
  887.                     printf("Replacing module \"%s\".\n",
  888.                         find_old->dirent.mname);
  889.                 }
  890.             }
  891.             else {
  892.                 nr_modules++;
  893.                 if (old_dirl == NULL) {
  894.                     *start_dirl = dirl;
  895.                 }
  896.                 else {
  897.                     old_dirl->next = dirl;
  898.                 }
  899.                 old_dirl = dirl;
  900.             }
  901.         }
  902.     }
  903.   }
  904.   if (dirl != NULL) {
  905.     dirl->next = NULL;
  906.   }
  907.   return nr_modules;
  908. }
  909.  
  910.  
  911. /* open a flib and test the magic-number */
  912. static FILE *open_flib(name,mode,directory,levels)
  913.   char *name;
  914.   char *mode;
  915.   struct dir *directory;
  916.   short levels;
  917. {
  918.   static char link_name[DOSNAMESIZE];
  919.   char *ptr;
  920.   FILE *f;
  921.   long magic;
  922.  
  923.   directory->is_link = FALSE;
  924.   directory->real_name[0] = '\0';
  925.  
  926.   if ((f = fopen(name,mode)) == NULL) {
  927.     fprintf(stderr,"*** Can't open library \"%s\"!\n",name);
  928.     return NULL;
  929.   }
  930.   if (!freadlong(&magic,f) ||
  931.     (magic != LIBMAGIC && magic != OLD_LIBMAGIC && magic != LNKMAGIC)) {
  932.         fclose(f);
  933.         fprintf(stderr,"*** File \"%s\" isn't a font library!\n",name);
  934.         return NULL;
  935.   }
  936.   if (magic == LNKMAGIC) {
  937.     (void)fread(link_name,sizeof(char),DOSNAMESIZE,f);
  938.     fclose(f);
  939.     if (link_name[0] != '<') {
  940.         fprintf(stderr,"*** Illegal flib-link \"%s\"!\n",name);
  941.         return NULL;
  942.     }
  943.     ptr = strrchr(link_name,'>');
  944.     if (ptr == NULL) {
  945.         fprintf(stderr,"*** Illegal flib-link \"%s\"!\n",name);
  946.         return NULL;
  947.     }
  948.     levels++;
  949.     if (levels > MAXLINKLEVELS) {
  950.         fprintf(stderr,"*** To many link levels!\n");
  951.         return NULL;
  952.     }
  953.     *ptr = '\0';
  954.     ptr = link_name;
  955.     ptr++;
  956.     f = open_flib(ptr,mode,directory,levels);
  957.     directory->is_link = TRUE;
  958.   }
  959.   else {
  960.     if (magic == LIBMAGIC) {
  961.         directory->version = NEW_VERSION;
  962.     }
  963.     else {
  964.         directory->version = OLD_VERSION;
  965.     }
  966.     strcpy(directory->real_name,name);
  967.   }
  968.  
  969.   return f;
  970. }
  971.  
  972. /* read the directory from the flib (file-pointer must be on the first dir) */
  973. /* only this directory entries a correct where "where != 0" the others are unused */
  974. static int read_dir(f,directory)
  975.   FILE *f;
  976.   struct dir *directory;
  977. {
  978.   long alloc;
  979.   union direntry dir;
  980.   struct dirlist *direntr, *old_direntry;
  981.   int i, j, nr;
  982.  
  983.   if (!freadlong(&alloc,f)) {
  984.     fprintf(stderr,"*** Error while reading internal flib directory!\n");
  985.     return FALSE;
  986.   }
  987.   direntr = old_direntry = NULL;
  988.   for (i=0, nr=0; i<alloc && !feof(f); i++) {
  989.     if (!freaddir(&dir,directory->version,f)) {
  990.         fprintf(stderr,"*** Error while reading internal flib directory!\n");
  991.         return FALSE;
  992.     }
  993.     if ((directory->version == NEW_VERSION && dir.new.where != 0) ||    /* used entry */
  994.         (directory->version == OLD_VERSION && dir.old.where != 0)) {
  995.         nr++;
  996.         if ((direntr = (struct dirlist *)
  997.                 malloc(sizeof(struct dirlist))) == NULL) {
  998.             fprintf(stderr,"*** No memory for internal flib directory!\n");
  999.             return FALSE;
  1000.         }
  1001.         for (j=0; j<NEWFILENAMELEN; j++) {    /* clear the string */
  1002.             direntr->dirent.mname[j] = '\0';
  1003.         }
  1004.         if (old_direntry == NULL ) {
  1005.             directory->dirlist = direntr;
  1006.         }
  1007.         else {
  1008.             old_direntry->next = direntr;
  1009.         }
  1010.         if (directory->version == NEW_VERSION) {
  1011.             direntr->dirent = dir.new;
  1012.         }
  1013.         else {
  1014.             strncpy(direntr->dirent.mname,dir.old.mname,FILENAMELEN);
  1015.             direntr->dirent.size     = dir.old.size;
  1016.             direntr->dirent.where    = dir.old.where;
  1017.             direntr->dirent.checksum = 0;
  1018.         }
  1019.         old_direntry = direntr;
  1020.     }
  1021.   }
  1022.   if (direntr != NULL) {
  1023.     direntr->next = NULL;
  1024.   }
  1025.   directory->total    = nr;
  1026.   directory->alloc    = alloc;
  1027.   if (nr == 0) {
  1028.     directory->dirlist = NULL;
  1029.   }
  1030.   return TRUE;
  1031. }
  1032.  
  1033. /* print the contents of the directory */
  1034. static void print_dir(directory, lib_name, verbose)
  1035.   struct dir *directory;
  1036.   char *lib_name;
  1037.   int verbose;
  1038.   struct dirlist *temp;
  1039.  
  1040.   if (verbose) {
  1041.     if (directory->total == 1) {
  1042.         printf ("Library contains one module. ");
  1043.     }
  1044.     else {
  1045.         printf ("Library contains %ld modules. ",directory->total);
  1046.     }
  1047.     if (directory->alloc == 1) {
  1048.         printf ("Directory size is one module.\n");
  1049.     }
  1050.     else {
  1051.         printf ("Directory size is %ld modules.\n",directory->alloc);
  1052.     }
  1053.     if (directory->is_link) {
  1054.         printf ("The library \"%s\" is a link to \"%s\"!\n",
  1055.                 lib_name, directory->real_name);
  1056.     }
  1057.     if (directory->version == OLD_VERSION) {
  1058.         printf ("WARNING: That's an old library-version!\n");
  1059.     }
  1060.     printf ("\n  Module name           Size   Position\n");
  1061.     printf ("  --------------------- ------ --------\n");
  1062.     for (temp = directory->dirlist; temp != NULL; temp = temp->next) {
  1063.         printf ("  %-21s %6ld %8ld\n", temp->dirent.mname,
  1064.             temp->dirent.size, temp->dirent.where);
  1065.     }
  1066.     printf("\n");
  1067.   }
  1068.   else {
  1069.     for (temp = directory->dirlist; temp != NULL; temp = temp->next) {
  1070.         puts(temp->dirent.mname);
  1071.     }
  1072.   }
  1073.   
  1074. }
  1075.  
  1076. /* search a module in the flib and copy it to a new file */
  1077. static int ex_module(directory, mname, flib, verbose)
  1078.   struct dir *directory;
  1079.   char *mname;
  1080.   FILE *flib;
  1081.   int verbose;
  1082. {
  1083.   struct dirlist *temp;
  1084.   FILE *module;
  1085.   int i, j, count;
  1086.   unsigned short check;
  1087.  
  1088.   if (directory == NULL || flib == NULL) {
  1089.     fprintf(stderr,"*** Internal error!\n");
  1090.     return FALSE;
  1091.   }
  1092.  
  1093.   /* find the module */
  1094.   for (temp = directory->dirlist; temp != NULL
  1095.     && strcmp(temp->dirent.mname,mname) != 0; temp = temp->next);
  1096.  
  1097.   if (temp == NULL) {
  1098.     fprintf(stderr,"*** Can't find module \"%s\"!\n",mname);
  1099.     return FALSE;
  1100.   }
  1101.  
  1102.   if (verbose) {
  1103.     printf("Extracting module %s \t(%ld bytes).\n",mname, temp->dirent.size);
  1104.   }
  1105.  
  1106.   if (fseek(flib,temp->dirent.where,0) != 0) {
  1107.     perror("*** ");
  1108.     fprintf(stderr,"*** Error during fseek!\n");
  1109.     return FALSE;
  1110.   }
  1111.   if ((module = fopen(mname,OPEN_FOR_WRITING)) == NULL) {
  1112.     fprintf(stderr,"*** Can't create file \"%s\"!\n",mname);
  1113.     return FALSE;
  1114.   }
  1115.  
  1116.   count = temp->dirent.size / BUFSIZE;
  1117.   check = 0;
  1118.   for (i=0; i<count; i++) {
  1119.     if (fread(buffer,sizeof(char),BUFSIZE,flib)!=BUFSIZE) {
  1120.         fclose(module);
  1121.         fprintf(stderr,"*** Can't read from flib!\n");
  1122.         return FALSE;
  1123.     }
  1124.     for (j=0; j<BUFSIZE; j++) {
  1125.         check += (unsigned short)buffer[j];
  1126.     }
  1127.     if (fwrite(buffer,sizeof(char),BUFSIZE,module) != BUFSIZE) {
  1128.         fclose(module);
  1129.         fprintf(stderr,"*** Can't write to module %s!\n",mname);
  1130.         return FALSE;
  1131.     }
  1132.   }
  1133.   i = temp->dirent.size - count * BUFSIZE;    /* copy rest */
  1134.   if (i > 0) {
  1135.     if (fread(buffer,sizeof(char),i,flib) != i) {
  1136.         fclose(module);
  1137.         fprintf(stderr,"*** Can't read from flib!\n");
  1138.         return FALSE;
  1139.     }
  1140.     for (j=0; j<i; j++) {
  1141.         check += buffer[j];
  1142.     }
  1143.     if (fwrite(buffer,sizeof(char),i,module) != i) {
  1144.         fclose(module);
  1145.         fprintf(stderr,"*** Can't write to module %s!\n",mname);
  1146.         return FALSE;
  1147.     }
  1148.   }
  1149.  
  1150.   fclose(module);
  1151.   if (directory->version != OLD_VERSION && check != temp->dirent.checksum) {
  1152.     fprintf(stderr,"*** WARNING: Module \"%s\" extracted with wrong checksum!\n",
  1153.                 mname);
  1154.   }
  1155.  
  1156.   return TRUE;
  1157. }
  1158.  
  1159. /* create a complete (new) flib, copy only files into the flib */
  1160. static int create_new_flib(directory, name, verbose)
  1161.   struct dir *directory;
  1162.   char *name;
  1163.   int verbose;
  1164. {
  1165.   FILE *flib;
  1166.   struct dirlist *dirl;
  1167.   long size=0, where=0;
  1168.   unsigned short check;
  1169.  
  1170.   if ((flib = copy_directory(directory, name, verbose)) == NULL) {
  1171.     return FALSE;
  1172.   }
  1173.  
  1174.   /* module abspeichern */
  1175.   for (dirl = directory->dirlist; dirl != NULL; dirl = dirl->next) {
  1176.     if (verbose) {
  1177.         printf("Copying module \"%s\"\t... ",dirl->dirent.mname);
  1178.     }
  1179.     if (!copy_module(dirl->dirent.mname,flib,&size,&where,&check)) {
  1180.         fprintf(stderr,"\n*** Can't copy module \"%s\" to library!\n",
  1181.                 dirl->dirent.mname);
  1182.         return FALSE;
  1183.     }
  1184.     if (verbose) {
  1185.         printf("ok. \t(%ld bytes at %ld)\n",size,where);
  1186.     }
  1187.     dirl->dirent.size     = size;
  1188.     dirl->dirent.where    = where;
  1189.     dirl->dirent.checksum = check;
  1190.   }
  1191.   update_dir(directory, flib, verbose);
  1192.  
  1193.   return TRUE;
  1194. }
  1195.  
  1196.  
  1197. /* create a new flib and prepare the directory part */
  1198. static FILE *copy_directory(directory, name, verbose)
  1199.   struct dir *directory;
  1200.   char *name;
  1201.   int verbose;
  1202. {
  1203.   FILE *flib;
  1204.   long magic = (directory->version == NEW_VERSION) ? LIBMAGIC : OLD_LIBMAGIC;
  1205.   struct dirlist *dirl;
  1206.   union direntry dir;
  1207.  
  1208.   if ((flib = fopen(name,OPEN_FOR_WRITING)) == NULL) {
  1209.     fprintf(stderr,"*** Can't open destination library!\n");
  1210.     return NULL;
  1211.   }
  1212.   if (!fwritelong(magic,flib) || !fwritelong(directory->total,flib)) {
  1213.     fprintf(stderr,"*** Can't write to destination library!\n");
  1214.     return NULL;
  1215.   }
  1216.   /* directory anlegen */
  1217.   if (verbose) {
  1218.     printf("Creating internal flib directory\t... ");
  1219.   }
  1220.   for (dirl = directory->dirlist; dirl != NULL; dirl = dirl->next) {
  1221.     if (directory->version == NEW_VERSION) {
  1222.         dir.new = dirl->dirent;
  1223.     }
  1224.     else {
  1225.         strncpy(dir.old.mname,dirl->dirent.mname,FILENAMELEN);
  1226.         dir.old.size  = dirl->dirent.size;
  1227.         dir.old.where = dirl->dirent.where;
  1228.     }
  1229.     if (!fwritedir(&dir,directory->version,flib)) {
  1230.         fprintf(stderr,"*** Can't write to destination library!\n");
  1231.         return NULL;
  1232.     }
  1233.   }
  1234.   if (verbose) {
  1235.     printf("ok.\n");
  1236.   }
  1237.   return flib;
  1238. }
  1239.  
  1240. /* copy a module (file) to the actual position in flib */
  1241. static int copy_module(name, flib, size, where, check)
  1242.   char *name;
  1243.   FILE *flib;
  1244.   long *size, *where;
  1245.   unsigned short *check;
  1246. {
  1247.   FILE *module;
  1248.   int len, i;
  1249.  
  1250.   if ((module = fopen(name,OPEN_FOR_READING)) == NULL) {
  1251.     return FALSE;
  1252.   }
  1253.   *size = 0;
  1254.   *where = ftell(flib);
  1255.   *check = 0;
  1256.   while ((len = fread(buffer,sizeof(char),BUFSIZE,module)) == BUFSIZE) {
  1257.     if (fwrite(buffer,sizeof(char),BUFSIZE,flib) != BUFSIZE) {
  1258.         fclose(module);
  1259.         return FALSE;
  1260.     }
  1261.     *size += BUFSIZE;
  1262.     for (i=0; i<BUFSIZE; i++) {
  1263.         *check += (unsigned short)buffer[i];
  1264.     }
  1265.   }
  1266.   if (len > 0) {
  1267.     if (fwrite(buffer,sizeof(char),len,flib) != len) {
  1268.         fclose(module);
  1269.         return FALSE;
  1270.     }
  1271.     *size += len;
  1272.     for (i=0; i<len; i++) {
  1273.         *check += (unsigned short)buffer[i];
  1274.     }
  1275.   }
  1276.   fclose(module);
  1277.  
  1278.   return TRUE;
  1279. }
  1280.  
  1281. /* copy the modules (from flib) with "where != 0" to flib (tmplib) */
  1282. static FILE *copy_old_flib(directory, flib, name, verbose)
  1283.   struct dir *directory;
  1284.   FILE *flib;
  1285.   char *name;
  1286.   int verbose;
  1287. {
  1288.   FILE *tmplib;
  1289.   struct dirlist *dirl;
  1290.   long where;
  1291.   int i, j;
  1292.   long len ,count;
  1293.   unsigned short check;
  1294.  
  1295.   if ((tmplib = copy_directory(directory, TMPFLIB, verbose)) == NULL) {
  1296.     return NULL;
  1297.   }
  1298.  
  1299.   /* module copy */
  1300.   for (dirl = directory->dirlist; dirl != NULL;    dirl = dirl->next) {
  1301.     if (dirl->dirent.where != 0L) {
  1302.         if (verbose) {
  1303.             printf("Copying module \"%s\"\t... ",dirl->dirent.mname);
  1304.         }
  1305.         if (fseek(flib,dirl->dirent.where,0) != 0) {
  1306.             perror("*** ");
  1307.             fprintf(stderr,"*** Error during fseek!\n");
  1308.             return NULL;
  1309.         }
  1310.         where = ftell(tmplib);
  1311.         count = dirl->dirent.size / BUFSIZE;
  1312.         check = 0;
  1313.         for (i=0; i<count; i++) {
  1314.             if (fread(buffer,sizeof(char),BUFSIZE,flib)!=BUFSIZE) {
  1315.                 fclose(tmplib);
  1316.                 fprintf(stderr,"*** Can't read from flib!\n");
  1317.                 return NULL;
  1318.             }
  1319.             for (j=0; j<BUFSIZE; j++) {
  1320.                 check += (unsigned short)buffer[j];
  1321.             }
  1322.             if (fwrite(buffer,sizeof(char),BUFSIZE,tmplib) != BUFSIZE) {
  1323.                 fclose(tmplib);
  1324.                 fprintf(stderr,"*** Can't write to temporary flib!\n");
  1325.                 return NULL;
  1326.             }
  1327.         }
  1328.         len = dirl->dirent.size - count * BUFSIZE;
  1329.         if (len > 0) {
  1330.             if (fread(buffer,sizeof(char),(int)len,flib) != len) {
  1331.                 fclose(tmplib);
  1332.                 fprintf(stderr,"*** Can't read from flib!\n");
  1333.                 return NULL;
  1334.             }
  1335.             for (j=0; j<len; j++) {
  1336.                 check += (unsigned short)buffer[j];
  1337.             }
  1338.             if (fwrite(buffer,sizeof(char),(int)len,tmplib) != len) {
  1339.                 fclose(tmplib);
  1340.                 fprintf(stderr,"*** Can't write to temporary flib!\n");
  1341.                 return NULL;
  1342.             }
  1343.         }
  1344.         dirl->dirent.where = where;
  1345.         dirl->dirent.checksum = check;
  1346.         if (verbose) {
  1347.             printf("ok.\n");
  1348.         }
  1349.     }
  1350.   }
  1351.   return tmplib;
  1352. }
  1353.  
  1354. /* copy the modules (files) with "where == 0" to flib (tmplib) */
  1355. static int append_modules_to_flib(directory, flib, verbose)
  1356.   struct dir *directory;
  1357.   FILE *flib;
  1358.   int verbose;
  1359. {
  1360.   struct dirlist *dirl;
  1361.   long size, where;
  1362.   unsigned short check;
  1363.  
  1364.   /* module abspeichern */
  1365.   if (fseek(flib,0L,2) != 0) {        /* end of file */
  1366.     perror("*** ");
  1367.     fprintf(stderr,"*** Error during fseek!\n");
  1368.     return 0;
  1369.   }
  1370.   for (dirl = directory->dirlist; dirl != NULL; dirl = dirl->next) {
  1371.     if (dirl->dirent.where == 0L) {
  1372.         if (verbose) {
  1373.             printf("Copying module \"%s\"\t... ",dirl->dirent.mname);
  1374.         }
  1375.         if (!copy_module(dirl->dirent.mname,flib,&size,&where,&check)) {
  1376.             fprintf(stderr,"\n*** Can't copy module \"%s\" to library!\n");
  1377.             return FALSE;
  1378.         }
  1379.         if (verbose) {
  1380.             printf("ok. \t(%ld bytes at %ld)\n",size,where);
  1381.         }
  1382.         dirl->dirent.size     = size;
  1383.         dirl->dirent.where    = where;
  1384.         dirl->dirent.checksum = check;
  1385.     }
  1386.   }
  1387.   return update_dir(directory, flib, verbose);
  1388. }
  1389.  
  1390. /* find a module and delete it from the directory list */
  1391. static int del_module_from_dir(directory, name, verbose)
  1392.   struct dir *directory;
  1393.   char *name;
  1394.   int verbose;
  1395. {
  1396.   struct dirlist *temp, *parent;
  1397.  
  1398.   if (directory == NULL) {
  1399.     fprintf(stderr,"*** Internal error!\n");
  1400.     return FALSE;
  1401.   }
  1402.  
  1403.   /* find the module */
  1404.   for (temp = directory->dirlist, parent = NULL; temp != NULL
  1405.     && strcmp(temp->dirent.mname,name) != 0;
  1406.     parent = temp, temp = temp->next);
  1407.  
  1408.   if (temp == NULL) {
  1409.     fprintf(stderr,"*** Can't find module \"%s\"!\n",name);
  1410.     return FALSE;
  1411.   }
  1412.   /* delete module from directory-list */
  1413.   if (parent == NULL) {
  1414.     directory->dirlist = temp->next;
  1415.   }
  1416.   else {
  1417.     parent->next = temp->next;
  1418.   }
  1419.   free(temp);
  1420.   directory->alloc = --directory->total;
  1421.  
  1422.   return TRUE;
  1423. }
  1424.  
  1425. /* save directory to file */
  1426. static int update_dir(directory, flib, verbose)
  1427.   struct dir *directory;
  1428.   FILE *flib;
  1429.   int verbose;
  1430. {
  1431.   struct dirlist *dirl;
  1432.   union direntry dir;
  1433.  
  1434.   /* directory size-where */
  1435.   if (verbose) {
  1436.     printf("Updating internal flib directory\t... ");
  1437.   }
  1438.   if (fseek(flib,8L,0) != 0) {
  1439.     perror("*** ");
  1440.     fprintf(stderr,"*** Can't fseek?!\n");
  1441.     return FALSE;
  1442.   }
  1443.   for (dirl = directory->dirlist; dirl != NULL; dirl = dirl->next) {
  1444.     if (directory->version == NEW_VERSION) {
  1445.         dir.new = dirl->dirent;
  1446.     }
  1447.     else {
  1448.         strncpy(dir.old.mname,dirl->dirent.mname,FILENAMELEN);
  1449.         dir.old.size  = dirl->dirent.size;
  1450.         dir.old.where = dirl->dirent.where;
  1451.     }
  1452.     if (!fwritedir(&dir,directory->version,flib)) {
  1453.         fprintf(stderr,"*** Can't write to destination library!\n");
  1454.         return FALSE;
  1455.     }
  1456.   }
  1457.   if (verbose) {
  1458.     printf("ok.\n");
  1459.   }
  1460.   return TRUE;
  1461. }
  1462.  
  1463.  
  1464. /* change module-names in directory                */
  1465. /* if dirl empty then change all names in directory        */
  1466. static int rename_entries(directory,dirl,verbose)
  1467.   struct dir     *directory;
  1468.   struct dirlist *dirl;
  1469.   int         verbose;
  1470. {
  1471.   struct dirlist *entry, *found;
  1472.   char str[256];
  1473.   int allowed_length = (directory->version == NEW_VERSION)
  1474.                 ? NEWFILENAMELEN
  1475.                 : FILENAMELEN;
  1476.  
  1477.  
  1478.   if (dirl == NULL) {        /* no modules -> change all names */
  1479.     for (entry = directory->dirlist; entry != NULL; entry = entry->next) {
  1480.         do {
  1481.             printf("Old name: %s, change it to: ",entry->dirent.mname);
  1482.             if (gets(str) == NULL) {
  1483.                 fprintf(stderr,"\nUnexpected end of \"stdin\"!?\n");
  1484.                 return FALSE;
  1485.             }
  1486.             if (strlen(str) > allowed_length) {
  1487.                 fprintf(stderr,"New name too long!\n");
  1488.             }
  1489.         } while (strlen(str) > allowed_length);
  1490.         if (str[0] != '\0') {
  1491.             if (verbose) {
  1492.                 printf("%s ---> %s\n",entry->dirent.mname,str);
  1493.             }
  1494.             strcpy(entry->dirent.mname,str);
  1495.         }
  1496.     }
  1497.   }
  1498.   else {            /* change only the names of the given modules */
  1499.     for (entry = dirl; entry != NULL; entry = entry->next) {
  1500.         if ((found = exist_entry(NULL,directory->dirlist,entry)) != NULL) {
  1501.             do {
  1502.                 printf("Old name: %s, change it to: ",
  1503.                         found->dirent.mname);
  1504.                 if (gets(str) == NULL) {
  1505.                     fprintf(stderr,"\nUnexpected end of \"stdin\"!?\n");
  1506.                     return FALSE;
  1507.                 }
  1508.                 if (strlen(str) > allowed_length) {
  1509.                     fprintf(stderr,"New name too long!\n");
  1510.                 }
  1511.             } while (strlen(str) > allowed_length);
  1512.             if (str[0] != '\0') {
  1513.                 if (verbose) {
  1514.                     printf("%s ---> %s\n",found->dirent.mname,str);
  1515.                 }
  1516.                 strcpy(found->dirent.mname,str);
  1517.             }
  1518.         }
  1519.     }
  1520.   }
  1521.   return TRUE;
  1522. }
  1523.  
  1524.  
  1525. /* test all checksums of the fontlibrary            */
  1526. static void test_flib(flib, directory, verbose)
  1527.   FILE *flib;
  1528.   struct dir *directory;
  1529.   int verbose;
  1530. {
  1531.   int i, j;
  1532.   struct dirlist *dirl;
  1533.   unsigned short check;
  1534.   long count, len;
  1535.  
  1536.   for (dirl = directory->dirlist; dirl != NULL;    dirl = dirl->next) {
  1537.     if (dirl->dirent.where != 0L) {
  1538.         if (verbose) {
  1539.             printf("Checking module \"%s\"\t... ",dirl->dirent.mname);
  1540.         }
  1541.         if (fseek(flib,dirl->dirent.where,0) != 0) {
  1542.             perror("*** ");
  1543.             fprintf(stderr,"*** Error during fseek!\n");
  1544.             return;
  1545.         }
  1546.         count = dirl->dirent.size / (long)BUFSIZE;
  1547.         check = 0;
  1548.         for (i=0; i<count; i++) {
  1549.             if (fread(buffer,sizeof(char),BUFSIZE,flib)!=BUFSIZE) {
  1550.                 fprintf(stderr,"*** Can't read from flib!\n");
  1551.                 return;
  1552.             }
  1553.             for (j=0; j<BUFSIZE; j++) {
  1554.                 check += (unsigned short)buffer[j];
  1555.             }
  1556.         }
  1557.         len = dirl->dirent.size - count * (long)BUFSIZE;
  1558.         if (len > 0) {
  1559.             if (fread(buffer,sizeof(char),(int)len,flib) != len) {
  1560.                 fprintf(stderr,"*** Can't read from flib!\n");
  1561.                 return;
  1562.             }
  1563.             for (j=0; j<len; j++) {
  1564.                 check += (unsigned short)buffer[j];
  1565.             }
  1566.         }
  1567.         if (dirl->dirent.checksum == check) {
  1568.             if (verbose) {
  1569.                 printf("ok.\n");
  1570.             }
  1571.         }
  1572.         else {
  1573.             if (verbose) {
  1574.                 printf("ERROR (expected %u, found %u)\n",
  1575.                     dirl->dirent.checksum, check);
  1576.             }
  1577.             else {
  1578.                 fprintf(stderr,
  1579.                       "ERROR: module \"%s\" (expected %u, found %u)\n",
  1580.                   dirl->dirent.mname, dirl->dirent.checksum, check);
  1581.             }
  1582.         }
  1583.     }
  1584.   }
  1585. }
  1586.  
  1587.  
  1588. /* read the directory structure                    */
  1589. static int freaddir(dir,version,f)
  1590.   union direntry *dir;
  1591.   int version;
  1592.   FILE *f;
  1593. {
  1594.   if (version == OLD_VERSION) {
  1595.     if (fread(dir->old.mname,FILENAMELEN,1,f) != 1) {
  1596.         return FALSE;
  1597.     }
  1598.     dir->new.mname[FILENAMELEN] = '\0';
  1599.     if (!freadlong(&(dir->old.size),f)) {
  1600.         return FALSE;
  1601.     }
  1602.     if (!freadlong(&(dir->old.where),f)) {
  1603.         return FALSE;
  1604.     }
  1605.   }
  1606.   else {
  1607.     if (fread(dir->new.mname,1,NEWFILENAMELEN,f) != NEWFILENAMELEN) {
  1608.         return FALSE;
  1609.     }
  1610.     if (!freadshort(&(dir->new.checksum),f)) {
  1611.         return FALSE;
  1612.     }
  1613.     if (!freadlong(&(dir->new.size),f)) {
  1614.         return FALSE;
  1615.     }
  1616.     if (!freadlong(&(dir->new.where),f)) {
  1617.         return FALSE;
  1618.     }    
  1619.   }
  1620.   return TRUE;
  1621. }
  1622.  
  1623.  
  1624. /* read a four byte number <hihi lohi hilo lolo> */
  1625. static int freadlong(buf,f)
  1626.   long *buf;
  1627.   FILE *f;
  1628. {
  1629.   unsigned char b[4];
  1630.  
  1631.   if (fread((char *)b,1,4,f) != 4) {
  1632.     return FALSE;
  1633.   }
  1634.   *buf = (long)(((unsigned long)b[0]) << 24) | (((unsigned long)b[1]) << 16) | 
  1635.             (((unsigned long)b[2]) << 8) | ((unsigned long)b[3]);
  1636.  
  1637.   return TRUE;
  1638. }
  1639.  
  1640. /* read a two byte number <hi lo> */
  1641. static int freadshort(buf,f)
  1642.   unsigned short *buf;
  1643.   FILE *f;
  1644. {
  1645.   unsigned char b[2];
  1646.  
  1647.   if (fread((char *)b,1,2,f) != 2) {
  1648.     return FALSE;
  1649.   }
  1650.   *buf = (unsigned short) (((unsigned short)b[0]) << 8) | ((unsigned short)b[1]);
  1651.  
  1652.   return TRUE;
  1653. }
  1654.  
  1655.  
  1656. /* write the directory structure                */
  1657. static int fwritedir(dir,version,f)
  1658.   union direntry *dir;
  1659.   int version;
  1660.   FILE *f;
  1661. {
  1662.   if (version == OLD_VERSION) {
  1663.     if (fwrite(dir->new.mname,NEWFILENAMELEN,1,f) != 1) {
  1664.         return FALSE;
  1665.     }
  1666.     if (!fwritelong(dir->new.size,f)) {
  1667.         return FALSE;
  1668.     }
  1669.     if (!fwritelong(dir->new.where,f)) {
  1670.         return FALSE;
  1671.     }
  1672.   }
  1673.   else {
  1674.     if (fwrite(dir->new.mname,NEWFILENAMELEN,1,f) != 1) {
  1675.         return FALSE;
  1676.     }
  1677.     if (!fwriteshort(dir->new.checksum,f)) {
  1678.         return FALSE;
  1679.     }
  1680.     if (!fwritelong(dir->new.size,f)) {
  1681.         return FALSE;
  1682.     }
  1683.     if (!fwritelong(dir->new.where,f)) {
  1684.         return FALSE;
  1685.     }    
  1686.   }
  1687.   return TRUE;
  1688. }
  1689.  
  1690. /* write a four byte number <hihi lohi hilo lolo> */
  1691. static int fwritelong(buf,f)
  1692.   long buf;
  1693.   FILE *f;
  1694. {
  1695.   unsigned char b[4];
  1696.  
  1697.   b[0] = (unsigned char)(((unsigned long)buf & 0xFF000000L) >> 24);
  1698.   b[1] = (unsigned char)(((unsigned long)buf & 0x00FF0000L) >> 16);
  1699.   b[2] = (unsigned char)(((unsigned long)buf & 0x0000FF00L) >> 8);
  1700.   b[3] = (unsigned char) ((unsigned long)buf & 0x000000FFL);
  1701.   if (fwrite((char *)b,1,4,f) != 4) {
  1702.     return FALSE;
  1703.   }
  1704.   return TRUE;
  1705. }
  1706.  
  1707. /* write a two byte number <hi lo> */
  1708. #ifdef ANSI
  1709. static int fwriteshort(unsigned short buf, FILE *f)
  1710. #else
  1711. static int fwriteshort(buf,f)
  1712.   unsigned short buf;
  1713.   FILE *f;
  1714. #endif /* ANSI */
  1715. {
  1716.   unsigned char b[2];
  1717.  
  1718.   b[0] = (unsigned char)(((unsigned long)buf & 0x0000FF00L) >> 8);
  1719.   b[1] = (unsigned char) ((unsigned long)buf & 0x000000FFL);
  1720.   if (fwrite((char *)b,1,2,f) != 2) {
  1721.     return FALSE;
  1722.   }
  1723.   return TRUE;
  1724. }
  1725.  
  1726.