home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
bullet25.zip
/
common
/
src
/
ANYDBF.C
next >
Wrap
C/C++ Source or Header
|
1996-11-23
|
8KB
|
231 lines
#include <os2.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "bullet_2.h"
int main(int argc,char *argv[]) {
INITPACK IP;
EXITPACK EP;
DESCRIPTORPACK DP;
OPENPACK OP;
HANDLEPACK HP;
STATDATAPACK SDP;
ACCESSPACK AP; // packs used here
PFIELDDESCTYPE fieldDescPtr; // pointer to field descriptor base allocation
PFIELDDESCTYPE fdPtr; // roving pointer to any field's descriptor
CHAR dataRec[8192]; // 'unknown' record layout since reading "any" DBF
CHAR fmt[32]; // printf() fmt string for on-the-fly formatting
ULONG dataID; // handle of DBF
LONG recNo; // loop counter
BYTE fldNo; // loop counter2
int rez; // primary op return code
int rez2; // secondary op return code (so to perserve primary rc)
if (argc < 2) {
puts("Use: C>progname anyfile.dbf");
return(1);
}
// init Bullet
IP.func = INIT_XB;
IP.JFTsize = 20; // 20 handles is all we need here
rez = BULLET(&IP);
if (rez!=0) {
printf("INIT_XB failed: %d\n",rez);
return(1);
}
// open existing DBF as named in command line
OP.func = OPEN_DATA_XB;
OP.filenamePtr = argv[1];
OP.asMode = READWRITE | DENYNONE;
rez = BULLET(&OP);
if (rez==0) {
dataID = OP.handle;
SDP.func = STAT_DATA_XB;
SDP.handle = dataID;
rez = BULLET(&SDP);
if (rez==0) {
// allocate field descriptors needed (SDP.fields is number needed)
// calloc() used since 0-filled storage is required
fieldDescPtr = calloc(SDP.fields,sizeof(FIELDDESCTYPE));
if (fieldDescPtr != NULL) {
fdPtr = fieldDescPtr; // fdPtr->each descriptor
// read each field descriptor from Bullet, storing to our program
// show each for display
// 1234567890-123456789-123456789-12345
printf("FLD# FIELDNAME T LEN.DEC OFFSET\n");
DP.func = GET_DESCRIPTOR_XB;
DP.handle = dataID;
for (fldNo=1;fldNo <= SDP.fields;fldNo++) {
DP.fieldNumber = fldNo;
rez = BULLET(&DP);
if (rez==0) {
strcpy(fdPtr->fieldName, DP.FD.fieldName);
fdPtr->fieldType = DP.FD.fieldType;
fdPtr->fieldLen = DP.FD.fieldLen;
fdPtr->fieldDC = DP.FD.fieldDC;
fdPtr->fieldDA = DP.fieldOffset;
printf("%3u %-10s %c %3u.%1u %4u\n",
fldNo,
fdPtr->fieldName,
fdPtr->fieldType,
(ULONG) fdPtr->fieldLen,
(ULONG) fdPtr->fieldDC,
fdPtr->fieldDA);
fdPtr++; // next field descriptor
}
else
break;
}
// An interesting item above is where fdPtr->fieldDA is set to
// DP.fieldOffset. fieldDA is a run-time storage area that in
// dBASE is used to directly access the field (DA="direct access").
// It has no meaning except for that particular run (it is a memory
// address). In this program example I use it to store the offset
// of the field, relative the start of the record buffer (where the
// tag byte = offset 0). You could just as easily use some of the
// 12 reserved bytes left over in the descriptor, as I do for the
// alternate field length. But, since fieldDA is already there, and
// not used otherwise, it makes sense to use it.
// Now have all we need to know about the DBF fields, having just
// read and stored the field descriptors. For this example, we
// grab the first nine records and spit them out, by field, in record
// number order (no indexing used).
if (SDP.records != 0) {
AP.func = GET_RECORD_XB;
AP.handle = dataID;
AP.recPtr = &dataRec;
for (recNo=1;recNo <= 9; recNo++) {
printf("\nrecNo %u: ",recNo); // show line number
AP.recNo = recNo; // get this record #...
rez = BULLET(&AP); // ...to dataRec buffer
if (rez==0) {
printf("%.1s ",(CHAR *) dataRec); // show if deleted or not
fdPtr = fieldDescPtr; // fdPtr->first field descriptor
for (fldNo=1;fldNo <= SDP.fields;fldNo++) {
// No special formatting is done on this output for this
// example -- since standard DBF data is always in pure
// ASCII form, all is printable.
switch (fdPtr->fieldType) {
case 'C': // text
case 'D': // date, show as-is
case 'L': // logical, show as-is
case 'M': // memo field (block number in ASCII)
case 'N': // numeric (ASCII)
// make fmt[] string like this: "%xx.xxs"
// where xx is field length for this field
sprintf(fmt,"%%-%i.%is ",
fdPtr->fieldLen,
fdPtr->fieldLen);
// fdPtr->fieldDA=offset of the field within the record
// so it plus dataRec (buffer base) results in the
// offset of the current field we are processing
printf(fmt,dataRec+fdPtr->fieldDA);
break;
default:
printf("\nUnknown field type: %c\n",fdPtr->fieldType);
} // switch
fdPtr += 1; // next field's descriptor
} // for fields
} // if record read
else {
if (rez==EXB_BAD_RECNO) // if < for-count records in DBF
rez=0; // then would get this error
else
printf("Failed GET_RECORD_XB, err: %d\n",rez);
break; // break for any ELSE case
}
} // for records
if (rez==0) printf("\nDone.\n"); // all FOR recs done
}
else
printf("No records in file\n");
free(fieldDescPtr);
}
else
printf("calloc failed!\n");
}
else
printf("STAT_DATA_XB failed: %d\n",rez);
HP.func = CLOSE_DATA_XB;
HP.handle = dataID;
rez2 = BULLET(&HP);
}
else
printf("OPEN_DATA_XB failed: %d\n",rez);
EP.func = EXIT_XB;
rez2=BULLET(&EP);
printf("\nPress ENTER to exit");
getchar();
if (rez==0) rez=rez2; // rez is more important, but if 0 use rez2 result
return rez;
}
#if 0
The above is a complete program. Running it against a sample DBF
results in the following output:
:xmp.
:font facename=Courier size=13x8.
FLD# FIELDNAME T LEN.DEC OFFSET
1 SSN C 9.0 1
2 LNAME C 16.0 10
3 FNAME C 16.0 26
4 HIRED D 8.0 42
5 DEPT_ID C 6.0 50
recNo 1: 465309999 Que Barbie 19900131 BOSS
recNo 2: 445038888 Stewart Jackie 19910228 ACC
recNo 3: 760443232 Whitman Kelly 19920414 HUM
recNo 4: 845309944 Beatty Leslie 19940122 PRG
recNo 5: 555033388 Jasper Amy 19930230 PRG
recNo 6: 430443222 Hauntos Poco 19920414 PRG
recNo 7: 365502949 Hopkins Lisa 19910121 PRG
recNo 8: 685733868 Leonard Rosina 19850218 PRG
recNo 9: 500945242 Morton Holly 19950406 PHY
Done.
Press ENTER to exit
#endif