PARM info='' entry=main ANYPARM parms=null comment This command file translates the SPOOK command set to the NM Spooler. comment Written by Jeff Vance (CSY) February 1990. if "!entry" = "text_file" then comment { Causes the dfid in "parms" to become texted. } comment {Input: parms, a dfid terminated by chr(0) } comment {Output: _spook_text, fully qualified Oxxx.OUT.HPSPOOL file } comment { _spook_textid, just the Oxxx part of _spook_text } comment { _spook_text_cctl, TRUE if _spook_text is a cctl file } comment { _spook_next_rec, intialized to 1, first record in file } comment { _spook_text_eof, set to eof of _spook_text } comment { hpcierr, set to 52 if _spook_text not found } comment setvar _spook_textid "!parms"-chr(0)-"#" if numeric(lft(_spook_textid,1)) then setvar _spook_textid "O" + _spook_textid endif setvar _spook_text _spook_textid + ".OUT.HPSPOOL" if finfo(_spook_text,"exists") then comment {Initialze starting and ending record numbers} setvar _spook_next_rec 1 setvar _spook_text_eof finfo(_spook_text,"eof") setvar _spook_text_cctl & pos('NOCCTL',finfo(_spook_text,"fmtfopt")) = 0 else comment {Dfid does not exist} echo Non-existent device file (!_spook_text). setvar HPCIERR 52 comment {Cleanup "text" variables.} deletevar _spook_text@ endif return elseif "!entry" = "default_spoolfiles" then comment { Reads output file, created by :listspf, and automatically } comment { texts one of the user's spoolfiles. The user is given an } comment { indexed choice when > 1 spoolid is found. } comment {Input: none } comment {Output: _spook_text@, if spoolfile selected (auto text occurs) } comment { hpcierr, 1 if illegal input, -1 if no spoolid is } comment { selected. } comment {Assumptions: 1) input redirected to the output of a successful } comment {:listspf, 2) since there is no error/warn there will be 1 or more} comment {valid spoolfile ids in the file, 3) listspf does not } comment {show input spoolfiles. } comment comment {Skip header records} input _spook_rec input _spook_rec input _spook_rec comment {Build _spook_spoolid array of all spoolids in file} comment {(empty record indicates end of spoolid output) } setvar _spook_i 0 while len(setvar(_spook_spoolid_![setvar(_spook_i,_spook_i+1)], & lft(input(),7))) > 0 do endwhile comment {Correct for empty record after last spoolid} setvar _spook_i _spook_i - 1 comment {If more than 1 spoolid prompt for desired spoolid by index} if _spook_i > 1 then echo SPOOLID choices for !_spook_owner: setvar _spook_pos _spook_i setvar _spook_i 0 comment {Echo list of spoolids} while setvar(_spook_i,_spook_i+1) <= _spook_pos do echo !_spook_i) !"_spook_spoolid_!_spook_i" endwhile setvar _spook_i _spook_i - 1 comment {Prompt user for spoolid choice, but remember input has } comment {been redirected to SPOOK000, so use file eq to terminal} file spkterm;dev=!hpldevin continue input _spook_i, 'Enter an index from 1..!_spook_pos or // to stop & (def=!_spook_i)> ' <*spkterm reset spkterm if '!_spook_i' = '//' then setvar HPCIERR -1 return endif if typeof(!_spook_i) <> 1 then comment {Non-integer input} setvar _spook_i 0 endif comment {Convert string input to integer and range check} if setvar(_spook_i,!_spook_i) <= 0 or _spook_i > _spook_pos then echo Invalid index. Expected a number in the range of 1..!_spook_pos setvar HPCIERR 1 return endif endif comment {Cause the selected spoolid to be texted} xeq spook entry="text_file" parms=![rtrim(_spook_spoolid_!_spook_i)+chr(0)] if HPCIERR = 0 and _spook_loud then echo Implict TEXT of !_spook_text endif deletevar _spook_spoolid_#@ return elseif "!entry" = "get_dfid_or_username" then comment { Parses list of dfid's and/or user[.acct]'s. Syntax: } comment { spspec [,spspec [,spspec]] } comment { spspec ::= spid [-spid [-spid]] ... } comment { spid ::= dfid | user[.acct] | * | ~ } comment { Unqualified usernames are qualified when the SET owner=name } comment { is different from the logon user.acct. } comment {Input: parms, contains difd/s or user.acct } comment { _spook_parms, everything right of command name } comment {Output: _spook_dfid, list of dfid/s, or "@" if user.acct used } comment { _spook_opts, seleq for owner= and/or spoolid= } comment { _spook_parms, _spook_parms without dfids or usernames } comment { hpcierr, set to 1 if invalid syntax } comment if "!parms" = "null" then comment {No dfid or user.acct specified} setvar _spook_opts ";SELEQ=[OWNER=!_spook_owner]" setvar _spook_dfid "@" return endif if pos('-',ltrim("!parms")) = 1 then echo Cannot begin a spool spec with a "-", see HELP. setvar HPCIERR 1 return endif comment {Append a comma to make parsing easier} setvar _spook_rec "!parms," comment {Change '*' to currently texted dfid} if setvar(_spook_pos,pos('*',_spook_rec)) > 0 then if bound(_spook_text) then setvar _spook_rec lft(_spook_rec,_spook_pos-1)+"#!_spook_textid"+& rht(_spook_rec,len(_spook_rec)-_spook_pos) else echo No spoolfile is currently TEXTed. setvar HPCIERR 2 return endif endif comment {Parse list of dfid's and/or user[.acct]'s} while setvar(_spook_pos,pos(',',_spook_rec)) > 0 do setvar _spook_except '' setvar _spook_spid ltrim(lft(_spook_rec,_spook_pos-1)) setvar _spook_rec rht(_spook_rec,len(_spook_rec)-_spook_pos) comment {Look for exception spec ("-spid")} if setvar(_spook_pos,pos('-',_spook_spid)) > 0 then comment {Create spid exception list} setvar _spook_except rht(_spook_spid,len(_spook_spid)-_spook_pos+1) setvar _spook_spid lft(_spook_spid,_spook_pos-1) endif if numeric(lft(_spook_spid,1)) or lft(_spook_spid,1) = "#" then comment {dfid} if len(_spook_opts) > 0 then setvar _spook_opts _spook_opts + "(SPOOLID=!_spook_spid" else setvar _spook_dfid _spook_dfid + "!_spook_spid," endif else comment {user[.acct]} if pos('.',_spook_spid) = 0 and & _spook_owner <> "!HPUSER.!HPACCOUNT" then comment {Qualify user names with acct name from _spook_owner} setvar _spook_spid _spook_spid + & rht(_spook_owner,len(_spook_owner)-pos('.',_spook_owner)+1) endif setvar _spook_opts _spook_opts + "(OWNER=!_spook_spid" endif if len(_spook_except) > 0 then while setvar(_spook_pos,pos("-",_spook_except,-1)) > 0 do comment {Reverse move exceptions to _spook_opts as part of seleq} setvar _spook_spid ltrim(rht(_spook_except,len(_spook_except)- & _spook_pos)) setvar _spook_except lft(_spook_except,_spook_pos-1) if numeric(lft(_spook_spid,1)) or lft(_spook_spid,1) = "#" then comment {dfid exception} setvar _spook_opts _spook_opts + " AND SPOOLID<>!_spook_spid" else comment {user[.acct] exception} if pos('.',_spook_spid) = 0 and & _spook_owner <> "!HPUSER.!HPACCOUNT" then comment {Qualify user names with acct name from _spook_owner} setvar _spook_spid _spook_spid + & rht(_spook_owner,len(_spook_owner)-pos('.',_spook_owner)+1) endif setvar _spook_opts _spook_opts + " AND OWNER<>!_spook_spid" endif endwhile endif if len(_spook_opts) > 0 then comment {Finish this spspec by appending ')' and 'or' for next spspec} setvar _spook_opts _spook_opts + ") OR " endif endwhile comment {Fix up _spook_dfid and _spook_opts (ends in ') or ')} if len(_spook_opts) > 0 then if len(_spook_dfid) > 0 then comment {Move dfids (ends in ',') to _spook_opts as part of seleq} while setvar(_spook_pos,pos(',',_spook_dfid)) > 0 do setvar _spook_opts _spook_opts + & "(SPOOLID=" + lft(_spook_dfid,_spook_pos-1) + ") OR " setvar _spook_dfid rht(_spook_dfid,len(_spook_dfid)-_spook_pos) endwhile endif setvar _spook_opts ";SELEQ=["+lft(_spook_opts,len(_spook_opts)-4)+"]" setvar _spook_dfid '@' elseif len(_spook_dfid) > 0 then setvar _spook_dfid "("+lft(_spook_dfid,len(_spook_dfid)-1)+")" endif comment {Return _spook_parms without dfid(s) or user.acct name(s)} setvar _spook_parms ltrim(_spook_parms-"!parms") return elseif "!entry" = "do_alt_purge_show" then comment { Parses the spool id selections for the alt,purge,show commands.} comment { This includes a list of dfids and/or user names and/or one of } comment { a date or daysold specification. Pri,copies,dev will be added. } comment {Input: parms, command name: 1=ALTER, 2=PURGE, 3=SHOW. } comment { _spook_parms, command line terminated with chr(0). } comment {Output: _spook_opts, seleq containing owner and date spec } comment { _spook_dfid, list of dfids or @ if any user names used } comment { _spook_parms, command line minus the spool id } comment { hpcierr, set if an error occurs } comment if len(_spook_parms) = 1 and !parms <> 3 then comment ALT and PURGE require a dfid or user name.} echo Expected a "user[.acct]" or "dfid" parameter. setvar HPCIERR 1 return endif if lft(_spook_parms,1) = "~" then comment {Use previous selection.} if not bound(_spook_tilda_dfid) then echo No previous selection has been made. setvar HPCIERR 2 else setvar _spook_dfid _spook_tilda_dfid setvar _spook_opts _spook_tilda_opts setvar _spook_parms ltrim(_spook_parms - "~") endif return endif comment {First parse the dfid[s] or user[.acct] name} if setvar(_spook_pos,pos(';',_spook_parms)) = 0 then setvar _spook_pos len(_spook_parms) endif xeq spook entry="get_dfid_or_username" parms=& ![lft(_spook_parms,_spook_pos-1)] if HPCIERR = 0 then comment {Check for datespec} if setvar(_spook_pos,pos('DAYSOLD',_spook_parms)) > 0 then xeq spook entry="do_daysold" parms=!_spook_pos elseif setvar(_spook_pos,pos('DATE',_spook_parms)) > 0 then xeq spook entry="do_date" parms=!_spook_pos endif if HPCIERR = 0 then comment {Save spook_dfid and spook_opts for later "~" use.} setvar _spook_tilda_dfid _spook_dfid setvar _spook_tilda_opts _spook_opts endif endif return elseif "!entry" = "do_daysold" then comment { Parses the "daysold" parameter, appends it to _spook_opts as } comment { part of the seleq. Number of days cannot exceed 30. Syntax: } comment { ;daysold <,<=,=,>,>= # of days } comment {Input: parms, indexes the 1st "d" in "daysold" } comment { _spook_parms, the command line (less a spspec, if any) } comment {Output: _spook_opts, seleq containing date spec } comment { _spook_parms, command line minus daysold spec } comment { hpcierr, set if an error occurs } comment comment {Left-justify "daysold"} setvar _spook_rec rht(_spook_parms,len(_spook_parms)-!parms+1) if setvar(_spook_pos,pos(';',_spook_rec)) = 0 then setvar _spook_pos len(_spook_rec) endif setvar _spook_rec lft(_spook_rec,_spook_pos-1) comment {Return _spook_parms without daysold} setvar _spook_parms _spook_parms - _spook_rec - ';' comment {Remove the "daysold" keyword} setvar _spook_rec ltrim(rht(_spook_rec,len(_spook_rec)-7)) comment {Save the relational operator and inverse it's meaning} comment {note: ord('<')=60, ord('=')=61, ord('>')=62} setvar _spook_relop chr(62 -((ord(lft(_spook_rec,1))+2) mod 62)) comment {Convert num-of-days expression to an integer} if pos('=',_spook_rec) = 2 then setvar _spook_relop _spook_relop + "=" setvar _spook_num ![rht(_spook_rec,len(_spook_rec)-2)] else setvar _spook_num ![rht(_spook_rec,len(_spook_rec)-1)] endif if typeof(_spook_num) <> 1 then echo Invalid number-of-daysold expression. setvar HPCIERR 1 return endif if _spook_num < 0 or _spook_num > 30 then echo Number-of-daysold must be >= 0 and <= 30. setvar HPCIERR 2 return endif comment {Compute seleq date from daysold and current date} setvar _spook_mm hpmonth setvar _spook_yyyy 1900+hpyear setvar _spook_dd hpdate-_spook_num if _spook_dd <= 0 then setvar _spook_mm _spook_mm-1 if _spook_mm = 0 then setvar _spook_mm 12 setvar _spook_yyyy _spook_yyyy-1 endif setvar _spook_dd 30+_spook_dd endif comment {Put date in seleq} if len(_spook_opts) = 0 then setvar _spook_opts ";SELEQ=[" else comment {Parenthesis seleq so date can be appended} setvar _spook_opts ";SELEQ=[("+str(_spook_opts,9,len(_spook_opts)-9)+& ") AND " endif setvar _spook_opts _spook_opts + & "DATE!_spook_relop!_spook_mm/!_spook_dd/!_spook_yyyy]" return elseif "!entry" = "do_date" then comment { Parses the "date" parameter, appends it to _spook_opts as } comment { part of the seleq. Date is in mm/dd/yy[yy] format. Syntax: } comment { ;date <,<=,=,>,>= mm/dd/yy } comment {Input: parms, indexes the "d" in "date" } comment { _spook_parms, the command line (less a spspec, if any) } comment {Output: _spook_opts, seleq containing date spec } comment { _spook_parms, command line minus date spec } comment comment {Left-justify "date"} setvar _spook_rec rht(_spook_parms,len(_spook_parms)-!parms+1) if setvar(_spook_pos,pos(';',_spook_rec)) = 0 then setvar _spook_pos len(_spook_rec) endif setvar _spook_rec lft(_spook_rec,_spook_pos-1) comment {Return _spook_parms without date} setvar _spook_parms _spook_parms - _spook_rec - ';' comment {Add year if left off} if pos('/',_spook_rec) = pos('/',_spook_rec,-1) then setvar _spook_rec _spook_rec + "/!hpyear" endif comment {Put date in seleq} if len(_spook_opts) = 0 then setvar _spook_opts ";SELEQ=[" else comment {Parenthesis seleq so date can be appended} setvar _spook_opts ";SELEQ=[("+str(_spook_opts,9,len(_spook_opts)-9)+& ") AND " endif setvar _spook_opts _spook_opts + _spook_rec + "]" return elseif "!entry" = "get_range" then comment { Parses a range into starting and ending record numbers. } comment { Handles #[/#],"*",+,-,FIRST,LAST. } comment {Input: parms, contains range } comment { _spook_next_rec, record number for current text file } comment {Output: _spook_start, integer starting record number for :print } comment { _spook_end, integer ending record number for :print } comment { hpcierr, set to 1 if a range error occurs } comment if "!parms" = "null" then comment {No range specified, use default range of current line} setvar _spook_start setvar(_spook_end,_spook_next_rec) return elseif "!parms" = "ALL" then setvar _spook_start 1 setvar _spook_end _spook_text_eof return else comment {Parse start [/end] specification} if setvar(_spook_pos,pos('/',"!parms")) > 0 then setvar _spook_start lft("!parms",_spook_pos-1) setvar _spook_end str("!parms",_spook_pos+1,& len("!parms")-_spook_pos) else setvar _spook_start "!parms" setvar _spook_end _spook_start endif comment {Compute the actual start and end (account for "LAST", "*", etc)} setvar _spook_i 0 setvar _spook_num _spook_start while _spook_i <= 1 do comment {Loop twice} if setvar(_spook_pos,pos('*',_spook_num)) > 0 then comment {Use current rec (minus 1 since it is really next rec)} setvar _spook_num lft(_spook_num,_spook_pos-1) + & "![_spook_next_rec-1]" + & rht(_spook_num,len(_spook_num)-_spook_pos) endif comment {Handle FIRST and LAST} if setvar(_spook_pos,pos('FIRST',_spook_num)) > 0 then setvar _spook_num lft(_spook_num,_spook_pos-1) + "1" +& rht(_spook_num,len(_spook_num)-_spook_pos-4) endif if setvar(_spook_pos,pos('LAST',_spook_num)) > 0 then setvar _spook_num lft(_spook_num,_spook_pos-1)+"!_spook_text_eof"+& rht(_spook_num,len(_spook_num)-_spook_pos-3) endif comment {Verify that final number/expression is an integer} if typeof(!_spook_num) <> 1 then echo Invalid range. Expected a number, ALL, FIRST, LAST or *. setvar HPCIERR 1 return endif comment {Do arithmetic and convert to an integer} if _spook_i = 0 then setvar _spook_start !_spook_num setvar _spook_num _spook_end setvar _spook_i 1 else setvar _spook_end !_spook_num setvar _spook_i 2 endif endwhile comment {Force start and end to be within file} if _spook_start > _spook_text_eof then setvar _spook_start _spook_text_eof endif if _spook_end > _spook_text_eof then setvar _spook_end _spook_text_eof endif endif return elseif "!entry" = "get_redo_cmd" then comment { Returns the command number of the command in the redo stack } comment { that matches 'parms'. Note: the DO/REDO cmd is still in the } comment { redo stack at this point and _spook_cmdnum indexes the } comment { DO/REDO command. } comment {Input: parms, an absolute (pos. #) or relative (neg. #) } comment { into redo stack, or a partial cmd string. } comment { Nul terminated, upshifted. } comment {Output: _spook_start, cmd number in redo stack } comment { hpcierr, non-zero if cmd not found in redo stack } comment if HPREDOSIZE <= 0 then echo HPREDOSIZE is 0 -- DO/REDO/LISTREDO are disabled. setvar HPCIERR 1 return endif if '!parms' = chr(0) then comment {-1 is default} setvar _spook_rec "-1" else setvar _spook_rec '!parms' - chr(0) endif if typeof(!_spook_rec) = 1 then comment {Integer number (pos or neg) into redo stack} setvar _spook_start !_spook_rec if _spook_start < 0 then setvar _spook_start _spook_cmdnum + _spook_start endif comment {Make sure _spook_start is defined in redo stack} if _spook_start < max(1,_spook_cmdnum-HPREDOSIZE) or & _spook_start >= _spook_cmdnum then echo Invalid numeric index (!_spook_rec) into redo stack. setvar HPCIERR 2 endif else comment {String cmd match into redo stack} setvar _spook_start _spook_cmdnum-1 setvar _spook_end max(1,_spook_cmdnum-HPREDOSIZE) while _spook_start >= _spook_end and & ups(lft(_spook_cmd!_spook_start,len(_spook_rec))) <> _spook_rec do setvar _spook_start _spook_start-1 endwhile if _spook_start < _spook_end then echo Command string "!_spook_rec" not found in redo stack. setvar HPCIERR 3 endif endif return elseif "!entry" = "find" then comment { Finds first occurence of "_spook_pattern" in the _spook_textid } comment { file. Input has been redirected from this file. } comment {Input: _spook_pattern, case sensitive string to match in file } comment { _spook_next_rec, current record number for _spook_textid } comment { _spook_any_match,TRUE if '@' used in find } comment { _spook_text_cctl,TRUE if dfid has CCTL byte in col 1 } comment {Output: _spook_next_rec, # of next record (or last) after match } comment { _spook_found, TRUE means pattern was found } comment setvar _spook_found FALSE while _spook_next_rec <= _spook_end and not (_spook_found) do comment {Read next record and strip 1st byte if CCTL file} if len(setvar(_spook_rec,input())) > 0 and _spook_text_cctl then setvar _spook_rec ltrim(rht(_spook_rec,len(_spook_rec)-1)) endif comment {Check if this record matches pattern} if setvar(_spook_pos,pos(_spook_pattern,_spook_rec)) > 0 and & (_spook_any_match or _spook_pos = 1) then comment {Match! Echo record with leading right-justified line number} echo ![rpt(" ",8-len("!_spook_next_rec"))]!_spook_next_rec) & ![rtrim(_spook_rec)] comment {Echo carets(^^) under matching word} echo ![rpt(" ",9+_spook_pos) + rpt("^",len(_spook_pattern))] comment {Stop while loop} setvar _spook_found TRUE endif setvar _spook_next_rec _spook_next_rec+1 endwhile if _spook_next_rec > _spook_text_eof then setvar _spook_next_rec _spook_text_eof endif return elseif "!entry" = "main" then comment {Main entry for SPOOK} echo echo SPOOK/iX Emulator Version 4.2 echo Enter '&dLhelp new&d@' to see the new features for this version. comment {Initialize user environment} setvar _spook_loud TRUE setvar _spook_redo_input FALSE setvar _spook_cmdnum 1 setvar _spook_prompt "spook(!![_spook_cmdnum]): " setvar _spook_owner "!HPUSER.!HPACCOUNT" setvar _spook_save_msgfence HPMSGFENCE setvar HPMSGFENCE 1 setvar _spook_looping TRUE comment {**** MAIN PROMPT / READ LOOP ****} while _spook_looping do setvar _spook_cmd "" comment {Check for info= string} if '!info' <> '' then setvar _spook_rec '!info'+chr(0) setvar _spook_looping FALSE elseif _spook_redo_input then comment {_spook_rec already contains the cmd from the redo stack} setvar _spook_redo_input FALSE echo !_spook_prompt!_spook_rec else comment {Prompt and read user input} setvar _spook_rec ltrim(rtrim(input("!_spook_prompt")))+chr(0) endif if len(_spook_rec) > 1 then comment {Push command on redo stack} if setvar(_spook_push_cmd,HPREDOSIZE > 0) then setvar _spook_cmd!_spook_cmdnum _spook_rec endif comment {Parse command name} setvar _spook_i 1 while alpha(str(_spook_rec,_spook_i,1)) do setvar _spook_i _spook_i+1 endwhile setvar _spook_cmd ups(lft(_spook_rec,_spook_i-1)) comment {Separate command parameters} setvar _spook_parms_raw ltrim(rht(_spook_rec,len(_spook_rec)-& _spook_i+1)) setvar _spook_parms ups(_spook_parms_raw) setvar _spook_dfid setvar(_spook_opts,'') errclear comment {Case _spook_cmd of...} comment ****** ALTER ****** if _spook_cmd = "A" or _spook_cmd = "ALT" or _spook_cmd = "ALTER" then comment {Convert to SPOOLF...;ALTER} xeq spook entry="do_alt_purge_show" parms=1 if HPCIERR = 0 then comment {Remove leading ';', parse for alter options} setvar _spook_parms ltrim(_spook_parms-';') while len(_spook_parms) > 1 do setvar _spook_i pos('=',_spook_parms) + 1 if setvar(_spook_pos,pos(',',_spook_parms)) = 0 then setvar _spook_pos len(_spook_parms) endif comment {Look for COPIES= ,DEV=, PRI= options} if lft(_spook_parms,1) = "C" then setvar _spook_opts _spook_opts + ";COPIES=" elseif lft(_spook_parms,1) = "D" then setvar _spook_opts _spook_opts + ";DEV=" elseif lft(_spook_parms,1) = "P" then setvar _spook_opts _spook_opts + ";PRI=" endif comment {Append value to above option} setvar _spook_opts _spook_opts + & str(_spook_parms,_spook_i,_spook_pos-_spook_i) comment {Remove this option from _spook_parms} setvar _spook_parms ltrim(rht(_spook_parms,& len(_spook_parms)-_spook_pos)) endwhile if _spook_loud then setvar _spook_opts _spook_opts + ';SHOW' echo spoolf !_spook_dfid !_spook_opts ;ALTER endif continue spoolf !_spook_dfid !_spook_opts ;ALTER endif comment ****** BROWSE ****** elseif _spook_cmd = "B" or _spook_cmd = "BROWSE" then comment {New SPOOK command: Syntax: browse [dfid]} comment {Invokes hpbrowse passing dfid or current text file} if not finfo("hpbrowse.pub.sys","exists") then echo HPBROWSE.PUB.SYS does not exist on this system. setvar HPCIERR 52 elseif len(_spook_parms) > 1 then if lft(_spook_parms,1) = "*" then if not bound(_spook_text) then setvar HPCIERR 1 endif else comment {Supplied the dfid} comment {Cause passed dfid to become the current text file} xeq spook entry="text_file" parms=!_spook_parms endif else comment {No spoolfile specified} comment {See if user has any spoolfiles to browse} continue listspf >spook000 if HPCIERR = 0 then xeq spook entry="default_spoolfiles" 0 then echo No text file, see TEXT command. else comment {Invoke hpbrowse passing the dfid file} continue xeq hpbrowse.pub.sys "!_spook_text" endif comment ****** DO ****** elseif _spook_cmd = "DO" then comment {New SPOOK command} xeq spook entry="get_redo_cmd" parms=!_spook_parms comment {Returns redo index in _spook_start} if HPCIERR = 0 then comment {move redo stack cmd to _spook_rec for execution} setvar _spook_rec _spook_cmd!_spook_start setvar _spook_redo_input TRUE endif comment {"pop" DO command from redo stack} setvar _spook_cmdnum max(1,_spook_cmdnum-1) setvar _spook_push_cmd FALSE comment ****** EDIT ****** elseif _spook_cmd = "EDIT" then comment {New SPOOK command: Syntax: edit [dfid]} comment {Invokes hpeditor passing dfid or current text file} if not bound(HPEDITOR) then if _spook_loud then echo HPEDITOR variable not defined, using 'HPEDIT.PUB.SYS' pause 2 endif setvar hpeditor 'HPEDIT.PUB.SYS' endif if len(_spook_parms) > 1 then if lft(_spook_parms,1) = "*" then if not bound(_spook_text) then setvar HPCIERR 1 endif else comment {Supplied the dfid} comment {Cause passed dfid to become the current text file} xeq spook entry="text_file" parms=!_spook_parms endif else comment {No spoolfile specified} comment {See if user has any spoolfiles to edit} continue listspf >spook000 if HPCIERR = 0 then xeq spook entry="default_spoolfiles" 0 then echo No text file, see TEXT command. else comment {Invoke the editor passing the dfid file} continue !hpeditor "!_spook_text" endif comment ****** EXIT / QUIT ****** elseif _spook_cmd = "E" or _spook_cmd = "Q" or & _spook_cmd = "EXIT" or _spook_cmd = "QUIT" then setvar _spook_looping FALSE comment ****** FIND ****** elseif _spook_cmd = "F" or _spook_cmd = "FIND" then if not bound(_spook_text) then echo No text file, see TEXT command. elseif len(_spook_parms) <= 4 and not bound(_spook_pattern) then comment {Handles: F, F", F"", F@" + chr(0)} echo No search pattern defined. else comment {Initialize range of text to be searched} setvar _spook_start _spook_next_rec setvar _spook_end _spook_text_eof if len(_spook_parms) > 4 then comment {Compute length of pattern} if setvar(_spook_i,pos('"',_spook_parms,-1)) - & setvar(_spook_pos,pos('"',_spook_parms)) <= 1 then if pos(',',_spook_parms) = 0 then comment {No range parameter therefore null pattern} echo Null pattern not allowed. setvar HPCIERR 1 endif else comment {Use "raw" buffer to handle lowercase patterns} setvar _spook_pattern str(_spook_parms_raw,_spook_pos+1,& _spook_i-_spook_pos-1) setvar _spook_any_match lft(_spook_parms,1) = "@" comment {Strip pattern from _spook_parms for range check} setvar _spook_parms ltrim(rht(_spook_parms,& len(_spook_parms)-_spook_i)) endif endif if HPCIERR = 0 and len(_spook_parms) > 2 and & lft(_spook_parms,1) = "," then comment {Range parameter specified} xeq spook entry="get_range" parms=![_spook_parms-","-chr(0)] setvar _spook_next_rec _spook_start endif if HPCIERR = 0 then if _spook_start > 1 then comment {Copy unsearched portion of dfid file to search} print !_spook_text;start=!_spook_start;end=!_spook_end;& page=0 >!_spook_textid file !_spook_textid,oldtemp else comment {Use .out.hpspool file directly} file !_spook_textid=!_spook_text,old endif comment {Invoke spook to find first occurence in local file} xeq spook entry="find" <*!_spook_textid reset !_spook_textid if _spook_start > 1 then purge !_spook_textid,temp endif if not _spook_found and _spook_loud then echo "!_spook_pattern" not found. endif endif endif comment ****** HELP ****** elseif _spook_cmd = "H" or _spook_cmd = "HELP" then comment {All help text is in the file spkhelp} xeq spkhelp ![_spook_parms-chr(0)] comment ****** INPUT / OUTPUT ****** elseif _spook_cmd="I" or _spook_cmd="IN" or _spook_cmd="INPUT" or & _spook_cmd="O" or _spook_cmd="OUT" or _spook_cmd="OUTPUT" then comment {Convert to SPFXFER} echo ![_spook_rec-chr(0)] >spfxin echo EXIT >>spfxin if _spook_loud then echo Commands for SPFXFER are: print spfxin echo endif continue xeq spfxfer.pub.sys 0 do setvar _spook_i pos('=',_spook_parms) + 1 comment {Capture value of keyword in _spook_rec} setvar _spook_rec ltrim(rtrim( & str(_spook_parms,_spook_i,_spook_pos-_spook_i))) if lft(_spook_parms,4) = "PAGE" or & lft(_spook_parms,2) = "PG" then setvar _spook_page !_spook_rec elseif lft(_spook_parms,5) = "OWNER" then if bound(_spook_text) then echo Owner= ignored since you have a spoolfile TEXTed. pause 1 else setvar _spook_owner _spook_rec endif else echo Unknown keyword: "![lft(_spook_parms,_spook_i-2)]". & Expected PAGE= or OWNER=. setvar HPCIERR 2 endif comment {Remove this option from _spook_parms} setvar _spook_parms ltrim(rht(_spook_parms,& len(_spook_parms)-_spook_pos)) endwhile if not bound(_spook_text) then comment {No currently TEXTed spoolfile} continue listspf O@;seleq=[owner=!_spook_owner] >spook000 if HPCIERR = 0 then xeq spook entry="default_spoolfiles" 0 then echo No text file, see TEXT command. else comment {Pass list range to spook for parsing} xeq spook entry="get_range" parms=!_spook_range if HPCIERR = 0 then comment {Increment current line count} setvar _spook_next_rec _spook_end+1 if _spook_end > 0 then comment {List something (vs. position curr_rec to 1)} if _spook_text_eof = 0 then comment {Spoolfile is in 'create' state} setvar _spook_start "" setvar _spook_end "" else comment {eof > 0, thus "end" range has meaning} if _spook_next_rec > _spook_text_eof then setvar _spook_next_rec _spook_text_eof endif setvar _spook_start ";start=!_spook_start" setvar _spook_end ";end=!_spook_end" endif continue print !_spook_text !_spook_start !_spook_end;page=& !_spook_page;num endif endif endif comment {Restore saved owner} setvar _spook_owner _spook_save_owner comment ****** LISTREDO ****** elseif _spook_cmd = "LISTR" or _spook_cmd = "LISTREDO" then comment {New SPOOK command} if HPREDOSIZE <= 0 then echo HPREDOSIZE is 0 -- DO/REDO/LISTREDO are disabled. else setvar _spook_i max(0,_spook_cmdnum-HPREDOSIZE) while setvar(_spook_i,_spook_i+1) <= _spook_cmdnum do echo !_spook_i) !"_spook_cmd!_spook_i" endwhile endif comment ****** PURGE ****** elseif _spook_cmd = "P" or _spook_cmd = "PURGE" then comment {Convert to SPOOLF...;DELETE} xeq spook entry="do_alt_purge_show" parms=2 if HPCIERR = 0 then if _spook_loud then setvar _spook_opts _spook_opts + ';SHOW' echo spoolf !_spook_dfid !_spook_opts ;DELETE endif setvar hpmsgfence 0 continue spoolf !_spook_dfid !_spook_opts ;DELETE setvar hpmsgfence 1 if HPCIERR <= 0 then comment {See if we purged the current text file.} if bound(_spook_text) and not finfo(_spook_text,0) then deletevar _spook_text@ endif comment {Clear saved (tilda) spec after PURGE.} deletevar _spook_tilda@ endif endif comment ****** RAWLIST ****** elseif _spook_cmd = "RAWL" or _spook_cmd = "RAWLIST" then comment {Convert to PRINTSPF} if len(_spook_parms) > 1 and lft(_spook_parms,1) <> "*" then comment {Supplied the dfid} comment {Cause passed dfid to become the current text file} xeq spook entry="text_file" parms=!_spook_parms elseif not bound(_spook_text) then echo No text file, see TEXT command. setvar HPCIERR 1 endif if HPCIERR = 0 then comment {Create input file for printspf} echo EXIT >prtspfi continue xeq printspf.pub.sys !_spook_text prtspfl continue print prtspfl purge prtspfi,temp purge prtspfl,temp endif comment ****** SET ****** elseif _spook_cmd = "SET" then if len(_spook_parms) = 1 then comment {No parm, display current values} if _spook_loud then echo Msg = LOUD else echo Msg = QUIET endif echo Owner = !_spook_owner else comment {Append ';' for easier parsing and delete nul} setvar _spook_parms _spook_parms-chr(0)+';' comment {Extract optional ;MSG= and ;OWNER= parms} while HPCIERR = 0 and & setvar(_spook_pos,pos(';',_spook_parms)) > 0 do setvar _spook_i pos('=',_spook_parms) + 1 comment {Capture value of keyword in _spook_rec} setvar _spook_rec ltrim(rtrim( & str(_spook_parms,_spook_i,_spook_pos-_spook_i))) if _spook_i > 1 then comment {keyword= was specified} if lft(_spook_parms,3) = "MSG" then if _spook_rec = 'LOUD' or _spook_rec = 'QUIET' then setvar _spook_loud _spook_rec='LOUD' else echo Expected MSG=LOUD or MSG=QUIET. setvar HPCIERR 1 endif elseif lft(_spook_parms,5) = "OWNER" then setvar _spook_owner _spook_rec if pos('.',_spook_owner) = 0 then setvar _spook_owner "!_spook_owner.!hpaccount" endif else echo Unknown keyword: & "![lft(_spook_parms,_spook_i-2)]". Expected MSG=& ,OWNER= or ! to see SET values. setvar HPCIERR 2 endif comment {Remove this option from _spook_parms} setvar _spook_parms ltrim(rht(_spook_parms,& len(_spook_parms)-_spook_pos)) else comment {No keyword=, process single parm as MSG or OWNER} setvar _spook_parms _spook_parms-';' if _spook_parms = "LOUD" or _spook_parms = "QUIET" then setvar _spook_loud _spook_parms='LOUD' else comment {Assume owner name} setvar _spook_owner _spook_parms if pos('.',_spook_owner) = 0 then setvar _spook_owner "!_spook_owner.!hpaccount" endif endif endif endwhile endif comment ****** SHOW ****** elseif _spook_cmd = "S" or _spook_cmd = "SHOW" then comment {Convert to LISTSPF} if len(_spook_parms) > 1 or & _spook_owner <> "!HPUSER.!HPACCOUNT" then xeq spook entry="do_alt_purge_show" parms=3 endif if HPCIERR = 0 then if _spook_dfid = "@" then comment {User[.acct] specified} comment {Parse additional SHOW options} if pos('@',_spook_parms) > 0 setvar _spook_opts _spook_opts + ";DETAIL" endif if pos('O',_spook_parms) > 0 then setvar _spook_dfid "O@" elseif pos('I',_spook_parms) > 0 then setvar _spook_dfid "I@" endif elseif len(_spook_dfid) > 0 then comment {Use ;detail when dfid(s) specified} setvar _spook_opts _spook_opts + ";DETAIL" endif if _spook_loud then echo listspf !_spook_dfid !_spook_opts endif continue listspf !_spook_dfid !_spook_opts endif comment ****** TEXT ****** elseif _spook_cmd = "T" or _spook_cmd = "TEXT" then comment {All text-related variable names begin with "_spook_text"} if len(_spook_parms) = 1 or lft(_spook_parms,1) = "*" then if bound(_spook_text) then if _spook_loud then echo File !_spook_text is un-texted. endif deletevar _spook_text@ endif else xeq spook entry="text_file" parms=!_spook_parms if HPCIERR = 0 and _spook_loud then echo Text file is: !_spook_text. echo Eof: !_spook_text_eof. Created on: & ![finfo(_spook_text,"fmtcreated")] at & ![finfo(_spook_text,"fmtalloctime")]. endif endif comment ****** MPE COMMAND ****** else comment {Otherwise, try to execute an MPE command} setvar _spook_rec _spook_rec - chr(0) comment {Save spook prompt length for possible caret position} setvar _spook_pos len("!_spook_prompt") if lft(_spook_rec,1) = ":" then setvar _spook_rec _spook_rec - ":" setvar _spook_pos _spook_pos+1 endif comment {Execute the command} setvar HPMSGFENCE 2 continue !_spook_rec setvar HPMSGFENCE 1 if HPCIERR = 975 then echo Invalid command name -- try HELP. elseif HPCIERR <> 0 then if HPCIERRCOL > 0 then echo ![rpt(" ",HPCIERRCOL+_spook_pos-1)]^ endif if hpfserr > 0 then echo FILE SYSTEM ERROR NUMBER: !HPFSERR endif echo !HPCIERRMSG endif endif comment {Increment cmd#, if necessary pop last command from redo stack} if setvar(_spook_cmdnum,_spook_cmdnum+1) > HPREDOSIZE and & _spook_push_cmd then deletevar _spook_cmd![_spook_cmdnum-HPREDOSIZE] endif endif endwhile comment {Cleanup!} setvar HPMSGFENCE _spook_save_msgfence deletevar _spook_@ endif return comment End of SPOOK! ************ Version History ************** 1.0 Initial (limited) release supporting alter,edit,exit,find,help,list, purge,show,text, and an MPE interface. SPOOK is ONE file with NO PROCESS CREATES so far... 1.1 Fixed text bug where finfo was called to get _spook_text_eof even if the dfid did not exist in .out.hpspool. Re-wrote list to use the new "get_range" entry point. This will later be used by find. Fixed bug where we strip the cctl char on nocctl files. 1.2 Added ",range" to find. 1.3 Some minor cleanup based on Steve Elmer's suggestions. Added test for existence of hpeditor and changed ";I@"and ";O@" logic into elseif. I also added some help text. 1.4 Fixed bug where :cmds were not executed since len(_spook_cmd) = 0. 1.5 Added browse,input,output commands. Changed get_dfid_or_username to use the "parms" parameter as input. 1.6 Fixed bug when range is used with find. Changed get_range entry to not expect chr(0) in parms. 1.7 Fixed bug where spfxfer was spelled spxfer. Added logic to purge to delete all text variables if _spook_text was one of the files purged. 1.8 Added set [loud|quiet] command, and incorporated this into alter,input, output,purge,text. 1.9 Fixed bug where 'exit' was append to the wrong file for in/out cmds. 1.10 In 'loud' mode the creation date is displayed when a file is texted. 2.0 Official BARUG version. Cleaned up some flaws Scott Cressler found. 2.1 Very minor quotes and indentation cleanup, added a few comments, echo the ;show option when loud, echo the dfid in browse and edit when not passed and loud. Also added _spook_noise_save so that internal calls don't echo when the outer level is loud. 2.2 Added rawlist command which invokes printspf. 2.3 Added dfid parm to rawlist. Internal changes related to texting a file: added the "text_file" entry, deleted the "cmd" parameter, deleted _spook_noise_save, etc. 2.4 Fixed bug in "find ,range" where the comma was not stripped before calling "get_range". This aborted spook when f,all was enterd. 2.5 Added typeof() checking to the range parameters in get_range and fixed list so that a dfid can be printed even when its eof=0 ('create'). 2.6 Enhanced get_dfid_or_username to accept a list of user[.acct]'s mixed with 0 or more dfid's. This entry is used by alter,purge,show. Help is ahead of spook since "-" logic has not yet been added. 2.7 Added minus ("-") feature to get_dfid_or_username. Now you can do a purge @.hpe,@.ui-jeff.ui,-#o123-456....etc! Flexible syntax. 2.8 Performance enhancement for find to not make a local copy of the file if the starting record is 1. Also, enhanced list to accept a starting record of 0 to position the current record to 1. 2.9 Fixed bug in exception (-) handling where s @-foo,123 didn't show 123 if it belonged to foo. Rewrote alot of get_dfid_or_username entry. Changed prompt to "spook> ". 3.0 Added ;daysold and ;date parameters to alt, purge and show. <,<=,=,>,>= are valid relational operators. "do_daysold" and "do_date" are new entries. 3.1 Moved all help text to the file spkhelp. Added more detailed help info for each command. 3.2 Changed get_range so that '*' means current record (not next). Also renamed _spook_curr_rec to _spook_next_rec. Enhanced get_range to force start/end record numbers to be within the file. 3.3 Added ;page= to the list command. Also let HPPAGE variable define default page size. 3.4 Made spook run with hpmsgfence 1 to suppress warnings (like no spoolfile found). Saved the original hpmsgfence value. 3.5 Fixed a bug where daysold>=n became daten became date<=y. Also started supporting tilda in alt,purge,show, eg. s @.ui,123,hpe.@ shows a bunch of files. p ~ refers to the same selection. Limitations: does not "remember" daysold or date specification. 3.6 Full support of tilda feature (ie. date= and daysold "remembered"). 3.7 Fixed bug where hpmsgfence was set to 1 then back to 0 in list and find commands. 3.8 Enhanced list command to not require the spoolfile to be texted. If no spoolfile is texted then user's own spoolfiles can be selected via an index. If only one spoolfile exists it is automatically chosen. Also changed _spook_noise='LOUD' to _spook_loud boolean variable. Also added check in get_dfid_or_username for '*' but no texted spoolfile. 3.9 Fixed up default_spoolfiles entry and added info= to spook. 3.10 Added implicit text feature to browse and edit commands. 4.0 Added owner= to list and set commands. New syntax for set: set [msg=loud] [;owner=user[.acct]]. Show and implicit list default to the current owner (defined by set). 4.1 Added the do and listredo commands. Redo stack define by hpredosize. 4.2 Fixed bug where SET owner=name was ignored for SHOW/ALT/PURGE commands that specified an unqualified username. Fixed caret position error since command number and optional leading ':' weren't considered. Added _spook_prompt var and changed prompt from '>' to ':' to prevent i/o redirection problems! Also moved SET help text after SHOW text.