jph@whuxle.UUCP (05/25/84)
#R:unc:-724700:whuxle:21300008:000:11925 whuxle!jph May 12 10:10:00 1984 Here is a library creation program that I obtained from a bulletin board. =================================== 10 DEFINT A-Z 20 DEF FNH2$(C)=RIGHT$("00"+HEX$(C),2) 30 DEF FNZ(H,L)=((H MOD &H25)*256 + L) MOD &H25 40 DEF FNR(H,L)=((H MOD HSIZE)*256 + L) MOD HSIZE 50 DEF FNS$(S$)=SPACE$(40-LEN(S$)\2)+S$ 60 MAXSYM=1000: DIM SYMB$(MAXSYM), SYMBLOCK(MAXSYM), SYMLOC(MAXSYM) 70 MAXBLK=127: DIM BLKSYM(MAXBLK), BLKSTR(MAXBLK), BLKOVF(MAXBLK) 100 PRINT 110 PRINT FNS$("MAKELIB - A program to create library [.LIB] files.") 120 PRINT 130 PRINT FNS$("Copyright 1983 by Dan Oetting, all commercial rights reserved.") 140 PRINT 150 PRINT FNS$("Version (Preliminary) 0.00 ") 160 PRINT FNS$("Release date: 03-NOV-1983") 170 PRINT FNS$("Last Modification: 31-DEC-1983") 180 PRINT: PRINT 190 ON ERROR GOTO 8000 200 REM Makelib Create an object library file 205 FILEOK=0: WHILE NOT FILEOK 210 INPUT "Library file [.LIB]";LIBFILE$ 215 IF LIBFILE$="" THEN SYSTEM 220 IF INSTR(LIBFILE$,".")=0 THEN LIBFILE$=LIBFILE$+".lib" 230 GOSUB 1000 'Init lib file 235 WEND 240 GOSUB 4490 'init symb tab 250 REM Object file loop 260 INPUT "Object file [.OBJ]";OBJFILE$: IF OBJFILE$="" THEN 480 270 IF INSTR(OBJFILE$,".")=0 THEN OBJFILE$=OBJFILE$+".obj" 280 IF INSTR(OBJFILE$,"*") THEN PRINT: PRINT "List of files matching '" ;OBJFILE$;"'": FILES OBJFILE$: PRINT "Enter each file separatly." : PRINT: GOTO 250 290 SAVELOC=LOFFSET 300 GOSUB 2000 'Init object buffer 310 READING=-1 320 WHILE READING 'REM Object record loop 330 GOSUB 2130 'Get record type and size 340 IF NOT FILEOK THEN GOTO 440 350 IF RTYPE=&H80 THEN GOSUB 3000: GOTO 420 'Process Title record 360 IF RTYPE=&H90 THEN GOSUB 3080: GOTO 420 'Process Global record 370 IF RTYPE=&H8A THEN READING=0: GOTO 420 'End record 380 IF (RTYPE=&HA2) OR (RTYPE=&H8C) OR (RTYPE=&H96) OR (RTYPE=&H98) OR (RTYPE=&H9A) OR (RTYPE=&H9C) OR (RTYPE=&HA0) THEN GOTO 420 'Pass 390 IF RTYPE=&HF0 THEN S$="Cannot includ library file.":GOSUB 2460:GOTO 440 400 IF (RTYPE=0) OR (RSIZE=0) OR (RSIZE>256) THEN S$="Premature end of file": GOSUB 2460: GOTO 440 410 PRINT "Unknown record type (";FNH2$(RTYPE);"), length ";RSIZE; " at offset ";OBJREC*128+OBJPOS-3;" in object file '";OBJFILE$;"'." 420 REM End current record 430 GOSUB 2190 440 WEND 450 REM Process end of object file 460 GOSUB 2250 'Flush buffer 470 GOTO 250 'loop for next file 480 REM produce hash table of global symbols 490 GOSUB 1170 'align lib file 500 HSTART=LOFFSET 510 GOSUB 6000 'Compute size of hash table 520 PRINT:PRINT " HSTART =";HSTART, " HSIZE =";HSIZE, "(blocks)": PRINT 530 GOSUB 4000 'Init block table 540 FOR SYM=1 TO LASTSYM 550 S$=SYMB$(SYM): GOSUB 4050: SYMBLOCK(SYM)=BLK 560 NEXT SYM 570 FOR BLK=0 TO HSIZE-1 580 GOSUB 4190 'init block 590 FOR SYM=1 TO LASTSYM 600 IF SYMBLOCK(SYM)=BLK THEN S$=SYMB$(SYM): GOSUB 4250 'add symb 610 NEXT SYM 620 GOSUB 4410 'put hash block 630 NEXT BLK 640 GOSUB 1210 'Close library file 650 SYSTEM 1000 REM Initialize library file buffer 1005 FILEOK=0 1010 OPEN LIBFILE$ FOR INPUT AS #1:CLOSE #1 'if not found then skip to open 1020 PRINT "File '";LIBFILE$;"' already exists! Should it be deleted";: BEEP 1030 GOSUB 6110: IF NOT YES THEN RETURN 1040 KILL LIBFILE$ 1050 OPEN LIBFILE$ AS #1 LEN=128 1060 FIELD #1, 128 AS LBUF$ 1070 LSET LBUF$=STRING$(128,0) 1080 PUT #1: PUT #1: PUT #1: PUT #1 1090 LOFFSET=1: LQPOS=0: FILEOK=-1 1100 RETURN 'resume here on open error 1110 REM Copy object buffer to lib file 1120 LSET LBUF$=OBUF$ 1130 REM Dump library file buffer 1140 PUT #1 1150 IF LQPOS<3 THEN LQPOS=LQPOS+1 ELSE LQPOS=0: LOFFSET=LOFFSET+1 1160 RETURN 1170 REM Allign to next block 1180 LSET LBUF$=STRING$(128,0) 1190 WHILE LQPOS<>0: GOSUB 1130: WEND 1200 RETURN 1210 REM Close library file 1220 LSET LBUF$=STRING$(128,0) 1230 MID$(LBUF$,1)=CHR$(&HF0)+MKI$(&H1FD)+CHR$(0)+MKI$(HSTART*2)+CHR$(0) +MKI$(HSIZE) 1240 PUT #1,1 'First (quarter) block 1250 CLOSE #1 1260 RETURN 2000 REM Init object file buffer 2010 OPEN OBJFILE$ FOR INPUT AS #2:CLOSE #2 2020 OPEN OBJFILE$ AS #2 LEN=128 2030 FIELD #2, 128 AS OBUF$ 2040 GET #2: OBJPOS=0: OBJREC=0 'Load first block 2050 FILEOK=-1 2060 RETURN 2070 REM Grab a byte from object buffer 2080 IF NOT FILEOK THEN RETURN 2090 WHILE OBJPOS>=128:GOSUB 1110:GET #2:OBJPOS=OBJPOS-128:OBJREC=OBJREC+1:WEND 2100 OBJPOS=OBJPOS+1: RCOUNT=RCOUNT-1 2110 CH$=MID$(OBUF$,OBJPOS,1) 2120 RETURN 2130 REM Get record type and size 2140 IF NOT FILEOK THEN RETURN 2150 GOSUB 2070: RTYPE=ASC(CH$) 2160 GOSUB 2310: RSIZE=WORD: IF RSIZE<0 THEN S$="Record too big.": GOSUB 2460 2170 RCOUNT=RSIZE 2180 RETURN 2190 REM Advance to next record 2200 IF NOT FILEOK THEN RETURN 2210 IF RCOUNT<=0 THEN S$="Record scan error.": GOSUB 2460: RETURN 2220 OBJPOS=OBJPOS+RCOUNT-1 2230 GOSUB 2070 'gets the check byte at end of record 2240 RETURN 2250 REM Close object file, flush buffer 2260 IF NOT FILEOK THEN RETURN 2270 IF OBJPOS>0 THEN GOSUB 1110 2280 GOSUB 1170 'align lib to next block 2290 CLOSE #2 'done with obj file 2300 RETURN 2310 REM Get word value WORD 2320 IF NOT FILEOK THEN RETURN 2330 GOSUB 2070: CH1$=CH$ 2340 GOSUB 2070 2350 WORD=CVI(CH1$+CH$) 2360 RETURN 2370 REM Get string S$ 2380 IF NOT FILEOK THEN RETURN 2390 GOSUB 2070: SIZE=ASC(CH$) 2400 IF SIZE>127 OR SIZE>=RCOUNT THEN S$="String too big.": GOSUB 2460: RETURN 2410 S$=SPACE$(SIZE) 2420 FOR I=1 TO SIZE 2430 GOSUB 2070: MID$(S$,I,1)=CH$ 2440 NEXT I 2450 RETURN 2460 REM Abort processing current object file 2470 PRINT: PRINT S$: BEEP 2480 PRINT "File '";OBJFILE$;"' will not be included in '";LIBFILE$;"'." 2490 PRINT 2500 GET #1, 4*SAVELOC-1 'restore library file position 2510 LASTSYM=SAVESYM 'restore symbol table 2520 READING=0 2530 FILEOK=0 2540 RETURN 3000 REM Process title record 3010 GOSUB 2370 'Get string 3020 IF NOT FILEOK THEN RETURN 3030 PRINT "TITLE ";S$ 3040 OBJLOC=LOFFSET 3050 S$=S$+"!" 3060 GOSUB 4530 'Add S$ to symbol tab 3070 RETURN 3080 REM Process global record 3090 GOSUB 2070: GOSUB 2070 'Skip two bytes 3100 WHILE RCOUNT>1 3110 GOSUB 2370 'get s$ 3120 GOSUB 2310 'get WORD 3130 GOSUB 2070 'get byte CH$ 3140 IF NOT FILEOK THEN RETURN 3150 PRINT "GLOBAL ";S$;" = ";HEX$(WORD);":";HEX$(ASC(CH$)) 3160 GOSUB 4530 'Add S$ to symbol tab 3170 WEND 3180 RETURN 4000 REM Initialize hash block table 4010 FOR I=0 TO HSIZE-1 4020 BLKSYM(I)=0: BLKSTR(I)=0: BLKOVF(I)=0 4030 NEXT I 4040 RETURN 4050 REM assign symbol to block 4060 GOSUB 5000 'Hash symbol S$ 4070 BLK=H2START 'Initial try 4080 FOR BCOUNT=1 TO HSIZE 4090 IF BLKSTR(BLK)+LEN(S$)>470 THEN 4140 4100 IF BLKSYM(BLK)>=&H25 THEN 4140 4110 BLKSTR(BLK)=BLKSTR(BLK)+3+(LEN(S$) OR 1) 4120 BLKSYM(BLK)=BLKSYM(BLK)+1 4130 RETURN 4140 REM This block is full, overflow to next 4150 BLKOVF(BLK)=BLKOVF(BLK)+1 4160 BLK=(BLK+H2INC) MOD HSIZE 4170 NEXT BCOUNT 4180 PRINT "Hash table is full!": STOP 4190 REM Initialize hash block 4200 FOR I=0 TO 3 4210 HBLK$(I)=STRING$(128,0) 4220 NEXT I 4230 STRPOS=&H26 4240 RETURN 4250 REM Add symbol S$ to hash block 4260 GOSUB 5000 'Hash symbol S$ 4270 SPTR=H1START 'Initial try 4280 FOR I=1 TO &H25 4290 IF ASC(MID$(HBLK$(0),SPTR+1,1))=0 GOTO 4330 4300 SPTR=(SPTR+H1INC) MOD &H25 4310 NEXT I 4320 PRINT "Oops it dosn't fit! This is a bug!":STOP 4330 MID$(HBLK$(0),SPTR+1)=CHR$(STRPOS\2) 4340 S$=CHR$(LEN(S$))+S$+MKI$(SYMLOC(SYM)) 4350 MID$(HBLK$(STRPOS\128),(STRPOS MOD 128)+1)=S$ 4360 STRPOS=STRPOS+LEN(S$) 4370 IF STRPOS >511 THEN PRINT "Too many strings in the block!":STOP 4380 IF ((STRPOS-1) MOD 128)+1 < LEN(S$) THEN MID$(HBLK$(STRPOS\128),1)=RIGHT$(S$,STRPOS MOD 128) 4390 IF (STRPOS AND 1) = 1 THEN STRPOS=STRPOS+1 4400 RETURN 4410 REM Put hash block 4420 PRINT "... Block";BLK, BLKSYM(BLK);" Symbols, ";BLKSTR(BLK);" Bytes, "; BLKOVF(BLK);" Overflow." 4430 IF BLKOVF(BLK)>0 THEN MID$(HBLK$(0),&H25+1)=CHR$(&HFF) ELSE MID$(HBLK$(0),&H25+1)=CHR$(STRPOS\2) 4440 FOR I=0 TO 3 4450 LSET LBUF$=HBLK$(I) 4460 GOSUB 1130 4470 NEXT I 4480 RETURN 4490 REM Initialize symbol table 4500 LASTSYM=0 'Last symbol added to table 4510 STRSIZE=0 'Total bytes in symbols 4520 RETURN 4530 REM Add symbol S$ to symbol table 4540 LASTSYM=LASTSYM+1 4550 IF LASTSYM>MAXSYM THEN PRINT "Too many symbols":STOP 4560 SYMB$(LASTSYM)=S$ 4570 STRSIZE=STRSIZE+LEN(S$) 4580 SYMBLOCK(LASTSYM)=-1 4590 SYMLOC(LASTSYM)=OBJLOC 4600 RETURN 5000 REM Compute hash numbers 5010 RH=0: RL=0: LH=0: LL=0: 5020 FOR I=LEN(S$) TO 1 STEP -1 5030 GOSUB 5200: GOSUB 5250 5040 C=ASC(MID$(S$,I)) OR &H20 5050 RL=RL XOR C 5060 LL=LL XOR C 5070 NEXT I 5080 H1START=FNZ(RH,RL): H2INC=FNR(LH,LL) 5090 RH=0: RL=LEN(S$) OR &H20: LH=0: LL=RL: 5100 FOR I=1 TO LEN(S$)-1 5110 GOSUB 5200: GOSUB 5250 5120 C=ASC(MID$(S$,I)) OR &H20 5130 RL=RL XOR C 5140 LL=LL XOR C 5150 NEXT I 5160 H1INC=FNZ(RH,RL): H2START=FNR(LH,LL) 5170 IF H1INC=0 THEN H1INC=1 5180 IF H2INC=0 THEN H2INC=1 5190 RETURN 5200 REM rotate rh,rl right by 2 bits 5210 C = RL 5220 RL = ((RL\4) OR (RH*64)) AND 255 5230 RH = ((RH\4) OR (C*64)) AND 255 5240 RETURN 5250 REM rotate lh,ll left by 2 bits 5260 C = LH 5270 LH = ((LH*4) OR (LL\64)) AND 255 5280 LL = ((LL*4) OR (C\64)) AND 255 5290 RETURN 6000 REM Compute size of hash table 6010 HSIZE=(STRSIZE+LASTSYM*5)\380 + 1 6020 I=LASTSYM/30: IF I>HSIZE THEN HSIZE=I 6030 IF HSIZE<=3 THEN RETURN 6040 HSIZE=HSIZE OR 1 6050 REM Raise HSIZE to nearest prime 6060 IF HSIZE>MAXBLK THEN STOP 'This is too big to handle! 6070 FOR I=3 TO SQR(HSIZE) STEP 2 6080 IF (HSIZE MOD I)=0 THEN HSIZE=HSIZE+2: GOTO 6050 'try next 6090 NEXT I 6100 RETURN 6110 REM Inquire for YES/NO answer 6120 INPUT " [Yes/No]";S$: I=ASC(S$) AND &HDF 6130 YES=(I=ASC("Y")): NO=(I=ASC("N")) 6140 RETURN 8000 REM Error processing 8010 ON ERROR GOTO 8000 8020 IF ERL<>1010 THEN GOTO 8060 8030 IF ERR=53 THEN RESUME 1050 'skip if file not found 8040 BEEP: PRINT: PRINT "Error opening '";LIBFILE$;"'.": PRINT: BEEP 8050 RESUME 1100 8060 IF ERL<>2010 THEN ON ERROR GOTO 0 8070 IF ERR=53 THEN S$="File '"+OBJFILE$+"' not found.": GOTO 8120 8080 IF ERR=64 THEN S$="Bad file name '"+OBJFILE$+"'.": GOTO 8120 8090 IF ERR=68 THEN S$="Device '"+OBJFILE$+"' is unavailable.": GOTO 8120 8100 IF ERR=71 THEN S$="Disk for '"+OBJFILE$+"' is not ready.": GOTO 8120 8110 S$="Error opening '"+OBJFILE$+"'." 8120 PRINT: PRINT S$: BEEP 8130 PRINT "File '";OBJFILE$;"' has not been added to '";LIBFILE$;"'." 8140 PRINT 8150 RESUME 250 10000 REM Program index 10010 GOTO 200 'Makelib main program 10020 ' 10030 GOSUB 1000 'Init lib file 10040 GOSUB 1130 'Dump library file buffer 10050 GOSUB 1170 'Allign to next block 10060 GOSUB 1210 'Close library file 10070 ' 10080 GOSUB 2000 'Init obj file 10090 GOSUB 2070 'Get byte CH$ 10100 GOSUB 2130 'get RTYPE and RSIZE 10110 GOSUB 2190 'Advance to next rec 10120 GOSUB 2250 'Close obj file 10130 GOSUB 2310 'Get word value WORD 10140 GOSUB 2370 'Get string S$ 10150 ' 10160 GOSUB 3000 'Process title record 10170 GOSUB 3080 'Process global record 10180 ' 10190 GOSUB 4000 'Init hash table 10200 GOSUB 4050 'assign symbol to block 10210 GOSUB 4190 'Initialize hash block 10220 GOSUB 4250 'Add symbol S$ to hash block 10230 GOSUB 4410 'Close hash block 10240 GOSUB 4490 'Initialize symbol table 10250 GOSUB 4530 'Add symbol S$ to symbol table 10260 ' 10270 GOSUB 5000 'Compute hash numbers 10280 GOSUB 5200 'rotate rh,rl right by 2 bits 10290 GOSUB 5250 'rotate lh,ll left by 2 bits 10300 GOSUB 6000 'Compute size of hash table 10310 REM