home *** CD-ROM | disk | FTP | other *** search
- DECLARE FUNCTION GetSetTracker% (recordno&, mode%)
- DECLARE FUNCTION GetDeleteLink2% (btHandle%, mode%, link&)
- DECLARE SUB DoAbend (msg$, errc%)
-
- REM BT2DBF.BAS
- REM 31-Jul-91
- REM Cornel Huth
-
- 'convert a QBTree data file to QBXDBF .DBF data and .DBX index files
- 'if you have multiple index files for a data file you need to make
- 'changes to this code or just write a routine from scratch using reindex--
- '--real easy.
-
- 'this isn't pretty but it works
-
- REM $INCLUDE: 'QBXDBF.BI'
-
- DEFINT A-Z
-
- CONST SETRACK = 0
- CONST GETRACK = 1
-
- TYPE QBTtype
- dtype AS STRING * 1
- start AS INTEGER
- bytes AS INTEGER
- END TYPE
-
- REDIM SHARED DelTracker(0 TO 32766) AS INTEGER
-
- DIM SHARED btHandle AS INTEGER
- DIM SHARED btRecLen AS INTEGER
- DIM SHARED btAvailList&
-
- DIM ReadBuffer AS STRING * 2080
- DIM DBFrecord AS STRING * 2048
- DIM temp AS STRING * 255
-
- rbseg = VARSEG(ReadBuffer)
- rboff = VARPTR(ReadBuffer)
- dbfseg = VARSEG(DBFrecord)
- dbfoff = VARPTR(DBFrecord)
-
- OpenMode = 2
- dbfile = 0
- kyfile = 0
-
- CLS
- PRINT "BT2DBF ■ QBTree data file to QBXDBF"
- PRINT
- INPUT "QBTree source file: ", BTS$
-
- IF LEN(BTS$) = 0 THEN DoAbend "No source file", 999
-
- 'construct base filename
-
- dot = INSTR(BTS$, ".")
- ldot = dot
- DO WHILE dot
- dot = INSTR(dot + 1, BTS$, ".")
- IF dot THEN ldot = dot
- LOOP
- IF ldot = 1 THEN '.\FILE
- fbase$ = BTS$
- ELSEIF ldot = 2 AND ASC(BTS$) = 46 THEN '..\FILE
- fbase$ = BTS$
- ELSEIF ldot > 2 THEN
- fbase$ = LEFT$(BTS$, ldot - 1)
- ELSEIF ldot = 0 AND LEN(BTS$) THEN
- fbase$ = BTS$
- ELSE
- fbase$ = "NONAME"
- END IF
- DBF$ = fbase$ + ".DBF"
- DBX$ = fbase$ + ".DBX"
- DBT$ = fbase$ + ".$$$"
- LOCATE 3, 40
- PRINT "QBXDBF out files: "; RIGHT$(fbase$, 13) + ".DBF/.DBX"
-
- BTS$ = BTS$ + CHR$(0)
-
- 'open the QBTree data file
-
- stat = OpenDevice(BTS$, OpenMode, btHandle, btLen&)
- IF btLen& > 2048 THEN bytes& = 2048& ELSE bytes& = btLen&
-
- IF stat = 0 THEN
- stat = ReadDevice(btHandle, 0&, bytes&, rbseg, rboff)
- IF stat = 0 THEN IF MID$(ReadBuffer, 1, 1) <> "S" THEN stat = 228
- END IF
- IF stat THEN DoAbend BTS$, stat
-
- 'get header info and prompt for number of fields to translate to
-
- btRecLen = CVI(MID$(ReadBuffer, 2, 2))
- btNoRecs& = CVL(MID$(ReadBuffer, 4, 3) + CHR$(0))
- btAvailList& = CVL(MID$(ReadBuffer, 7, 3) + CHR$(0))
-
- PRINT "reclen="; btRecLen; " recs="; btNoRecs&;
- INPUT ; " fields= ", btNoFields
- IF btNoFields < 1 OR btNoFields > 1023 THEN DoAbend "Bad Field Count", 999
- LOCATE 4, 40
- PRINT USING "reclen=####"; 0
-
- 'allocate the Field List array
-
- REDIM FLA(1 TO btNoFields) AS DBFFieldListTYPE
- REDIM QBT(1 TO btNoFields) AS QBTtype
-
- 'prompt for the field info
-
- LOCATE 6, 1
- PRINT "Field ---NAME--- TYPE LEN DC QBType start bytes ----QBTree Data Rec #1 ---";
-
- LOCATE 19, 1
- PRINT STRING$(80, 196)
- PRINT "NAME=1 to 10 alphanumeric chars only, start with letter, no spaces, _ is valid"
- PRINT "TYPE=(C)haracter (N)umeric (D)ate (L)ogical"
- PRINT "LEN=C(1-255) N(1-19) D(8)=MM/DD/YY L(1)=T/F or Y/N or blank"
- PRINT "DC=dec in N data type(0,2-15) min LEN with DC<>0 is ##.## (LEN=5 DC=2)"
- PRINT "QBtype=$ % & ! #, start=byte position in record, bytes=length of $";
-
- VIEW PRINT 7 TO 18
-
- FOR i = 1 TO btNoFields
- PRINT USING "###"; i;
-
- IF0:
- LOCATE , 7
- INPUT ; "", FLA(i).FieldName
- FLA(i).FieldName = UCASE$(FLA(i).FieldName)
- LOCATE , 7
- PRINT FLA(i).FieldName; " ";
- redo = 0
- IF INSTR(RTRIM$(FLA(i).FieldName), " ") THEN GOTO IF0
- IF ASC(FLA(i).FieldName) < 65 THEN GOTO IF0
- FOR j = 1 TO i - 1
- IF FLA(i).FieldName = FLA(j).FieldName THEN redo = -1: EXIT FOR
- NEXT
- IF redo GOTO IF0
-
- IF1:
- LOCATE , 21
- INPUT ; "", FLA(i).FieldType
- FLA(i).FieldType = UCASE$(FLA(i).FieldType)
- LOCATE , 21
- PRINT FLA(i).FieldType; " ";
- IF INSTR("CNDL", FLA(i).FieldType) = 0 THEN GOTO IF1
- IF FLA(i).FieldType = "C" THEN FLA(i).FieldDC = 0
- IF FLA(i).FieldType = "L" THEN FLA(i).FieldDC = 0
- IF FLA(i).FieldType = "D" THEN FLA(i).FieldLen = 8: FLA(i).FieldDC = 0
-
- IF2:
- LOCATE , 25
- INPUT ; "", FLA(i).FieldLen
- LOCATE , 25
- PRINT FLA(i).FieldLen; " ";
- redo = 0
- SELECT CASE FLA(i).FieldType
- CASE "C"
- IF FLA(i).FieldLen > 255 THEN redo = -1
- CASE "N"
- IF FLA(i).FieldLen > 19 THEN redo = -1
- CASE "D"
- IF FLA(i).FieldLen <> 8 THEN redo = -1
- CASE "L"
- IF FLA(i).FieldLen > 1 THEN redo = -1
- CASE ELSE
- END SELECT
- IF FLA(i).FieldLen < 1 THEN redo = -1
- IF redo THEN GOTO IF2
-
- IF3:
- LOCATE , 30
- INPUT ; "", FLA(i).FieldDC
- redo = 0
- SELECT CASE FLA(i).FieldType
- CASE "C", "D", "L"
- FLA(i).FieldDC = 0
- CASE "N" 'simple check only here, consult a dBASE/FOX/Clipper manual for
- 'specific limitations, also on N length
- IF FLA(i).FieldDC = 1 THEN redo = -1
- CASE ELSE
- END SELECT
- LOCATE , 30
- PRINT FLA(i).FieldDC; " ";
- IF redo THEN GOTO IF3
-
- IF4:
- LOCATE , 36
- INPUT ; "", QBT(i).dtype
- LOCATE , 36
- PRINT QBT(i).dtype; " ";
- IF INSTR("$%&!#", QBT(i).dtype) = 0 THEN GOTO IF4
-
- IF5:
- LOCATE , 43
- INPUT ; "", QBT(i).start
- IF QBT(i).start = 0 THEN
- IF i > 1 THEN
- QBT(i).start = QBT(i - 1).start + QBT(i - 1).bytes
- ELSE
- QBT(i).start = 1
- END IF
- END IF
- LOCATE , 43
- PRINT QBT(i).start; " ";
- IF QBT(i).start < 0 OR QBT(i).start > btRecLen THEN GOTO IF5
- IF i > 1 THEN IF QBT(i).start < (QBT(i - 1).start + QBT(i - 1).bytes) THEN GOTO IF5
-
- IF6:
- LOCATE , 50
- INPUT ; "", QBT(i).bytes
-
- 'enter a -1 at the last prompt to re-enter this field's info
-
- IF QBT(i).bytes = -1 THEN GOTO IF0
-
- redo = 0
- IF QBT(i).start + QBT(i).bytes - 1 > btRecLen THEN GOTO IF5
- SELECT CASE QBT(i).dtype
- CASE "$"
- IF QBT(i).bytes < 1 OR QBT(i).bytes > 255 THEN redo = -1
- CASE "%"
- QBT(i).bytes = 2
- CASE "&", "!"
- QBT(i).bytes = 4
- CASE "#"
- QBT(i).bytes = 8
- CASE ELSE
- END SELECT
- LOCATE , 50
- PRINT QBT(i).bytes; " ";
- IF redo THEN GOTO IF6
-
- 'construct this field for first record as an example
-
- temp = MID$(ReadBuffer, 32 + QBT(i).start, QBT(i).bytes)
- LOCATE , 55
- SELECT CASE QBT(i).dtype
- CASE "$"
- PRINT LEFT$(temp, 26)
- CASE "%"
- PRINT CVI(temp)
- CASE "&"
- PRINT CVL(temp)
- CASE "!"
- PRINT CVS(temp)
- CASE "#"
- PRINT CVD(temp)
- CASE ELSE
- END SELECT
-
- old = CSRLIN
- runlen = runlen + FLA(i).FieldLen
- VIEW PRINT
- LOCATE 4, 40
- PRINT USING "reclen=####"; runlen
- VIEW PRINT 7 TO 18
- LOCATE old, 1
-
- NEXT
-
- VIEW PRINT 20 TO 25
- CLS
-
-
- 'start up QBXDBF
-
- stat = InitDBF(1, 1, btNoFields)
- IF stat THEN DoAbend "InitDBF", stat
-
- 'create the QBXDBF file
-
- stat = CreateDataDBF(DBF$, btNoFields, FLA())
- IF stat = 230 THEN
-
- IF7:
- LOCATE , 1
- PRINT DBF$; " exists--delete it? (y/n) ";
- ccol = POS(0)
- INPUT ; "", a$
- a$ = LEFT$(UCASE$(a$) + CHR$(0), 1)
- LOCATE , ccol
- PRINT a$; " ";
- IF INSTR("YN", a$) = 0 THEN GOTO IF7
- PRINT
- IF UCASE$(a$) = "Y" THEN
- stat = DeleteFile(DBF$ + CHR$(0))
- IF stat = 0 THEN stat = CreateDataDBF(DBF$, btNoFields, FLA())
- END IF
- END IF
- IF stat = 0 THEN stat = OpenDataDBF(DBF$, dbfile, OpenMode)
- IF stat THEN DoAbend DBF$, stat
-
- PRINT "Example key expression: UPPER(SUBSTR("; RTRIM$(FLA(1).FieldName); ",1,5))+..."
- oldLine = CSRLIN
-
- 'delete DBF$ partner index
-
- IF FileExists(DBX$) = -1 THEN stat = DeleteFile(DBX$ + CHR$(0))
-
- IF8:
- LOCATE oldLine, 1
- LINE INPUT ; "Key expression: "; kx$
- stat = CreateKeyDBF(DBX$, kx$, dbfile)
- IF stat = 240 THEN
- LOCATE , 1: PRINT SPACE$(79);
- GOTO IF8
- END IF
- stat = OpenKeyDBF(DBX$, kyfile, dbfile, OpenMode)
- IF stat THEN DoAbend "Open " + DBX$, stat
- PRINT
-
- IF9:
- LOCATE , 1
- INPUT ; "Skip records marked as deleted? (y/n) ", SkipDel$
- SkipDel$ = LEFT$(UCASE$(SkipDel$) + CHR$(0), 1)
- LOCATE , 39
- PRINT SkipDel$; " ";
- IF INSTR("YN", SkipDel$) = 0 THEN GOTO IF9
- PRINT
- IF SkipDel$ = "Y" THEN
- LOCATE , 1: PRINT delcnt&; "deleted records found";
- stat = GetDeleteLink2(btHandle, 0, link&)
- DO WHILE stat = 0
- stat = GetDeleteLink2(btHandle, 1, link&)
- IF stat = 0 THEN
- stat = GetSetTracker(link&, SETRACK)
- delcnt& = delcnt& + 1
- LOCATE , 1: PRINT delcnt&; "deleted records found";
- END IF
- LOOP
- PRINT
- IF stat = 202 THEN stat = 0
- END IF
- IF stat THEN DoAbend "Searching delete list", stat
-
- 'read each record from the QBTree data file
- 'if it's not deleted then AddRecordDBF()
-
- cnt& = 0
- recno& = 1
- start& = 32&
- PRINT "Records added"; cnt&;
- DO
- IsDeleted = GetSetTracker(recno&, GETRACK)
- IF IsDeleted = 0 THEN
- start& = 1& * 32 + ((recno& - 1) * btRecLen)
- stat = ReadDevice(btHandle, start&, btRecLen, rbseg, rboff)
- IF stat = 0 THEN
- cnt& = cnt& + 1
- LOCATE , 14: PRINT cnt&;
- MID$(DBFrecord, 1, 1) = " "
- bpos = 2 'skip past delete tag
- FOR i = 1 TO btNoFields
-
- 'convert the stuff to what is expected in .DBF format (all ASCII)
-
- SELECT CASE QBT(i).dtype
- CASE "$"
- MID$(DBFrecord, bpos, QBT(i).bytes) = MID$(ReadBuffer, QBT(i).start, QBT(i).bytes)
- CASE "%"
- tint = CVI(MID$(ReadBuffer, QBT(i).start, QBT(i).bytes))
- MID$(DBFrecord, bpos) = MKN$(dbfile, i, CDBL(tint), stat)
- CASE "&"
- tlng& = CVL(MID$(ReadBuffer, QBT(i).start, QBT(i).bytes))
- MID$(DBFrecord, bpos) = MKN$(dbfile, i, CDBL(tlng&), stat)
- CASE "!"
- tsng! = CVS(MID$(ReadBuffer, QBT(i).start, QBT(i).bytes))
- MID$(DBFrecord, bpos) = MKN$(dbfile, i, CDBL(tsng!), stat)
- CASE "#"
- tdbl# = CVD(MID$(ReadBuffer, QBT(i).start, QBT(i).bytes))
- MID$(DBFrecord, bpos) = MKN$(dbfile, i, tdbl#, stat)
- CASE ELSE
- END SELECT
-
- bpos = bpos + FLA(i).FieldLen
-
- NEXT
- stat = AddRecordDBF(dbfile, dbfseg, dbfoff, nul&)
- END IF
- END IF
- recno& = recno& + 1
- LOOP WHILE stat = 0
- IF stat = -2 THEN stat = 0
- IF stat THEN DoAbend "Adding records", stat
-
- 'reindex
- PRINT
- PRINT "Reindexing"
- IF FileExists(DBT$) = -1 THEN stat = DeleteFile(DBT$ + CHR$(0))
- IF stat = 0 THEN stat = CopyKeyStrucDBF(kyfile, DBT$)
- IF stat = 0 THEN
- stat = ReIndexDBF(kyfile, dbfile, DBT$)
- IF stat = 0 THEN
- stat = CloseKeyDBF(kyfile)
- IF stat = 0 THEN
- stat = DeleteFile(DBX$ + CHR$(0))
- IF stat = 0 THEN
- stat = RenameFile(DBT$ + CHR$(0), DBX$ + CHR$(0))
- IF stat = 0 THEN
- stat = OpenKeyDBF(DBX$, kyfile, dbfile, OpenMode)
- IF stat THEN DoAbend "Open " + DBX$, stat
- END IF
- END IF
- END IF
- IF stat THEN DoAbend "DOS I/O", stat
- END IF
- IF stat THEN DoAbend "Reindexing", stat
- END IF
- IF stat THEN DoAbend "Copy Struc", stat
-
- 'take a look at them, what the heck
- '2.5 hours, down-n-dirty BASIC
-
- PRINT "Records counted";
-
- stat = GetFirstDBF(kyfile, dbfile, dbfseg, dbfoff)
- cnt& = 0
- DO WHILE stat = 0
- cnt& = cnt& + 1
- LOCATE , 16: PRINT cnt&;
- stat = GetNextDBF(kyfile, dbgile, dbfseg, dbfoff)
- LOOP
- PRINT
- PRINT
-
- xit:
- VIEW PRINT
- nul = CloseDevice(btHandle)
- stat = ExitDBF
- LOCATE 25, 1: PRINT SPACE$(80);
- LOCATE 24, 1: PRINT "Done.";
- CLEAR
- END
-
- SUB DoAbend (msg$, errc)
-
- VIEW PRINT 20 TO 25
- CLS
- PRINT "Error:"; errc; "on "; msg$
- IF btHandle THEN nul = CloseDevice(btHandle)
- nul = ExitDBF
- SYSTEM
-
- END SUB
-
- FUNCTION GetDeleteLink2 (btHandle, mode, link&)
-
- 'traverse the deleted records' linked-list
- 'mode<>0 then for each time called return in link& the next deleted record-
- '-in list, when link& returned as 0 then last link was end of list (stat=202)
- 'mode=0 then reinit start link
-
- STATIC nextlinkrec&
-
- DIM AvailPtr AS STRING * 8
-
- IF mode = 0 THEN
- nextlinkrec& = 0&
- link& = 0
- ELSE
- IF nextlinkrec& = 0 THEN
- recno& = btAvailList&
- btAvailList& = 0
- ELSE
- recno& = nextlinkrec&
- END IF
- IF recno& <> 0 THEN
- apseg = VARSEG(AvailPtr)
- apoff = VARPTR(AvailPtr)
- start& = 1& * 32 + ((recno& - 1) * btRecLen)
- stat = ReadDevice(btHandle, start&, 3&, apseg, apoff)
- IF stat = 0 THEN nextlinkrec& = CVL(LEFT$(AvailPtr, 3) + CHR$(0))
- GetDeleteLink2 = stat
- ELSE
- GetDeleteLink2 = 202 'return EOF when at last deleted link&
- END IF
- link& = recno&
- END IF
-
- END FUNCTION
-
- FUNCTION GetSetTracker (recordno&, mode)
-
- 'bitmap of deleted records, max records supported: 65532*8 = 524,256 recs
-
- ndx = (recordno& - 1) \ 16
- bmask& = 1& * 2 ^ ((recordno& - 1) MOD 16)
- IF bmask& > 32767 THEN bitmask = bmask& - 65536 ELSE bitmask = bmask&
-
- IF mode = GETRACK THEN
- IsDeleted = DelTracker(ndx) AND bitmask
- ELSE
- DelTracker(ndx) = DelTracker(ndx) OR bitmask
- IsDeleted = 0
- END IF
- GetSetTracker = IsDeleted
-
- END FUNCTION
-
-