home *** CD-ROM | disk | FTP | other *** search
- (*
- This program makes a DBASE data base from the catalog files found
- in The Borland LIBs. It will create a DBF and DBT file with user
- supplied name. It will also append new records if an existing file
- name is specified, this will allow updating with the BP???.NEW files.
- The newest files will come last but DBASE can fix that for you.
-
- The program was written in the discovery fashion as I had no information
- on the internal structure of DBASE files when I started. Apoligies aside
- here it is:
- TITLE 60 characters
- KEY_WDS 80 characters
- F_NAME 6 characters
- EXT 3 characters
- BIN 1 logical /binary after file name = true
- USER_ID 10 characters
- DATE 8 Date
- SIZE 6 number
- COUNT 4 number
- INFO 10 memo has pointer to the file description
- in the *.DBT file.
-
- This is written to the header with an array constant and could be
- modified fairly easy. The output files are type ARRAY OF CHAR (read slow)
- because the header for the DBF file is not the same size as the records.
-
- I used the '[' Char followed by {0..9} for the input record seperator
- which causes a problem when a guy puts his user-id in the file description
- (his name is Michael Day ), you'll have to edit the input file to solve
- this. The only other problem I know of is one file had the date followed
- by another date in '()'. If the program crashes it will probably be a
- range check error, the program outputs the record number and date(DBASE
- style ie. YYYYMMDD) the offending entry will most likely be the one just
- after the last listed.
- IF the description is more than 510 chars it will be truncated.
- IF there is no 'Title', the first sentence or first 60 chars of the
- description will go in the TITLE field.
-
- This DBASE prog. works a little like BROWSE.
- * BP_FIND.PRG
- * Searches for key word in KEY_WDS Field
- set talk off
- Set MemoWidth TO 60
- CLEAR
- @ 0,0
- ACCEPT "Enter Key Word " TO Sword
- LOCATE FOR UPPER(Sword)$Key_Wds
- DO WHILE .NOT. EOF()
- @ 3,0 CLEAR
- Disp F_Name,Ext,USER_ID,Size,Count,date
- Disp Title OFF
- Disp INFO OFF
- WAIT
- CONT
- LOOP
- ENDDO
- SET TALK ON
- Set MemoWidth TO 50
- RETURN
- *)
-
-
- Program Cat2Db; (* By Bill Drummond 1990 *)
-
- (*$R+*) (* Crashes ugly without Range Check *)
- USES CRT;
- (*****************************************)
- VAR
- InPutArray : ARRAY[0..2000] OF CHAR;
- OutPutArray : ARRAY[0..288] OF CHAR;
- MemoArray : ARRAY[0..511] OF CHAR;
- InFile,OutFile,MemoFile : FILE OF CHAR;
- InSize : INTEGER;
- StartOfRec,UserIdEnd,KWEnd,MemoEnd : Integer;
- MemoCtr,OutCtr : INTEGER;
- DownLoad: BOOLEAN; (* sometimes nobody has downloaded a file *)
- NoTitle : BOOLEAN; (* so we know to fake a title *)
- Done : BOOLEAN;
- HiByte,LoByte : CHAR;(* so we can read 2 byte values from file *)
- OutFileIndex,MemoFileIndex : LONGINT;
- InFileName :STRING;
- OutFileName :STRING;
- MemoFileName:STRING;
- OverWrite,Cancel : BOOLEAN;
- CONST
- (* try to make it easy to change field lengths.
- See procedure WriteDBFHeader *)
- OutRecSize = 189;
- MemoSize = $200;
- (* first char of first field is actually the deleted record flag *)
- LenTitle = 61; LenKeyWd = 80; LenFname = 6; LenBin = 1;
- LenUserId = 10; LenExt = 3;LenDate = 8; LenSize = 6; LenCount = 4;
- LenMemo = 10;
- TitleSt = 1;
- KeyWdSt = LenTitle;
- FNameSt = LenTitle+LenKeyWd;
- ExtSt = LenTitle+LenKeyWd+LenFname;
- BinSt = LenTitle+LenKeyWd+LenFname+LenExt;
- UserIdSt = LenTitle+LenKeyWd+LenFname+LenExt+LenBin;
- DateSt = LenTitle+LenKeyWd+LenFname+LenExt+LenBin+LenUserId;
- SizeSt = LenTitle+LenKeyWd+LenFname+LenExt+LenBin+LenUserId+LenDate;
- countSt = LenTitle+LenKeyWd+LenFname+LenExt+LenBin+LenUserId+LenDate+LenSize;
- MemoSt = LenTitle+LenKeyWd+LenFname+LenExt+LenBin+LenUserId+LenDate+LenSize+LenCount;
- LeftBracket = '[';
- RightBracket = ']';
- CR = CHR($0D);
- Space = CHR($20);
- Term = CHR($1A);
- (*****************************************)
- PROCEDURE InitDbaseArray;
- VAR I : INTEGER;
- BEGIN
- FOR I := 0 TO OutRecSize-1 DO
- BEGIN
- OutPutArray[I] := Space;
- END;
- END;
- (*****************************************)
- Function FindWord(FWord : String;Position : INTEGER): INTEGER;
- (* used to find where sub-string starts in the input array,
- Position gives it a head start *)
- VAR x : INTEGER;
- TestStr : String;
- BEGIN
- TestStr[0] := FWord[0];
- REPEAT
- IF InPutArray[Position] = FWord[1] THEN
- BEGIN
- FOR x := 1 to Length(FWord) DO
- BEGIN
- TestStr[x] := InputArray[Position+x-1];
- END;
- IF Fword = TestStr THEN
- BEGIN
- FindWord := Position;
- Exit;
- END;
- INC(Position);
- END;
- INC(Position);
- UNTIL Position >= InSize;
- FindWord := 0;
- END;
- (*****************************************)
- PROCEDURE Title;
- VAR I,J,x : INTEGER;
-
- BEGIN
- I := TitleSt;
- NoTitle := False;
- x := FindWord('Title',0);
- IF x = 0 THEN
- BEGIN
- Notitle := TRUE;
- EXIT;
- END;
- J := x+10;
- REPEAT
- OutPutArray[I] := InputArray[J];
- INC(I); INC(J);
- UNTIL (OutPutArray[I-1] = CR);
-
- OutputArray[I-1] := Space;
- END;
- (*****************************************)
- PROCEDURE KeyWords;
- VAR I,J,K,S : INTEGER;
- CONST
- CrLfSpSpSpSp : String =(#$0d+#$0a+' ');
- CrLFCrLf : String =(#$0d+#$0a+#$0d+#$0a);
- BEGIN
- I := KeyWdSt;
- S := FindWord('Keywords',0);
- J := S+10;
- REPEAT
- OutPutArray[I] := InputArray[J];
- INC(I); INC(J);
- UNTIL (OutPutArray[I-1] = CR);
- OutputArray[I-1] := ' ';
- KWEnd := J-1;
- J := FindWord(CrLfSpSpSpSp,j-20)+6;
- K := FindWord(CrLfCrLf,j-20)+6;
- IF K < J THEN EXIT;
- REPEAT
- OutPutArray[I] := InputArray[J];
- INC(I); INC(J);
- UNTIL (OutPutArray[I-1] = #$0d);
- OutputArray[I-1] := Space;
- KWEnd := J-1;
- END;
- (*****************************************)
- PROCEDURE UserId;
- VAR I,J : INTEGER;
- ID : String[9];
- BEGIN
- I := UserIdSt;
- J := StartOfRec;
- REPEAT
- OutPutArray[I] := InputArray[J];
- INC(I); INC(J);
- UNTIL (OutPutArray[I-1] = ']');
- OutputArray[I-1] := ' ';
- UserIdEnd := J;
- END;
- (*****************************************)
- PROCEDURE Date;
- CONST
- Month : STRING =
- 'Jan01Feb02Mar03Apr04May05Jun06Jul07Aug08Sep09Oct10Nov11Dec12';
- VAR I,J : INTEGER;
- M,D : STRING[2]; Y : STRING[4];
- DATE : STRING[8];
- BEGIN
- Y := ' ';M := ' ';
- I := DateSt;
- J := UserIdEnd+28;
- D[1] := InputArray[J];
- INC(J);
- D[2] := InputArray[J];
- INC(J,2);
- Y[1] := InputArray[J];
- INC(J);
- Y[2] := InputArray[J];
- INC(J);
- Y[3] := InputArray[J];
- INC(J,2);
- M[1] := MONTH[Pos(Y,Month)+3];
- M[2] := MONTH[Pos(Y,Month)+4];
- Y := ' ';
- Y[3] := InputArray[J];
- INC(J);
- Y[4] := InputArray[J];
- Y[1] := '1'; Y[2] := '9';
- DATE := Y+M+D;
- Write(OutCtr);
- WriteLn(' ',Date);
- I := 1;
- FOR J := DateSt TO DateSt+7 DO
- BEGIN
- OutputArray[J] := DATE[I];
- INC(I);
- END;
- END;
- (*****************************************)
- PROCEDURE Count;
- VAR I,J : INTEGER;
- St : STRING[8];
- BEGIN
- I := 1;
- J := UserIdEnd+57;
- REPEAT
- St[0] := CHR(I-1);
- ST[I] := InputArray[J];
- INC(I); INC(J);
- UNTIL (ST[I-1] = Space) OR (ST[I-1] = CR);
- FOR J := 1 TO ORD(ST[0]) DO
- Outputarray[CountSt+ (LenCount-Length(ST))+J-1] := ST[J];
- END;
-
- (*****************************************)
- PROCEDURE Size;
- VAR I,J,O : INTEGER;
- St : STRING[8];
- BEGIN
- I := 1;
- J := UserIdEnd+38;
- REPEAT
- St[0] := CHR(I-1);
- ST[I] := InputArray[J];
- INC(I); INC(J);
- UNTIL (ST[I-1] = Space) OR (ST[I-1] = CR);
- IF (ST[I-1] <> CR) THEN
- Count;
- FOR J := 1 TO ORD(ST[0]) DO
- Outputarray[SizeSt+ (LenSize-Length(ST))+J-1] := ST[J];
- END;
-
- (*****************************************)
- PROCEDURE FName;
- VAR I,J,x : INTEGER;
- BEGIN
- I := FnameSt;
- J := UserIdEnd+2;
- REPEAT
- OutPutArray[I] := InputArray[J];
- INC(I); INC(J);
- UNTIL (OutPutArray[I-1] = '.');
- OutPutArray[I-1] := ' ';
- I := ExtSt;
- FOR x := 1 to 3 DO
- BEGIN
- OutPutArray[I] := InputArray[J];
- INC(I); INC(J);
- END;
- IF (FindWord('binary',0) <> 0) THEN
- OutputArray[BinSt] := 'T'
- Else
- OutputArray[BinSt] := 'F';
- END;
-
- (*****************************************)
- PROCEDURE ReadFile; (* get data till we have 2 left brackets *)
- VAR
- CH,CX : CHAR;
- BrackCnt : INTEGER;
- CONST
- Number : SET OF '0'..'9' = ['0'..'9'];
- BEGIN
- BrackCnt := 0;
- InSize := 0;
- READ(InFile,CH);
- WHILE (BrackCnt < 2) AND (CH <> Term) DO
- BEGIN
- READ(InFile,CH);
- IF (CX = LeftBracket) AND NOT (CH IN Number) THEN
- DEC(BrackCnt);
- CX := CH;
- InPutArray[InSize] := CH;
- INC(InSize);
- IF CH = LeftBracket THEN
- BEGIN
- IF BrackCnt = 0 THEN
- StartOfRec := InSize;
- INC(BrackCnt);
- END;
- END;
- Done := EOF(InFile);
- SEEK(InFile,FilePos(InFile)-2); (* back up to before left bracket *)
- DEC(InSize,2);
- END;
- (******************************************)
- PROCEDURE Memo;
- VAR St : STRING[10];
- I,J: INTEGER;
- CONST
- CrLfSpSpSpSp : String =(#$0d+#$0a+' ');
- BEGIN
- Str(MemoCtr,St);
- For I := 1 TO Length(St) DO
- OutputArray[MemoSt +(LenMemo-Length(St))+I-1] := St[I];
- J := FindWord(CrLfSpSpSpSp,KWEND);
- I := 0;
- REPEAT
- MemoArray[I] := InputArray[J];
- INC(I); INC(J);
- UNTIL (J = InSize) OR (I = 509);
- MemoEnd := I-1;
-
- END;
- (******************************************)
- PROCEDURE WriteFile;
- CONST
- AlphaNum : SET OF '0'..'z' = ['0'..'9','A'..'Z','a'..'z'];
- DEOF :CHAR = #$1a;
- CR :CHAR = #$0d;
- LF :CHAR = #$0a;
- VAR I,J : INTEGER;
- Key : CHAR;
- BEGIN
- InitDbaseArray; (* erase to spaces *)
- INC(OutCtr);
- ReadFile;
- Title; (* put em in right order so if we step to far *)
- KeyWords; (* the next guy will fix it *)
- UserId;
- Date;
- FName; (* fname.ext/binary *)
- Size; (* this will get count too. easy to see if it's missing here *)
- Memo; (* this will write memo field pointer in DBF file
- and stuff memo array *)
-
- IF NoTitle THEN (* make one any way *)
- BEGIN
- J := 0;
- I := TitleSt;
- REPEAT
- INC(J);
- UNTIL MemoArray[J] IN AlphaNum; (* zap spaces and blank lines *)
- REPEAT
- OutputArray[I] := MemoArray[J];
- INC(I); INC(J);
- UNTIL ((MemoArray[J-1] = '.') AND (MEMOArray[J] = Space)) OR
- (MemoArray[J] = CR) OR
- (I = LenTitle);
- END;
-
- (* write assembled record to DBF file *)
- FOR I := 0 TO OutRecSize-1 DO
- BEGIN
- Write(OutFile,OutputArray[I]);
- END;
-
- (* Now write to the memo file
- memo records are up to 510 bytes + 2 eofs
- DBASE will let you make them multiples of 512
- but I did't make the effort.
- *)
- INC(MemoCtr);
- Seek(MemoFile,MemoFileIndex); (* always start on 512 byte boundry *)
- FOR I := 0 TO MemoEnd-1 DO
- BEGIN
- IF MemoArray[I] = CR THEN
- MemoArray[I] := #$8d; (* CR with hi bit set for word wrap *)
- Write(MemoFile,MemoArray[I]);
- END;
- Write(MemoFile,CR);
- Write(MemoFile,LF);
- Write(MemoFile,DEOF);
- Write(MemoFile,DEOF);
- INC(MemoFileIndex,MemoSize);
- END;
- (*****************************************)
- PROCEDURE WriteDBFHeader;
- CONST
- (* header loc 4,5 = record pointer
- header loc 8,9 = header size
- header loc 8,9 = Record size *)
- DBFHeader : ARRAY[0..$160] OF CHAR = (
- #$83,#$59,#$0c,#$1d,#0,#0,#0,#0,#$61,#$01,#$bd,#0,#0,#0,#0,#0,
- #0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,
- 'T','I','T','L','E', #0,#0,#0,#0,#0,#0, 'C',#0,#0,#0,#0,
- #60,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,
- 'K','E','Y','_','W','D','S',#0,#0,#0,#0, 'C',#0,#0,#0,#0,
- #80,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,
- 'F','_','N','A','M','E', #0,#0,#0,#0,#0, 'C',#0,#0,#0,#0,
- #6,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,
- 'E','X','T', #0,#0,#0,#0,#0,#0,#0,#0,'C',#0,#0,#0,#0,
- #3,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,
- 'B','I','N', #0,#0,#0,#0,#0,#0,#0,#0,'L',#0,#0,#0,#0,
- #1,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,
- 'U','S','E','R','_','I','D',#0,#0,#0,#0, 'C',#0,#0,#0,#0,
- #10,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,
- 'D','A','T','E', #0,#0,#0,#0,#0,#0,#0, 'D',#0,#0,#0,#0,
- #8,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,
- 'S','I','Z','E', #0,#0,#0,#0,#0,#0,#0, 'N',#0,#0,#0,#0,
- #6,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,
- 'C','O','U','N','T', #0,#0,#0,#0,#0,#0, 'C',#0,#0,#0,#0,
- #4,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,
- 'I','N','F','O', #0,#0,#0,#0,#0,#0,#0, 'M',#0,#0,#0,#0,
- #10,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#$0D);
- VAR I : INTEGER;
- BEGIN
- ASSIGN(OutFile,OutFileName);
- ReWrite(OutFile);
- FOR I := 0 TO $160 DO
- Write(OutFile,DBFHeader[I]);
- Seek(OutFile,$161);
- END;
- (*****************************************)
- PROCEDURE WriteDBTHeader;
- (* the only thing in memo file header we care about is loc 0,1 and we do
- that after we're done *)
- VAR I : INTEGER;
- N : CHAR;
- BEGIN
- N := #0;
- Assign(MemoFile,MemoFileName);
- ReWrite(MemoFile);
- FOR I := 0 TO $1FF DO
- Write(MemoFile,N);
- END;
- (*****************************************)
- PROCEDURE Query;
- VAR Name : STRING;
- C : CHAR;
- Good : BOOLEAN;
- BEGIN
- OverWrite := TRUE;
- Cancel := FALSE;
- REPEAT
- Write('ENTER CATALOG FILE [\Path\Name.Ext] ');
- READLN(InFileName);
- IF InFileName = '' THEN (* clean get away if stumped *)
- Begin
- Cancel := TRUE;
- EXIT;
- END;
- ASSIGN(InFile,InFileName);
- (*$I-*)
- Reset(InFile);
- (*$I+*)
- IF IORESULT = 0 THEN
- Good := TRUE
- ELSE
- Begin
- WriteLn('File Not Found, Re-Enter (hit enter to quit) ');
- Good := FALSE;
- END;
- UNTIL Good;
- Write('ENTER DBASE FILE [\Path\Name] ');
- READLN(Name);
- OutFileName := Name + '.DBF';
- MemoFileName:= Name + '.DBT';
- ASSIGN(MemoFile,MemoFileName);
- ASSIGN(OutFile,OutFileName);
- (*$I-*)
- Reset(OutFile);
- (*$I+*)
- IF IORESULT = 0 THEN
- BEGIN
- WriteLn('That DBASE File Already Exist.');
- REPEAT
- Write('Overwrite, Append or Cancel : [ O A C ] ');
- C := ReadKey;
- CASE C OF
- 'O','o':Begin
- OverWrite := TRUE;
- Good := TRUE;
- END;
- 'A','a':Begin
- OverWrite := FALSE;
- Good := TRUE;
- END;
- 'C','c':Begin
- Cancel := TRUE;
- Good := TRUE;
- END;
- ELSE
- Begin
- Good := FALSE;
- WriteLn('??');
- END;
- END;
- UNTIL GOOD;
- END;
- WriteLn;
- END;
- (*****************************************)
- PROCEDURE DbaseAppend;
- VAR
- a0,a1,a4,a5,a8,a9,a10,a11 : char;
- RC,RS,HS : LONGINT;
- BEGIN
- Seek(OutFile,4); (*Header Address 4,5 Has Rec Count*)
- Read(OutFile,a4);
- Read(OutFile,a5);
- Seek(OutFile,8); (*Header Address 8,9 Has Rec Size*)
- Read(OutFile,a8);
- Read(OutFile,a9);
- Read(OutFile,a10); (*Header Address 10,11 Has Header Size*)
- Read(OutFile,a11);
- OutCtr := ORD(a4) + (256*ORD(a5));
- RS := ORD(a10) + (256*ORD(a11));
- HS := ORD(a8) + (256*ORD(a9));
- SEEK(OutFile,(OutCtr*RS)+HS);
- Reset(MemoFile); (*Header Address 0,1 Has Memo Count*)
- Read(MemoFile,A0);
- Read(MemoFile,A1);
- MemoCtr := ORD(a0) + (256*ORD(a1));
- MemoFileIndex := MemoCtr; (* put in wide place for multiply *)
- MemoFileIndex := MemoFileIndex*MemoSize;
- END;
- (*****************************************)
- VAR KEY : CHAR;
-
- BEGIN
- ClrScr;
- Query;
- IF Cancel THEN
- Begin
- WriteLn;
- WriteLn('Operation Canceled',#7);
- EXIT;
- END;
- Done := FALSE;
- MemoCtr := 1;
- OutCtr := 0;
- MemoFileIndex := MemoSize;
- ASSIGN(InFile,InFileName);
- RESET(InFile);
- IF OverWrite THEN (* or a new file *)
- Begin
- WriteDBFHeader;
- WriteDbtHeader;
- END
- ELSE
- Begin
- DbaseAppend;
- END;
- REPEAT
- WriteFile;
- UNTIL Done;
-
- (* Now fix up the headers *)
-
- LoByte := CHR(LO(OutCtr));
- HiByte := CHR(Hi(OutCtr));
- SEEK(outFile,4);
- Write(OutFile,LoByte);
- Write(OutFile,HiByte);
- INC(MemoCtr); (* point to next memo *)
- LoByte := CHR(LO(MemoCtr));
- HiByte := CHR(Hi(MemoCtr));
- Reset(MemoFile);
- Write(MemoFile,LoByte);
- Write(MemoFile,HiByte);
-
- CLOSE(InFile);
- CLOSE(OutFile);
- Close(MemoFile);
- END.