home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload / ShartewareOverload.cdr / database / makendx.zip / MAKENDX.C next >
C/C++ Source or Header  |  1988-01-19  |  5KB  |  211 lines

  1. /*
  2. MAKENDX.C
  3. Extracted from MAKEDBF.C        AS        14-Jan-88
  4. e.g.:
  5. makendx p_req name+addr+city c 58
  6.  
  7.  
  8. Microsoft C 5.0:  cl -Zpe -Ox -W3 -Gs makendx.c
  9.  
  10. Andrew Schulman, 12 Humboldt Street, Cambridge MA 02140, (617) 876-2102
  11. */
  12.  
  13. #include    <stdio.h>
  14. #include    <string.h>
  15. #include    <io.h>
  16. #include    <ctype.h>
  17. #include    <stdlib.h>
  18. #include    <dos.h>
  19. #include    <fcntl.h>
  20.  
  21. #define MAXKEYLEN        256
  22.  
  23. #define FILE_EXISTS(f)    (!access(f, 0x00))
  24.  
  25. #define LOCAL             static
  26. #define VOID            void
  27.  
  28. typedef unsigned char BYTE;
  29.  
  30. typedef struct
  31. {
  32.     unsigned long rootnode;
  33.     unsigned long nextnode;
  34.     unsigned long pad1;
  35.     BYTE keylen, pad2;
  36.     BYTE keypernode, pad3;
  37.     BYTE numeric, pad4;
  38.     BYTE sizekeyentry;
  39.     char pad5[5];
  40.     char expression[MAXKEYLEN];
  41. } NDX_HEAD;
  42.  
  43. typedef struct
  44. {
  45.     BYTE numentries;
  46.     char pad1[3];
  47.     unsigned long nextbranch;        /* 0 if leaf node */
  48.     unsigned long recordnum;        /* if not a branch */
  49. } PSEUDO_NDX_NODE;    
  50.  
  51. LOCAL char *ndxerror = "MAKENDX ERROR:";
  52. LOCAL char *ndxwarn = "MAKENDX WARNING:";
  53. LOCAL char *write_error = "write to file";
  54.  
  55. #define PASCAL pascal
  56.  
  57. LOCAL VOID PASCAL makendx(char *name, char *key, char *typ, char *len);
  58. LOCAL VOID PASCAL ndxmissingerror(char *s);
  59. LOCAL VOID PASCAL help(void);
  60. LOCAL VOID PASCAL backup(char *fname);
  61. LOCAL VOID PASCAL doserror(char *s, char *f);
  62.  
  63. main(argc, argv)
  64.     int argc;
  65.     char *argv[];
  66. {
  67.     if (argc<3) help();
  68.  
  69.     makendx(argv[1], argv[2], argv[3], argv[4]);
  70.     exit(0);
  71. }    
  72.  
  73. LOCAL VOID PASCAL makendx(name, key, typ, len)
  74.      char *name, *key, *typ, *len;
  75. {
  76.     NDX_HEAD ndx;
  77.     PSEUDO_NDX_NODE root;
  78.     char filename[80];
  79.     unsigned int f, count;
  80.     int type;
  81.  
  82. /***** MOSTLY ERROR CHECKING *****/ 
  83.     
  84.     if (name)    {
  85.         strcpy(filename,name);
  86.         if (! strchr(filename, '.')) strcat(filename, ".NDX");
  87.         backup(filename);
  88.         }
  89.     else    {
  90.         ndxmissingerror("NDX filename");
  91.         return;
  92.         }
  93.     
  94.     if (!key)    {
  95.         ndxmissingerror("key expression");
  96.         return;
  97.         }
  98.  
  99.     type = (typ) ? toupper(*typ) : 0;
  100.     if (! type)    {
  101.         ndxmissingerror("expression type");
  102.         return;
  103.         }
  104.     
  105.     /* can't index on logical or memo fields */
  106.     if (type=='L'||type=='M')    {
  107.         printf("** %s Can't index on %c field! **\n", ndxerror, type);
  108.         return;
  109.         }
  110.  
  111. /***** END OF ERROR CHECKING:  INTO REAL WORK *****/
  112. /***** BUT THERE'S PLENTY OF ERROR CHECKING BELOW TOO!!! *****/        
  113.         
  114.     /* should be done at compile-time, not run-time! */
  115.     ndx.pad1 = ndx.pad2 = ndx.pad3 = ndx.pad4 =
  116.     ndx.pad5[0]=ndx.pad5[1]=ndx.pad5[2]=ndx.pad5[3]=ndx.pad5[4] = 0;
  117.         
  118.     ndx.rootnode = 1;
  119.     ndx.nextnode = 2;
  120.  
  121.     if (type=='C')            /* character expression */
  122.         {
  123.         ndx.numeric = 0;
  124.         /* the length of the key is NOT the length of the key expression,
  125.          * but the length of the resulting dBase value.     For instance,
  126.          * the length of the key DATE()-DATE is 8.    The length of the key
  127.          * SUBSTR(CHARFIELD,3,5) would be 5 -- but how can this be determined
  128.          * without including a complete dBase expression parser???
  129.          */
  130.         if (! (len && (ndx.keylen = atoi(len))))    {
  131.             ndxmissingerror("expression length");
  132.             return;
  133.             }
  134.         if (ndx.keylen > 100)    {
  135.             printf("** %s Index too big (100 char max) **\n", ndxerror);
  136.             return;
  137.             }
  138.         }
  139.     else
  140.         {
  141.         ndx.numeric = 1;
  142.         ndx.keylen = 8;        /* no reason to read len */
  143.         }
  144.  
  145.     ndx.sizekeyentry = ndx.keylen + 9;        /* even though spec says 8 */
  146.     ndx.keypernode = 508 / ndx.sizekeyentry;    
  147.  
  148.     memset(ndx.expression, 0, MAXKEYLEN);
  149.     if (strlen(key) < MAXKEYLEN) strcpy(ndx.expression, key);
  150.     else /* complain or something */ ;
  151.  
  152.     if (_dos_creat(filename, _A_NORMAL, &f) != 0)
  153.         doserror("create file", filename);
  154.     
  155.     /* write out anchor node (includes garbage at end) */
  156.     if (_dos_write(f, (void far *)&ndx, 512, &count) != 0)
  157.         doserror(write_error, filename);
  158.     
  159.     /* write out root node (includes garbage at end) */
  160.     root.numentries = 0;
  161.     root.pad1[0]=root.pad1[1]=root.pad1[2]=0;
  162.     root.nextbranch = root.recordnum = 0;
  163.     if (_dos_write(f, (void far *)&root, 512, &count) != 0)
  164.         doserror(write_error, filename);
  165.     
  166.     if (_dos_close(f) != 0)
  167.         doserror("close file", filename);
  168.     
  169.     printf("Index file %s created with key %s (type %c) (length %d)\n",
  170.         strupr(filename), strupr(ndx.expression), type, ndx.keylen);
  171. }
  172.  
  173. LOCAL VOID PASCAL ndxmissingerror(s)
  174.     char *s;
  175. {
  176.     printf("** %s Missing %s **\n", ndxerror, s);
  177. }
  178.  
  179. LOCAL VOID PASCAL doserror(s,f)
  180.     char *s, *f;
  181. {
  182.     extern int errno;
  183.     printf("** %s Can't %s (%s) (DOS error #%d) **\n", ndxerror, s, f, errno);
  184.     exit(1);
  185. }    
  186.  
  187. LOCAL VOID PASCAL help()
  188. {
  189.     printf("MAKENDX 1.0 (Andrew Schulman 1988)\n");
  190.     printf("creates dBase III Plus NDX files\n");
  191.     printf("usage: MAKENDX <filename> <ndx key> <ndx type> [length]\n");
  192.     exit(1);
  193. }    
  194.  
  195. LOCAL VOID PASCAL backup(fname)
  196.     char *fname;
  197. {
  198.     char bakname[35];
  199.  
  200.     strcpy(bakname, fname);
  201.     *(strchr(bakname, '.')) = '\0';
  202.     strcat(bakname, ".NDK");
  203.  
  204.     if (!FILE_EXISTS(fname)) return;
  205.     else if (FILE_EXISTS(bakname)) unlink(bakname);
  206.     
  207.     if (rename(fname, bakname)) /* return 0 on success */
  208.         doserror("create backup file", bakname);
  209. }
  210.  
  211.