home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / blt2_214.zip / src / ANYDBF.C next >
C/C++ Source or Header  |  1996-11-23  |  8KB  |  231 lines

  1. #include <os2.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5.  
  6. #include "bullet_2.h"
  7.  
  8. int main(int argc,char *argv[]) {
  9.  
  10. INITPACK IP;
  11. EXITPACK EP;
  12. DESCRIPTORPACK DP;
  13. OPENPACK OP;
  14. HANDLEPACK HP;
  15. STATDATAPACK SDP;
  16. ACCESSPACK AP;          // packs used here
  17.  
  18. PFIELDDESCTYPE fieldDescPtr;    // pointer to field descriptor base allocation
  19. PFIELDDESCTYPE fdPtr;           // roving pointer to any field's descriptor
  20.  
  21. CHAR dataRec[8192];     // 'unknown' record layout since reading "any" DBF
  22. CHAR  fmt[32];          // printf() fmt string for on-the-fly formatting
  23. ULONG dataID;           // handle of DBF
  24. LONG  recNo;            // loop counter
  25. BYTE  fldNo;            // loop counter2
  26. int   rez;              // primary op return code
  27. int   rez2;             // secondary op return code (so to perserve primary rc)
  28.  
  29. if (argc < 2) {
  30.    puts("Use: C>progname anyfile.dbf");
  31.    return(1);
  32. }
  33.  
  34. // init Bullet
  35.  
  36. IP.func = INIT_XB;
  37. IP.JFTsize = 20;                // 20 handles is all we need here
  38. rez = BULLET(&IP);
  39. if (rez!=0) {
  40.    printf("INIT_XB failed: %d\n",rez);
  41.    return(1);
  42. }
  43.  
  44. // open existing DBF as named in command line
  45.  
  46. OP.func = OPEN_DATA_XB;
  47. OP.filenamePtr = argv[1];
  48. OP.asMode = READWRITE | DENYNONE;
  49. rez = BULLET(&OP);
  50. if (rez==0) {
  51.  
  52.    dataID = OP.handle;
  53.  
  54.    SDP.func = STAT_DATA_XB;
  55.    SDP.handle = dataID;
  56.    rez = BULLET(&SDP);
  57.    if (rez==0) {
  58.  
  59.       // allocate field descriptors needed (SDP.fields is number needed)
  60.       // calloc() used since 0-filled storage is required
  61.  
  62.       fieldDescPtr = calloc(SDP.fields,sizeof(FIELDDESCTYPE));
  63.  
  64.       if (fieldDescPtr != NULL) {
  65.  
  66.          fdPtr = fieldDescPtr;          // fdPtr->each descriptor
  67.  
  68.          // read each field descriptor from Bullet, storing to our program
  69.          // show each for display
  70.  
  71.          //      1234567890-123456789-123456789-12345
  72.          printf("FLD#   FIELDNAME  T  LEN.DEC  OFFSET\n");
  73.  
  74.          DP.func = GET_DESCRIPTOR_XB;
  75.          DP.handle = dataID;
  76.          for (fldNo=1;fldNo <= SDP.fields;fldNo++) {
  77.  
  78.             DP.fieldNumber = fldNo;
  79.             rez = BULLET(&DP);
  80.             if (rez==0) {
  81.  
  82.                strcpy(fdPtr->fieldName, DP.FD.fieldName);
  83.                fdPtr->fieldType = DP.FD.fieldType;
  84.                fdPtr->fieldLen = DP.FD.fieldLen;
  85.                fdPtr->fieldDC = DP.FD.fieldDC;
  86.                fdPtr->fieldDA = DP.fieldOffset;
  87.                printf("%3u   %-10s  %c  %3u.%1u     %4u\n",
  88.                   fldNo,
  89.                   fdPtr->fieldName,
  90.                   fdPtr->fieldType,
  91.                   (ULONG) fdPtr->fieldLen,
  92.                   (ULONG) fdPtr->fieldDC,
  93.                   fdPtr->fieldDA);
  94.                fdPtr++;                 // next field descriptor
  95.             }
  96.             else
  97.                break;
  98.          }
  99.  
  100.          // An interesting item above is where fdPtr->fieldDA is set to
  101.          // DP.fieldOffset.  fieldDA is a run-time storage area that in
  102.          // dBASE is used to directly access the field (DA="direct access").
  103.          // It has no meaning except for that particular run (it is a memory
  104.          // address). In this program example I use it to store the offset
  105.          // of the field, relative the start of the record buffer (where the
  106.          // tag byte = offset 0).  You could just as easily use some of the
  107.          // 12 reserved bytes left over in the descriptor, as I do for the
  108.          // alternate field length.  But, since fieldDA is already there, and
  109.          // not used otherwise, it makes sense to use it.
  110.       
  111.          // Now have all we need to know about the DBF fields, having just
  112.          // read and stored the field descriptors.  For this example, we
  113.          // grab the first nine records and spit them out, by field, in record
  114.          // number order (no indexing used).
  115.  
  116.          if (SDP.records != 0) {
  117.  
  118.             AP.func = GET_RECORD_XB;
  119.             AP.handle = dataID;
  120.             AP.recPtr = &dataRec;
  121.  
  122.             for (recNo=1;recNo <= 9; recNo++) {
  123.  
  124.                printf("\nrecNo %u: ",recNo);    // show line number
  125.                AP.recNo = recNo;                // get this record #...
  126.                rez = BULLET(&AP);               // ...to dataRec buffer
  127.                if (rez==0) {
  128.                   printf("%.1s ",(CHAR *) dataRec); // show if deleted or not
  129.  
  130.                   fdPtr = fieldDescPtr; // fdPtr->first field descriptor
  131.  
  132.                   for (fldNo=1;fldNo <= SDP.fields;fldNo++) {
  133.  
  134.                      // No special formatting is done on this output for this
  135.                      // example -- since standard DBF data is always in pure
  136.                      // ASCII form, all is printable.
  137.  
  138.                      switch (fdPtr->fieldType) {
  139.                      case 'C':  // text
  140.                      case 'D':  // date, show as-is
  141.                      case 'L':  // logical, show as-is
  142.                      case 'M':  // memo field (block number in ASCII)
  143.                      case 'N':  // numeric (ASCII)
  144.  
  145.                         // make fmt[] string like this: "%xx.xxs"
  146.                         // where xx is field length for this field
  147.  
  148.                         sprintf(fmt,"%%-%i.%is ",
  149.                                 fdPtr->fieldLen,
  150.                                 fdPtr->fieldLen);
  151.  
  152.                         // fdPtr->fieldDA=offset of the field within the record
  153.                         // so it plus dataRec (buffer base) results in the
  154.                         // offset of the current field we are processing
  155.  
  156.                         printf(fmt,dataRec+fdPtr->fieldDA);
  157.                         break;
  158.                      default:
  159.                         printf("\nUnknown field type: %c\n",fdPtr->fieldType);
  160.                      } // switch
  161.  
  162.                      fdPtr += 1;                  // next field's descriptor
  163.  
  164.                   } // for fields
  165.                } // if record read
  166.  
  167.                else {
  168.                   if (rez==EXB_BAD_RECNO)       // if < for-count records in DBF
  169.                      rez=0;                     // then would get this error
  170.                   else
  171.                      printf("Failed GET_RECORD_XB, err: %d\n",rez);
  172.                   break;                        // break for any ELSE case
  173.                }
  174.  
  175.             } // for records
  176.             if (rez==0) printf("\nDone.\n"); // all FOR recs done
  177.          }
  178.          else
  179.             printf("No records in file\n");
  180.  
  181.          free(fieldDescPtr);
  182.       }
  183.       else
  184.          printf("calloc failed!\n");
  185.    }
  186.    else
  187.       printf("STAT_DATA_XB failed: %d\n",rez);
  188.  
  189.    HP.func = CLOSE_DATA_XB;
  190.    HP.handle = dataID;
  191.    rez2 = BULLET(&HP);
  192. }
  193. else
  194.    printf("OPEN_DATA_XB failed: %d\n",rez);
  195.  
  196. EP.func = EXIT_XB;
  197. rez2=BULLET(&EP);
  198.  
  199. printf("\nPress ENTER to exit");
  200. getchar();
  201. if (rez==0) rez=rez2;  // rez is more important, but if 0 use rez2 result
  202. return rez;
  203. }
  204.  
  205. #if 0
  206. The above is a complete program.  Running it against a sample DBF
  207. results in the following output:
  208.  
  209. :xmp.
  210. :font facename=Courier size=13x8.
  211. FLD#   FIELDNAME  T  LEN.DEC  OFFSET
  212.   1   SSN         C    9.0        1
  213.   2   LNAME       C   16.0       10
  214.   3   FNAME       C   16.0       26
  215.   4   HIRED       D    8.0       42
  216.   5   DEPT_ID     C    6.0       50
  217.  
  218. recNo 1:   465309999 Que              Barbie           19900131 BOSS
  219. recNo 2:   445038888 Stewart          Jackie           19910228 ACC
  220. recNo 3:   760443232 Whitman          Kelly            19920414 HUM
  221. recNo 4:   845309944 Beatty           Leslie           19940122 PRG
  222. recNo 5:   555033388 Jasper           Amy              19930230 PRG
  223. recNo 6:   430443222 Hauntos          Poco             19920414 PRG
  224. recNo 7:   365502949 Hopkins          Lisa             19910121 PRG
  225. recNo 8:   685733868 Leonard          Rosina           19850218 PRG
  226. recNo 9:   500945242 Morton           Holly            19950406 PHY
  227. Done.
  228.  
  229. Press ENTER to exit
  230. #endif
  231.