PARM info='' entry=main ANYPARM parms=null # This command file translates the SPOOK command set to the NM Spooler. # Written by Jeff Vance (CSY) February 1990. if "!entry" = "text_file" then # Causes the dfid in "parms" to become texted. # Input: parms, a dfid terminated by chr(0) # Output: _spook_text, fully qualified Oxxx.OUT.HPSPOOL file # _spook_textid, just the Oxxx part of _spook_text # _spook_text_cctl, TRUE if _spook_text is a cctl file # _spook_next_rec, intialized to 1, first record in file # _spook_text_eof, set to eof of _spook_text # hpcierr, set to 52 if _spook_text not found # 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 # 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 # Dfid does not exist echo Non-existent device file (!_spook_text). setvar HPCIERR 52 # Cleanup "text" variables. deletevar _spook_text@ endif return elseif "!entry" = "default_spoolfiles" then # Reads output file, created by :listspf, and automatically # texts one of the user's spoolfiles. The user is given an # indexed choice when > 1 spoolid is found. # Input: none # Output: _spook_text@, if spoolfile selected (auto text occurs) # hpcierr, 1 if illegal input, -1 if no spoolid is # selected. # Assumptions: 1) input redirected to the output of a successful # :listspf, 2) since there is no error/warn there will be 1 or more # valid spoolfile ids in the file, 3) listspf does not # show input spoolfiles. # # Skip header records input _spook_rec input _spook_rec input _spook_rec # Build _spook_spoolid array of all spoolids in file # (empty record indicates end of spoolid output) setvar _spook_i 0 while len(setvar(_spook_spoolid_![setvar(_spook_i,_spook_i+1)], & word(input()))) > 0 do endwhile # Correct for empty record after last spoolid setvar _spook_i _spook_i - 1 # 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 # Echo list of spoolids while setvar(_spook_i,_spook_i+1) <= _spook_pos do echo !_spook_i) !"_spook_spoolid_!_spook_i" & ![finfo(rht(_spook_spoolid_!_spook_i,-2)+'.OUT.HPSPOOL',"fmtcreated")] & ![finfo(rht(_spook_spoolid_!_spook_i,-2)+'.OUT.HPSPOOL',"fmtalloctime")] endwhile setvar _spook_i _spook_i - 1 # Prompt user for spoolid choice, but remember input has # 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 # Non-integer input setvar _spook_i 0 endif # 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 # Cause the selected spoolid to be texted xeq spook entry="text_file" parms=![_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 # Parses list of dfid's and/or user[.acct]'s. Syntax: # spspec [,spspec [,spspec]] # spspec ::= spid [-spid [-spid]] ... # spid ::= dfid | user[.acct] | * | ~ # Unqualified usernames are qualified when the SET owner=name # is different from the logon user.acct. # Input: parms, contains difd/s or user.acct (no trailing chr(0)) # _spook_parms, everything right of command name # Output: _spook_dfid, list of dfid/s, or "@" if user.acct used # _spook_opts, seleq for owner= and/or spoolid= # _spook_parms, _spook_parms without dfids or usernames # hpcierr, set to 1 if invalid syntax # if "!parms" = "null" then # No dfid or user.acct specified setvar _spook_opts ";SELEQ=[OWNER=!_spook_owner]" setvar _spook_dfid "@" return endif if lft("!parms",1) = "-" then echo Cannot begin a spool spec with a "-", see HELP. setvar HPCIERR 1 return endif # Append a comma to make parsing easier setvar _spook_rec "!parms," # Change '*' to currently texted dfid if pos('*',_spook_rec) > 0 then if bound(_spook_text) then setvar _spook_rec repl(_spook_rec,'*','#!_spook_textid',1) else echo No spoolfile is currently TEXTed. setvar HPCIERR 2 return endif endif # Parse list of dfid's and/or user[.acct]'s setvar _spook_pos 0 while setvar(_spook_pos,_spook_pos+1) < len(_spook_rec) do setvar _spook_except '' setvar _spook_spid word(_spook_rec,",",1,_spook_pos,_spook_pos) # Look for exception spec ("-spid") if pos('-',_spook_spid) > 0 then # Create spid exception list setvar _spook_except rht(_spook_spid,-(pos('-',_spook_spid)+1)) setvar _spook_spid word(_spook_spid,'-') endif if numeric(lft(_spook_spid,1)) or lft(_spook_spid,1) = "#" then # 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 # user[.acct] if pos('.',_spook_spid) = 0 and & _spook_owner <> "!HPUSER.!HPACCOUNT" then # Qualify user names with acct name from _spook_owner setvar _spook_spid _spook_spid+"."+word(_spook_owner,'.',-1) endif setvar _spook_opts _spook_opts + "(OWNER=!_spook_spid" endif setvar _spook_i 0 while setvar(_spook_i,_spook_i+1) < len(_spook_except) do # Move exceptions to _spook_opts as part of seleq setvar _spook_spid word(_spook_except,"-",1,_spook_i,_spook_i) if numeric(lft(_spook_spid,1)) or lft(_spook_spid,1) = "#" then # dfid exception setvar _spook_opts _spook_opts + " AND SPOOLID<>!_spook_spid" else # user[.acct] exception if pos('.',_spook_spid) = 0 and & _spook_owner <> "!HPUSER.!HPACCOUNT" then # Qualify user names with acct name from _spook_owner setvar _spook_spid _spook_spid + & rht(_spook_owner,-pos('.'_spook_owner)) endif setvar _spook_opts _spook_opts + " AND OWNER<>!_spook_spid" endif endwhile if len(_spook_opts) > 0 then # Finish this spspec by appending ')' and 'or' for next spspec setvar _spook_opts _spook_opts + ") OR " endif endwhile # Fix up _spook_dfid and _spook_opts (ends in ') or ') if len(_spook_opts) > 0 then if len(_spook_dfid) > 0 then # Move dfids (ends in ',') to _spook_opts as part of seleq setvar _spook_i 0 while setvar(_spook_i,_spook_i+1) < len(_spook_dfids) do setvar _spook_opts _spook_opts + "(SPOOLID=" + & word(_spook_dfids,",",1,_spook_i,_spook_i) + ") OR " 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 # Return _spook_parms without dfid(s) or user.acct name(s) setvar _spook_parms _spook_parms-"!parms" return elseif "!entry" = "do_alt_purge_show" then # Parses the spool id selections for the alt,purge,show commands. # This includes a list of dfids and/or user names and/or one of # a date or daysold specification. Pri,copies,dev will be added. # Input: parms, command name: 1=ALTER, 2=PURGE, 3=SHOW. # _spook_parms, command line terminated with chr(0). # Output: _spook_opts, seleq containing owner and date spec # _spook_dfid, list of dfids or @ if any user names used # _spook_parms, command line minus the spool id # hpcierr, set if an error occurs # if len(_spook_parms) = 1 and !parms <> 3 then # 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 # 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 _spook_parms - "~" endif return endif # First parse the dfid[s] or user[.acct] name xeq spook entry="get_dfid_or_username" & parms=![word(_spook_parms,";"+chr(0))] if HPCIERR = 0 then # 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 # 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 # Parses the "daysold" parameter, appends it to _spook_opts as # part of the seleq. Number of days cannot exceed 30. Syntax: # ;daysold <,<=,=,>,>= # of days # Input: parms, indexes the 1st "d" in "daysold" # _spook_parms, the command line (less a spspec, if any) # Output: _spook_opts, seleq containing date spec # _spook_parms, command line minus daysold spec # hpcierr, set if an error occurs # # Left-justify "daysold" setvar _spook_rec word(_spook_parms,';',1,,!parms) # Return _spook_parms without daysold setvar _spook_parms _spook_parms - _spook_rec - ';' # Remove the "daysold" keyword setvar _spook_rec rht(_spook_rec,len(_spook_rec)-7) # Save the relational operator and inverse it's meaning # note: ord('<')=60, ord('=')=61, ord('>')=62 setvar _spook_relop chr(62 -((ord(lft(_spook_rec,1))+2) mod 62)) # 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,-3)] else setvar _spook_num ![rht(_spook_rec,-2)] 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 # 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 # Put date in seleq if len(_spook_opts) = 0 then setvar _spook_opts ";SELEQ=[" else # 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 # Parses the "date" parameter, appends it to _spook_opts as # part of the seleq. Date is in mm/dd/yy[yy] format. Syntax: # ;date <,<=,=,>,>= mm/dd/yy # Input: parms, indexes the "d" in "date" # _spook_parms, the command line (less a spspec, if any) # Output: _spook_opts, seleq containing date spec # _spook_parms, command line minus date spec # # Get the "date" token setvar _spook_rec word(_spook_parms,';',1,,!parms) # Return _spook_parms without date setvar _spook_parms _spook_parms - _spook_rec - ';' # Add year if left off if pos('/',_spook_rec) = pos('/',_spook_rec,-1) then setvar _spook_rec _spook_rec + "/!hpyear" endif # Put date in seleq if len(_spook_opts) = 0 then setvar _spook_opts ";SELEQ=[" else # 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 # Parses a range into starting and ending record numbers. # Handles #[/#],"*",+,-,FIRST,LAST. # Input: parms, contains range # _spook_next_rec, record number for current text file # Output: _spook_start, integer starting record number for :print # _spook_end, integer ending record number for :print # hpcierr, set to 1 if a range error occurs # if "!parms" = "null" then # 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 # Parse start [/end] specification setvar _spook_num word("!parms","/") setvar _spook_end word("!parms","/",-1) # Compute the actual start and end (account for "LAST", "*", etc) setvar _spook_i 0 while _spook_i <= 1 do # Loop twice # Handle *, use current rec (minus 1 since it is really next rec) setvar _spook_num repl(_spook_num,"*","![_spook_next_rec-1]") # Handle FIRST and LAST setvar _spook_num repl(_spook_num,"FIRST","1") setvar _spook_num repl(_spook_num,"LAST","!_spook_text_eof") # 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 # 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 # 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 # Returns the command number of the command in the redo stack # that matches 'parms'. Note: the DO/REDO cmd is still in the # redo stack at this point and _spook_cmdnum indexes the # DO/REDO command. # Input: parms, an absolute (pos. #) or relative (neg. #) # into redo stack, or a partial cmd string. # Nul terminated, upshifted. # Output: _spook_start, cmd number in redo stack # hpcierr, non-zero if cmd not found in redo stack # if HPREDOSIZE <= 0 then echo HPREDOSIZE is 0 -- DO/REDO/LISTREDO are disabled. setvar HPCIERR 1 return endif if '!parms' = chr(0) then # -1 is default setvar _spook_rec "-1" else setvar _spook_rec '!parms' - chr(0) endif if typeof(!_spook_rec) = 1 then # 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 # 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 # 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 # Finds first occurence of "_spook_pattern" in the _spook_textid # file. Input has been redirected from this file. # Input: _spook_pattern, case sensitive string to match in file # _spook_next_rec, current record number for _spook_textid # _spook_any_match,TRUE if '@' used in find # _spook_text_cctl,TRUE if dfid has CCTL byte in col 1 # Output: _spook_next_rec, # of next record (or last) after match # _spook_found, TRUE means pattern was found # setvar _spook_found FALSE while _spook_next_rec <= _spook_end and not (_spook_found) do # 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 rht(_spook_rec,len(_spook_rec)-1) endif # 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 # Match! Echo record with leading right-justified line number echo ![rpt(" ",8-len("!_spook_next_rec"))]!_spook_next_rec) & ![rtrim(_spook_rec)] # Echo carets(^^) under matching word echo ![rpt(" ",9+_spook_pos) + rpt("^",len(_spook_pattern))] # 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 # Main entry for SPOOK echo echo SPOOK/iX Emulator Version 5.0 echo Enter '&dLhelp new&d@' to see the new features for this version. # 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 # **** MAIN PROMPT / READ LOOP **** while _spook_looping do setvar _spook_cmd "" # Check for info= string if '!info' <> '' then setvar _spook_rec '!info'+chr(0) setvar _spook_looping FALSE elseif _spook_redo_input then # _spook_rec already contains the cmd from the redo stack setvar _spook_redo_input FALSE echo !_spook_prompt!_spook_rec else # Prompt and read user input setvar _spook_rec ltrim(rtrim(input("!_spook_prompt")))+chr(0) endif if len(_spook_rec) > 1 then # Push command on redo stack if setvar(_spook_push_cmd,HPREDOSIZE > 0) then setvar _spook_cmd!_spook_cmdnum _spook_rec endif # 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)) # Separate and deblank command parameters from cmd name setvar _spook_parms_raw repl(rht(_spook_rec,-_spook_i),' ','') setvar _spook_parms ups(_spook_parms_raw) setvar _spook_dfid setvar(_spook_opts,'') errclear # Case _spook_cmd of... # ****** ALTER ****** if _spook_cmd = "A" or _spook_cmd = "ALT" or _spook_cmd = "ALTER" then # Convert to SPOOLF...;ALTER xeq spook entry="do_alt_purge_show" parms=1 if HPCIERR = 0 then # Remove leading ';', parse for alter options setvar _spook_parms _spook_parms-';' setvar _spook_pos 0 while setvar(_spook_pos,_spook_pos+1) < len(_spook_parms) do setvar _spook_word word(_spook_parms,,,_spook_pos,_spook_pos) # Look for COPIES= ,DEV=, PRI= options if _spook_word = "C" or _spook_word = "COPIES" then setvar _spook_opts _spook_opts + ";COPIES=" + & word(_spook_parms,,,_spook_pos,_spook_pos+1) elseif _spook_word = "D" or _spook_word = "DEV" then setvar _spook_opts _spook_opts + ";DEV=" + & word(_spook_parms,,,_spook_pos,_spook_pos+1) elseif _spook_word = "P" or _spook_word = "PRI" then setvar _spook_opts _spook_opts + ";PRI=" + & word(_spook_parms,,,_spook_pos,_spook_pos+1) else echo Unknown keyword "!_spook_word". Expected COPIES=, & DEV=, and/or PRI=. setvar HPCIERR -1 endif 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 # ****** BROWSE ****** elseif _spook_cmd = "B" or _spook_cmd = "BROWSE" then # New SPOOK command: Syntax: browse [dfid] # 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 # Supplied the dfid # Cause passed dfid to become the current text file xeq spook entry="text_file" parms=!_spook_parms endif else # No spoolfile specified # 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 # Invoke hpbrowse passing the dfid file continue xeq hpbrowse.pub.sys "!_spook_text" endif # ****** DO / REDO ****** elseif _spook_cmd = "DO" or _spook_cmd = "REDO" then # New SPOOK commands xeq spook entry="get_redo_cmd" parms=!_spook_parms # Returns redo index in _spook_start if HPCIERR = 0 then # move redo stack cmd to _spook_rec for execution setvar _spook_rec _spook_cmd!_spook_start # _spook_rec has trailing chr(0) setvar _spook_redo_input TRUE # Handle redo edit if _spook_cmd = "REDO" then setvar _spook_rec _spook_rec - chr(0) echo !_spook_rec setvar _spook_parms input() while len(_spook_parms) > 0 do setvar _spook_rec edit(_spook_rec,_spook_parms) echo !_spook_rec setvar _spook_parms input() endwhile setvar _spook_rec _spook_rec + chr(0) endif endif # "pop" DO/REDO command from redo stack setvar _spook_cmdnum max(1,_spook_cmdnum-1) setvar _spook_push_cmd FALSE # ****** EDIT ****** elseif _spook_cmd = "EDIT" then # New SPOOK command: Syntax: edit [dfid] # 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 # Supplied the dfid # Cause passed dfid to become the current text file xeq spook entry="text_file" parms=!_spook_parms endif else # No spoolfile specified # 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 # Invoke the editor passing the dfid file continue !hpeditor "!_spook_text" endif # ****** EXIT / QUIT ****** elseif _spook_cmd = "E" or _spook_cmd = "Q" or & _spook_cmd = "EXIT" or _spook_cmd = "QUIT" then setvar _spook_looping FALSE # ****** 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 # Handles: F, F", F"", F@" + chr(0) echo No search pattern defined. else # 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 # 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 # No range parameter therefore null pattern echo Null pattern not allowed. setvar HPCIERR 1 endif else # 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) = "@" # Strip pattern from _spook_parms for range check setvar _spook_parms rht(_spook_parms,-_spook_i-1) endif endif if HPCIERR = 0 and len(_spook_parms) > 2 and & lft(_spook_parms,1) = "," then # 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 # 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 # Use .out.hpspool file directly file !_spook_textid=!_spook_text,old endif # 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 # ****** HELP ****** elseif _spook_cmd = "H" or _spook_cmd = "HELP" then # All help text is in the file spkhelp xeq spkhelp ![_spook_parms-chr(0)] # ****** 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 # 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 spook000 if HPCIERR = 0 then xeq spook entry="default_spoolfiles" 0 then echo No text file, see TEXT command. else # Pass list range to spook for parsing xeq spook entry="get_range" parms=!_spook_range if HPCIERR = 0 then # Increment current line count setvar _spook_next_rec _spook_end+1 if _spook_end > 0 then # List something (vs. position curr_rec to 1) if _spook_text_eof = 0 then # Spoolfile is in 'create' state setvar _spook_start "" setvar _spook_end "" else # 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 # Restore saved owner setvar _spook_owner _spook_save_owner # ****** LISTREDO ****** elseif _spook_cmd = "LISTR" or _spook_cmd = "LISTREDO" then # 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 # ****** PURGE ****** elseif _spook_cmd = "P" or _spook_cmd = "PURGE" then # Convert to SPOOLF...;DELETE xeq spook entry="do_alt_purge_show" parms=2 # Extra check for purge @.@ with no filtering if _spook_dfid = "@" and pos('OWNER=@.@',_spook_opts) > 0 and & pos('<>',_spook_opts) = 0 and pos('SM',hpusercapf) > 0 then if dwns(input("Do you really want to purge every & spoolfile? ",,1)) <> 'y' then setvar HPCIERR 1 endif endif 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 # See if we purged the current text file. if bound(_spook_text) and not finfo(_spook_text,0) then deletevar _spook_text@ endif # Clear saved (tilda) spec after PURGE. deletevar _spook_tilda@ endif endif # ****** RAWLIST ****** elseif _spook_cmd = "RAWL" or _spook_cmd = "RAWLIST" then # Convert to PRINTSPF if len(_spook_parms) > 1 and lft(_spook_parms,1) <> "*" then # Supplied the dfid # 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 # 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 # ****** SET ****** elseif _spook_cmd = "SET" then if len(_spook_parms) = 1 then # No parm, display current values if _spook_loud then echo Msg = LOUD else echo Msg = QUIET endif echo Owner = !_spook_owner else # Extract optional ;MSG= and ;OWNER= parms setvar _spook_i 0 while setvar(_spook_i,_spook_i+1) < len(_spook_parms) do setvar _spook_word & word(_spook_parms,';'+chr(0),1,_spook_i,_spook_i) if pos('=',_spook_word) > 0 then if setvar(_spook_rec,word(_spook_word,'=')) = "MSG" then if setvar(_spook_word,word(_spook_word,'=',-1))="LOUD" & or _spook_word="QUIET" then setvar _spook_loud _spook_word='LOUD' else echo Expected MSG=LOUD or MSG=QUIET. endif elseif _spook_rec = "OWNER" then setvar _spook_owner word(_spook_word,'=',-1) if pos('.',_spook_owner) = 0 then setvar _spook_owner "!_spook_owner.!hpaccount" endif else echo Unknown keyword "!_spook_rec=". Expected MSG= & and/or OWNER= or "DEFAULT" or ! endif else # No keyword=, assume 1 parm (loud, default, owner name) setvar _spook_i len(_spook_parms) if _spook_word="LOUD" or _spook_word="QUIET" then setvar _spook_loud (_spook_word="LOUD") elseif _spook_word = "DEFAULT" then setvar _spook_loud TRUE setvar _spook_owner "!HPUSER.!HPACCOUNT" else # Assume owner name setvar _spook_owner _spook_word if pos('.',_spook_owner) = 0 then setvar _spook_owner "!_spook_owner.!hpaccount" endif endif endif endwhile endif # ****** SHOW ****** elseif _spook_cmd = "S" or _spook_cmd = "SHOW" then # 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 # User[.acct] specified # 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 # 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 # ****** TEXT ****** elseif _spook_cmd = "T" or _spook_cmd = "TEXT" then # 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 # ****** MPE COMMAND ****** else # Otherwise, try to execute an MPE command setvar _spook_rec _spook_rec - chr(0) # 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 # 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 # 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 # Cleanup! setvar HPMSGFENCE _spook_save_msgfence deletevar _spook_@ endif return # 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 #s, 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. 5.0 Added REDO command based on the new edit() eval function. Cleaned up parsing by using repl(), word(), rht(..,-indx), etc. Requires MPE/iX Release 5.5 or later.