home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / database / dbflis / dbf.c next >
Encoding:
C/C++ Source or Header  |  1988-05-23  |  8.4 KB  |  259 lines

  1. /* DBF.c
  2.  *
  3.  * DBF.Com -- dBASE III / FoxBASE+  Database structure lister
  4.  *
  5.  * Copyright (c) 1988, by Matrix Software Systems
  6.  *                        All rights reserved
  7.  *
  8.  * This program will list the structure of any dBASE III /FoxBASE +
  9.  * database file in a format similar to "List Structure." It is similar
  10.  * to another PD program (ListStru.COM) except that this version handles
  11.  * wildcards, comes complete with source code (for use with Turbo C),
  12.  * and is about one-half the size.
  13.  *
  14.  *
  15.  * This program is provided on an "as-is" basis.  No warranty, expressed
  16.  * or implied, covers this program.  Matrix Software Systems disclaims
  17.  * all conditions and warranties, whether express or implied with regard
  18.  * to this program, including all implied conditions or warranties of
  19.  * merchantibility and fitness for a particular purpose.
  20.  *
  21.  * This program is NOT public domain.  It may be freely distributed as
  22.  * long as the following conditions are met:
  23.  *
  24.  *  1.  Any and all copies must include the above copyright notice.
  25.  *  2.  The software must be distributed in its original ARC format
  26.  *      which contains the files DBF.COM, DBF.C, and READ.ME.
  27.  *  3.  No fee may be charged for any copy, aside from a possible small
  28.  *      duplication and handling fee.  (I sincerely doubt you could sell
  29.  *      this if you wanted to...)
  30.  *
  31.  *
  32.  * To compile the source code, you will need Turbo C (V1.0).
  33.  *
  34.  *    tcc -Ic:\tc\include -Lc:\tc\lib -K -O -Z -d -f- -mt dbf.c
  35.  *    exe2bin dbf.exe dbf.com
  36.  *
  37.  */
  38.  
  39. #include <stdio.h>
  40. #include <fcntl.h>
  41. #include <io.h>
  42. #include <errno.h>
  43. #include <dir.h>
  44. #include <string.h>
  45.  
  46.  
  47. /* A few typedefs from Amigaland.  Makes porting code a hell of a lot easier */
  48. #define VOID   void
  49. typedef unsigned char UBYTE;
  50. typedef unsigned short UWORD;
  51. typedef unsigned long ULONG;
  52. typedef char BYTE;
  53. typedef short WORD;
  54. typedef char *STRPTR;
  55.  
  56.  
  57. STRPTR usagemessage[] = {
  58.    "DBF.Com -- Copyright (c) 1988, by Matrix Software Systems",
  59.    "        -- All Rights Reserved --",
  60.    " ",
  61.    "List dBASE III / FoxBASE+ database file structures",
  62.    "Usage:  DBF <filename.ext> [<filename.ext>...]",
  63.    "        Filenames may include path and/or wildcards (* and ?)",
  64.    "        If no extension is specified, '.DBF' is assumed.",
  65.    " ",
  66.    "Please send comments/requests to the following locations:",
  67.    "  CompuServe:  75126,2223",
  68.    "  BIX:  dlove",
  69.    ""
  70. };
  71.  
  72. /* dBASE III database header size and offset information */
  73. #define SIZEOF_DBF_HEADER  32
  74. #define HOFF_VERSION       0
  75. #define HOFF_UPDATE_DAY    3
  76. #define HOFF_UPDATE_MONTH  2
  77. #define HOFF_UPDATE_YEAR   1
  78. #define HOFF_RECORDS       4
  79. #define HOFF_HEADER_SIZE   8
  80. #define HOFF_RECORD_SIZE   10
  81.  
  82. #define hdr_version(x)        ( (WORD)*(x) )
  83. #define hdr_update_day(x)     ( (WORD)*(x+HOFF_UPDATE_DAY) )
  84. #define hdr_update_month(x)   ( (WORD)*(x+HOFF_UPDATE_MONTH) )
  85. #define hdr_update_year(x)    ( (WORD)*(x+HOFF_UPDATE_YEAR)+1900)
  86. #define hdr_records(x)        (*((ULONG *)(x+HOFF_RECORDS)))
  87. #define hdr_size(x)           (*((UWORD *)(x+HOFF_HEADER_SIZE)))
  88. #define hdr_rsize(x)          (*((UWORD *)(x+HOFF_RECORD_SIZE)))
  89. #define num_fields(x)         ((hdr_size(x)-32)>>5)
  90.  
  91.  
  92. /* dBASE field header size and offset information */
  93. #define SIZEOF_DBF_FIELD   32
  94. #define FOFF_TYPE    11
  95. #define FOFF_LENGTH  16
  96. #define FOFF_DECIMAL 17
  97.  
  98. #define fld_name(x)     (x)
  99. #define fld_type(x)     (x[FOFF_TYPE])
  100. #define fld_length(x)   ((UWORD)x[FOFF_LENGTH])
  101. #define fld_decimal(x)  ((UWORD)x[FOFF_DECIMAL])
  102.  
  103.  
  104.  
  105.  
  106. /* Prototypes */
  107. WORD main(int, char**);
  108. STRPTR fixname(STRPTR,struct ffblk *);
  109. WORD liststru(STRPTR);
  110. VOID usage(void);
  111.  
  112.  
  113. WORD
  114. main(argc,argv)
  115. WORD argc;
  116. char *argv[];
  117. {
  118.    static char filename[256];
  119.    static struct ffblk ffblk;
  120.    register STRPTR st;
  121.  
  122.    if (argc < 2) {               /* Show usage if no argument given */
  123.       usage();
  124.    } else {
  125.       while(--argc) {
  126.          strcpy(filename,*(++argv));
  127.  
  128.          /* Assume the extension .dbf unless otherwise specified */
  129.          for (st = filename; *st != '\0' && *st != '.'; st++);
  130.          if (*st == '\0')
  131.             strcpy(st,".dbf");
  132.  
  133.          /* Now check for a matching file.  If no match is found, assume
  134.           * the argument is a directory name, append "\\*.dbf" and attempt
  135.           * to match a file there.  If there are still no matches found,
  136.           * print a warning message and skip to the next arg.            */
  137.  
  138.          if (findfirst(filename,&ffblk,0)) {
  139.             sprintf(filename,"%s%s",*argv,"\\*.dbf");
  140.             if (findfirst(filename,&ffblk,0)) {
  141.                printf("Could not locate %s.",*argv);
  142.                continue;
  143.             }
  144.          }
  145.  
  146.          /* If we get here, findfirst() found a matching file.  So fix the
  147.           * filename to eliminate any wildcards and attempt to process it.
  148.           * Loop until all matches have been handled.                       */
  149.          do {
  150.             liststru(fixname(filename,&ffblk));
  151.          } while (!findnext(&ffblk));
  152.       }
  153.    }
  154. }
  155.  
  156.  
  157. STRPTR
  158. fixname(filename,ffblk)
  159. STRPTR filename;
  160. struct ffblk *ffblk;
  161. {
  162.    static char drive[MAXDRIVE];
  163.    static char dir[MAXDIR];
  164.    static char file[MAXFILE];
  165.    static char ext[MAXEXT];
  166.  
  167.    /* Tear the filename apart to get the drive and directory */
  168.    fnsplit(filename,drive,dir,file,ext);
  169.  
  170.    /* Then reassemble it with the correct filename */
  171.    sprintf(filename,"%s%s%s",drive,dir,ffblk->ff_name);
  172.  
  173.    /* For convenience, return a pointer to the fixed filename */
  174.    return(filename);
  175. }
  176.  
  177.  
  178. WORD
  179. liststru(filename)
  180. STRPTR filename;
  181. {
  182.    static char header[SIZEOF_DBF_HEADER];
  183.    static char field[SIZEOF_DBF_FIELD];
  184.    register int fp;
  185.    register int size,i;
  186.    register STRPTR format,type;
  187.  
  188.    printf("Structure for database : %s\n",filename);
  189.  
  190.    /* Attempt to open the file (Note that O_BINARY MUST be present!) */
  191.    fp = open(filename,O_RDONLY|O_BINARY|O_DENYNONE);
  192.    if (fp) {
  193.       /* Attempt to read the database header */
  194.       size = read(fp,&header[0],SIZEOF_DBF_HEADER);
  195.       if (size == SIZEOF_DBF_HEADER) {
  196.  
  197.          /* Got it, so print out the header information */
  198.          /* Uncomment the next line to check the dbf version #.  For dBASE III
  199.             and FoxBASE + files it will be 3 (or 83 if there is an associated
  200.             .dbt file) */
  201.          /* printf("Version #%d\n",hdr_version(header)); */
  202.  
  203.          printf("Number of data records : %10ld\n",hdr_records(header));
  204.          printf("Date of last update    : %02d-%02d-%4d\n",
  205.                hdr_update_month(header),hdr_update_day(header),
  206.                hdr_update_year(header));
  207.          printf("Field  Field name  Type       Width    Dec\n");
  208.          printf("-----  ----------  ----       -----    ---\n");
  209.  
  210.          /* Finally, print out each field */
  211.          for (i = 1; i <= num_fields(header); i++) {
  212.             size = read(fp,&field[0],SIZEOF_DBF_FIELD);
  213.             if (size == SIZEOF_DBF_FIELD) {
  214.                format = "%-9s  %5d\n";
  215.                printf("%5d  %-10s  ",i,fld_name(field));
  216.                switch(fld_type(field)) {
  217.                   case 'C':
  218.                      type = "Character";break;
  219.                   case 'D':
  220.                      type = "Date";break;
  221.                   case 'L':
  222.                      type = "Logical";break;
  223.                   case 'M':
  224.                      type = "Memo";break;
  225.                   case 'N':
  226.                      type = "Numeric";
  227.                      format = "%-9s  %5d    %3d\n";break;
  228.                   default:
  229.                      /* Egads!  A goto! */
  230.                      goto error;
  231.                }
  232.                printf(format,type,fld_length(field),fld_decimal(field));
  233.             } else
  234.                /* Oh No!  Another one! */
  235.                goto error;
  236.          }
  237.          /* Finally, print out the total record size.  Notice that this is one
  238.           * byte larger than the sum of the individual field length printed
  239.           * above.  dBASE adds one byte to the beginning of every record
  240.           * for internal use (deletion state).                                */
  241.  
  242.          printf("** Total **                   %5d\n",hdr_rsize(header));
  243.       } else {
  244. error:
  245.          puts("Database file corrupt!");
  246.       }
  247.       close(fp);
  248.    } else
  249.       printf("Couldn't open database : %s\n",filename);
  250. }
  251.  
  252.  
  253. void usage()
  254. {
  255.    register STRPTR *st;
  256.    for(st = usagemessage; **st; st++)
  257.       puts(*st);
  258. }
  259.