$title ('Help Utility Version 1.1') help: do; /* [JCE] Cut-down version of help that only does [C]reate */ /* Copyright (C) 1982 Digital Research P.O. 579 Pacific Grove, CA 93950 Revised: 06 Dec 82 by Bruce Skidmore */ declare plm label public; /********************************************** Interface Procedures **********************************************/ mon1: procedure (func,info) external; declare func byte; declare info address; end mon1; mon2: procedure (func,info) byte external; declare func byte; declare info address; end mon2; mon3: procedure (func,info) address external; declare func byte; declare info address; end mon3; /********************************************** Global Variables **********************************************/ declare (list$mode,nopage$mode,create$mode,extract$mode,page$mode) byte; declare (offset,eod) byte; declare cmdrv (1) byte external; /* [JCE] Help patch 2 */ declare fcb (13) byte external; declare fcb2 (36) byte; declare maxb address external; declare fcb16 (1) byte external; declare tbuff (128) byte external; declare control$z literally '1AH'; declare cr literally '0DH'; declare lf literally '0AH'; declare tab literally '09H'; declare slash literally '''/'''; declare true literally '0FFH'; declare false literally '00H'; declare (cnt,index) byte; declare sub(12) byte; declare com(11) structure( name(15) byte); declare sysbuff(8) structure( subject(12) byte, record address, rec$offset byte, level byte) at (.memory); declare name(12) byte; declare level byte; declare gindex address; declare tcnt byte; declare version address; /************************************** * * * B D O S Externals * * * **************************************/ read$console: procedure byte; return mon2 (1,0); end read$console; write$console: procedure (char); declare char byte; call mon1 (2,char); end write$console; print$console$buf: procedure (buff$adr); declare buff$adr address; call mon1 (9,buff$adr); end print$console$buf; read$console$buff: procedure (buff$adr); declare buff$adr address; call mon1(10,buff$adr); end read$console$buff; direct$con$io: procedure(func) byte; declare func byte; return mon2(6,func); end direct$con$io; get$version: procedure address; return mon3(12,0); end get$version; delete$file: procedure (fcb$address); declare fcb$address address; call mon1(19,fcb$address); end delete$file; open$file: procedure (fcb$address) byte; declare fcb$address address; declare fcb based fcb$address (1) byte; fcb(12) = 0; /* EX = 0 */ fcb(32) = 0; /* CR = 0 */ return mon2 (15,fcb$address); end open$file; close$file: procedure (fcb$address) byte; declare fcb$address address; return mon2 (16,fcb$address); end close$file; read$record: procedure (fcb$address) byte; declare fcb$address address; return mon2 (20,fcb$address); end read$record; write$record: procedure (fcb$address) byte; declare fcb$address address; return mon2(21,fcb$address); end write$record; make$file: procedure (fcb$address) byte; declare fcb$address address; declare fcb based fcb$address (1) byte; fcb(12) = 0; /* EX = 0 */ fcb(32) = 0; /* CR = 0 */ return mon2(22,fcb$address); end make$file; read$rand: procedure (fcb$address) byte; declare fcb$address address; return mon2(33,fcb$address); end read$rand; set$dma: procedure (dma$address); declare dma$address address; call mon1(26,dma$address); end set$dma; set$rand$rec: procedure (fcb$address); declare fcb$address address; call mon1(36,fcb$address); end set$rand$rec; terminate: procedure; call mon1 (0,0); end terminate; /********************************************* Error Procedure Displays error messages and terminates if required. *********************************************/ error: procedure(term$code,err$msg$adr); declare term$code byte; declare err$msg$adr address; call print$console$buf(.(cr,lf,'ERROR: $')); call print$console$buf(err$msg$adr); call print$console$buf(.(cr,lf,'$')); if term$code then call terminate; end error; /********************************************* Move Procedure Moves specified number of bytes from the Source address to the Destination address. *********************************************/ movef: procedure (mvcnt,source$addr,dest$addr); declare (source$addr,dest$addr) address; declare mvcnt byte; call move(mvcnt,source$addr,dest$addr); return; end movef; /********************************************* Compare Function Compares 12 byte strings Results: 0 - string1 = string2 1 - string1 < string2 2 - string1 > string2 *********************************************/ compare: procedure(str1$addr,str2$addr) byte; declare (str1$addr,str2$addr) address; declare string1 based str1$addr (12) byte; declare string2 based str2$addr (12) byte; declare (result,i) byte; result, i = 0; do while ((i < 12) and (string1(i) <> ' ')); if string1(i) <> string2(i) then do; if string1(i) < string2(i) then do; result = 1; end; else do; result = 2; end; i = 11; end; i = i + 1; end; return result; end compare; /********************************************* Increment Procedure Increments through a record. *********************************************/ inc: procedure (inci) byte; declare inci byte; inci = inci + 1; if inci > 127 then do; if read$record(.fcb) = 0 then do; inci = 0; end; else do; eod = true; inci = 0; end; end; return inci; end inc; /******************************************* Init Procedure Reads the index into memory *******************************************/ init: procedure; declare (buf$size,max$buf,init$i) address; declare end$index byte; buf$size = maxb - .memory; max$buf = buf$size; end$index = 0; init$i = 7; do while (not end$index) and (max$buf > 127); call set$dma(.sysbuff(init$i-7).subject); if read$record(.fcb) <> 0 then do; init$i = close$file(.fcb); call error(true,.('Reading HELP.HLP index.$')); end; if sysbuff(init$i).subject(0) = '$' then end$index = true; if not end$index then do; max$buf = max$buf - 128; init$i = init$i + 8; end; end; call set$dma(.tbuff); if (max$buf < 128) and (not end$index) then do; init$i = close$file(.fcb); call error(true,.('Too many entries in Index Table.', ' Not enough memory.$')); end; end init; /******************************************* Parse Procedure Parses the command tail *******************************************/ parse: procedure byte; declare (index,begin,cnt,i,stop,bracket) byte; index = 0; if tbuff(0) <> 0 then do; do index = 1 to tbuff(0); if tbuff(index) = tab then tbuff(index) = ' '; else if tbuff(index) = ',' then tbuff(index) = ' '; end; index = 1; do while(index < tbuff(0)) and (tbuff(index) = ' '); index = index + 1; end; if tbuff(index) = '.' then do; begin = level; tbuff(index) = ' '; end; else begin = 0; do index = begin to 10; call movef(15,.(' ',cr,'$'),.com(index).name); end; index = begin; cnt = 1; stop, bracket = 0; do while (tbuff(cnt) <> 0) and (not stop); if (tbuff(cnt) <> 20H) then do; i = 0; do while (((tbuff(cnt) <> 20H) and (tbuff(cnt) <> '[')) and (tbuff(cnt) <> 0)) and ((i < 12) and (index < 11)); if (tbuff(cnt) > 60H) and (tbuff(cnt) < 7BH) then do; com(index).name(i) = tbuff(cnt) - 20H; end; else do; com(index).name(i) = tbuff(cnt); end; cnt = cnt + 1; i = i + 1; end; index = index + 1; if (bracket or (index > 10)) then do; stop = true; end; else if tbuff(cnt) = '[' then do; if com(index-1).name(0) = ' ' then index = index - 1; com(index).name(0) = '['; cnt = cnt + 1; index = index + 1; bracket = true; end; end; else do; cnt = cnt + 1; end; end; end; list$mode, nopage$mode, create$mode, extract$mode = false; if index > 0 then do; i = 0; do while (i < 10); if com(i).name(0) = '[' then do; if (com(i+1).name(0) = 'C') then do; create$mode = true; index = index - 2; end; else if (com(i+1).name(0) = 'E') then do; extract$mode = true; index = index - 2; end; else if (com(i+1).name(0) = 'N') then do; nopage$mode =true; index = index - 2; end; else if (com(i+1).name(0) = 'L') then do; list$mode = true; nopage$mode = true; index = index - 2; end; else if (com(i+1).name(0) <> ' ') then do; index = index - 2; end; else do; index = index - 1; end; i = 10; end; i = i + 1; end; end; return index; end parse; /****************************************** Create$index Procedure Creates HELP.HLP from HELP.DAT ******************************************/ create$index: procedure; declare (cnt, i, rec$cnt) byte; declare (index,count,count2,max$buf,save$size) address; declare fcb3(36) byte; call print$console$buf(.(cr,lf,'Creating HELP.HLP....$')); do i = 0 to 7; call movef(12,.('$ '),.sysbuff(i).subject); end; rec$cnt, index = 0; save$size = maxb - .memory; max$buf = save$size; call movef(13,.(0,'HELP DAT',0),.fcb); if open$file(.fcb) = 0FFH then do; call error(true,.('HELP.DAT not on current drive.$')); end; eod = 0; do while (not eod) and (read$record(.fcb) = 0); i = 0; do while(i < 128) and (not eod); if tbuff(i) = control$z then do; eod = true; end; else do; if tbuff(i) = slash then do; cnt = 0; do while(not eod) and (tbuff(i) = slash); i = inc(i); cnt = cnt + 1; end; if (cnt = 3) and (not eod) then do; sysbuff(index).level = tbuff(i) - '0'; i = inc(i); cnt = 0; do while ((cnt < 12) and (not eod)) and (tbuff(i) <> cr); if (tbuff(i) > 60H) and (tbuff(i) < 7BH) then do; sysbuff(index).subject(cnt) = tbuff(i) - 20H; end; else do; sysbuff(index).subject(cnt) = tbuff(i); end; i = inc(i); cnt = cnt + 1; end; if (not eod) then do; call set$rand$rec(.fcb); call movef(1,.fcb(33),.sysbuff(index).record); call movef(1,.fcb(34),.sysbuff(index).record+1); sysbuff(index).record = sysbuff(index).record - 0001H; sysbuff(index).rec$offset = i; index = index + 1; if ((index mod 8) = 0) then do; rec$cnt = rec$cnt + 1; max$buf = max$buf - 128; if (max$buf < 128) and (not eod) then do; cnt = close$file(.fcb); call error(true, .('Too many entries in Index Table.', ' Not enough memory.$')); end; else do count = index to index + 7; call movef(12,.('$ '), .sysbuff(count).subject); end; end; end; end; end; else do; i = inc(i); end; end; end; end; call set$dma(.sysbuff); rec$cnt = rec$cnt + 1; /******************************** create HELP.HLP ********************************/ call movef(13,.(0,'HELP HLP',0),.fcb3); call delete$file(.fcb3); if make$file(.fcb3) = 0FFH then do; cnt = close$file(.fcb2); call delete$file(.fcb2); cnt = close$file(.fcb); call error(true,.('Unable to Make HELP.HLP.$')); end; call movef(4,.(0,0,0,0),.fcb2+32); cnt = read$rand(.fcb2); do count = 0 to index - 1; sysbuff(count).record = sysbuff(count).record + rec$cnt; end; do count = 0 to rec$cnt - 1; call set$dma(.memory(shl(count,7))); if write$record(.fcb3) = 0FFH then do; cnt = close$file(.fcb3); call delete$file(.fcb3); cnt = close$file(.fcb2); call delete$file(.fcb2); cnt = close$file(.fcb); call error(true,.('Writing file HELP.HLP.$')); end; end; call movef(4,.(0,0,0,0),.fcb+32); cnt = read$rand(.fcb); eod = 0; do while (not eod); count = 0; max$buf = save$size; do while (not eod) and (max$buf > 127); call set$dma(.memory(shl(count,7))); if read$record(.fcb) <> 0 then do; eod = true; end; else do; max$buf = max$buf - 128; count = count + 1; end; end; do count2 = 0 to count-1; call set$dma(.memory(shl(count2,7))); if write$record(.fcb3) = 0FFH then do; i = close$file(.fcb3); call delete$file(.fcb3); i = close$file(.fcb); call error(true,.('Writing file HELP.HLP.$')); end; end; end; if close$file(.fcb) = 0FFH then do; cnt = close$file(.fcb3); call error(true,.('Closing file HELP.DAT.$')); end; if close$file(.fcb3) = 0FFH then do; call error(true,.(false,'Closing file HELP.HLP.$')); end; call print$console$buf(.('HELP.HLP created',cr,lf,'$')); end create$index; /******************************************** Extract$file Procedure Creates HELP.DAT from HELP.HLP ********************************************/ extract$file: procedure; declare (end$index,i) byte; declare (count,count2,max$buf,save$size) address; call print$console$buf(.(cr,lf,'Extracting data....$')); call movef(13,.(0,'HELP HLP',0),.fcb); if open$file(.fcb) = 0FFH then do; call error(true,.('Unable to find file HELP.HLP.$')); end; call movef(13,.(0,'HELP DAT',0),.fcb2); call delete$file(.fcb2); if make$file(.fcb2) = 0FFH then do; i = close$file(.fcb); call error(true,.('Unable to Make HELP.DAT.$')); end; call set$dma(.sysbuff); end$index = 0; do while ((i := read$record(.fcb)) = 0) and (not end$index); if sysbuff(7).subject(0) = '$' then end$index = true; end; eod = 0; if i <> 0 then eod = true; i = write$record(.fcb2); save$size = maxb - .memory; do while (not eod); count = 0; max$buf = save$size; do while (not eod) and (max$buf > 127); call set$dma(.memory(shl(count,7))); if read$record(.fcb) <> 0 then do; eod = true; end; else do; max$buf = max$buf - 128; count = count + 1; end; end; do count2 = 0 to count-1; call set$dma(.memory(shl(count2,7))); if write$record(.fcb2) = 0FFH then do; i = close$file(.fcb2); call delete$file(.fcb2); i = close$file(.fcb); call error(true,.('Writing file HELP.DAT.$')); end; end; end; if close$file(.fcb) = 0FFH then do; call error(false,.('Unable to Close HELP.HLP.$')); end; if close$file(.fcb2) = 0FFH then do; call delete$file(.fcb2); call error(true,.('Unable to Close HELP.DAT.$')); end; call print$console$buf(.('Extraction complete',cr,lf,lf, 'HELP.DAT created',cr,lf,'$')); end extract$file; /********************************************* Search$file Procedure Searches the index table for the key *********************************************/ search$file: procedure byte; declare (eod, error, cnt, found, saved, save$level) byte; declare index address; eod, error, found, saved, index = 0; do while(not eod) and (not error); if sysbuff(index).subject(0) <> '$' then do; if sysbuff(index).level = level + 1 then do; cnt = compare(.com(level).name,.sysbuff(index).subject); if cnt = 0 then do; call movef(12,.sysbuff(index).subject,.com(level).name); level = level + 1; if (not saved) then do; save$level = level; saved = true; end; if ((level > 8) or (com(level).name(0) = ' ')) or (com(level).name(0) = '[') then do; found = true; eod = true; end; else do; index = index + 1; found = 0; end; end; else do; index = index + 1; end; end; else do; if saved then do; if save$level < sysbuff(index).level then do; index = index + 1; end; else do; error = true; end; end; else do; index = index + 1; end; end; end; else do; error = true; end; end; if found then do; gindex = index + 1; call movef(1,.sysbuff(index).record,.fcb(33)); call movef(1,.sysbuff(index).record+1,.fcb(34)); fcb(35) = 0; offset = sysbuff(index).rec$offset; level = sysbuff(index).level; end; return error; end search$file; /************************************** Main Program **************************************/ declare last$dseg$byte byte initial (0); plm: do; eod, tcnt = 0; version = get$version; if (high(version) = 1) or (low(version) < 30h) then do; call error(true,.('Requires CP/M Version 3$')); end; cnt = parse; if create$mode then do; call create$index; end; else if extract$mode then do; call extract$file; end; end; call terminate; end help;