home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Spezial / SPEZIAL2_97.zip / SPEZIAL2_97.iso / ANWEND / ONLINE / SREFV12J / DOSEARCH.CM0 < prev    next >
Text File  |  1997-06-29  |  29KB  |  776 lines

  1. /****************************************************************/
  2. /* generic text file  search utility for SREFILTR package.  Designed to be used
  3. as a directly requested file searcher, or as part of a "searchable index" process
  4. (when used in conjunction with an SRE-Filter alias).
  5.  
  6.  
  7.   ---- Invoking DOSEARCH ---
  8.  
  9.   When called directly, the "request string"    should have the form:
  10.        DOSEARCH?option_1=val_1&option_2=val_2&etc.
  11.    where the file to be searched, the search string, and other options are returned
  12.    in the option_n list.
  13.    In this case, list0=option_1=val_1&option_2=val_2&etc.
  14.    Note that a FILE and a SEARCH option should always be present.
  15.  
  16.  --------  DOSEARCH options -----
  17.  
  18. DOSEARCH looks at "paragraphs".  By default, a paragraph is defined as being
  19. all text between blank lines.  Alternatively, one can define paragraphs as single lines,
  20. or as delimited by any arbitrary character sequence (see options section below).
  21.  
  22. A search string is comprised of "targets" There are two kinds of targets: subwords and phrases.
  23.   Each space delimited entry in the search string is treated as a seperate "subwords".
  24.   Phrases are delimited by ( xx yy zz ); phrases must be matched precisely.
  25.  
  26. Search algorithims.  There are two modes:
  27.  Simple mode with highlighting.  Two "meta commands" and 4 "target specific"
  28.  instructions are recognized.  
  29.         Meta commands are signified by *& or *\ at the beginning of the search string.
  30.              *&  means "find paragraphs that match ALL targets in the search string"
  31.              *\  means "find paragraphs that match NONE of the targets in the search string"
  32.      If there are no meta commands, the following "target specific" commands are recognized.
  33.           &  means "paragraphs MUST have this target"
  34.           |   means "accept paragraph if it has this target"
  35.               Note that | is the default (assumed if no target specific command entered).
  36.           \ means "paragraph must NOT have this target" 
  37.           % means "accept paragraph if it does NOT have this target"
  38.  
  39.     Summarizing: to be a "found" paragraph:
  40.       Test 1a) Any | must be present,    or
  41.             1b)   All of the % are missing
  42.             (if no % appears, then 1b is ignored)
  43.       Test 2a) If pass test 1, then
  44.             2b)   None of the \ can be present, and
  45.                All of the & must be present
  46.      If present, all & and | targets will be highlighted
  47.  
  48.  Logical expression mode without highlighting.
  49.       The user enters a logical expression using the following operators:
  50.           & = AND  ,  | = OR ,    \ = not ,   @ = xor , ( ) to group expressions.
  51.       A sequence of words without any operators is treated as a phrase -- to
  52.       treat each word as a seperate subword, put ( ) around each one.
  53.       Basically, when using this mode, be liberal in your use of ( ).
  54.  
  55. Options (included in the ALIAS definition, or generated by a form):
  56.        Options are included after the searchstring, seperated by &.  Typically,
  57. they would be placed there by a form, not by an <ISINDEX> response.  Form of the
  58. options is option_name=option_value&option_Nam2=option_value2&...
  59.  
  60.        DELIM :  The paragraph delimiter.
  61.                    Blank or 0= blank lines   (the DEFAULT)
  62.                    $  = Each line is a paragraph
  63.                    other  = User specified delimiter
  64.        LINE : Maximum number of lines to display in a paragraph. If 0, no lines displayed
  65.               just summary.   Default is display all lines.
  66.        NUM : YES=Display the line or paragraph number, NO=Don't (Default=YES)
  67.        BAR:  YES= Seperate each paragraph/line by a horizontal bar, NO=Don't (Default=YES)
  68.        EXPERT: YES= Use "logical expression mode", NO=Use simple mode (Default=NO)
  69.       HIGHLIGHT: YES= Highlight mathes, NO=DON'T (only if non-expert mode)
  70.        FILE or FILES:  Additional files to search (can include wildcards)
  71.        SEARCH: Use this as the searchlist -- required for FORM based submittal,
  72.                 overrides default (first thing after the ? and before the first &) if
  73.                 a ISINDEX based submittal)
  74.                 Note: SEARCHFOR  STRING NEEDLE TARGET can be used instead of SEARCH
  75.        CASE : If YES, then search is case sensitive (default is no)
  76.  
  77.  
  78. Note: a FILE (or FILES) and a SEARCH option should always be present.
  79.  
  80. */
  81. /***********************************************************/
  82.  
  83.  
  84.  
  85. parse arg ddir,tempfile,sel,list00,verb,uri,user,basedir, ,
  86.                workdir,privset,enmadd,transaction,verbose, ,
  87.                SERVERNAME,HOST_NICKNAME,HOMEDIR
  88.  
  89. if verb="" then do
  90.    say " This SRE-Filter procedure is not meant to be run in stand alone mode"
  91.    exit
  92. end  /* Do */
  93.  
  94.  
  95.  
  96. /**** no longer used:
  97. ameth=upper(extract('clientmethod'))
  98. if ameth="GET" then
  99.    parse var uri foo '?' list0
  100. else ***** */
  101.  
  102. list0=list00
  103.  
  104. list0=translate(list0, ' ', '+'||'090a0d'x)  /* Whitespace, etc. */
  105.  
  106. ddir=translate(ddir,'\','/')
  107. ddir=strip(ddir,'t','\')||'\'
  108.  
  109. macrospace_input=strip(params0)
  110.  
  111. parse var uri index_htm '?' listuri
  112. index_htm=translate(strip(index_htm,,'/'))
  113.  
  114.  options=" "
  115.  gotss=0
  116.  searchlist=" "
  117. ifiles=0
  118.  
  119.  options=list0
  120.  
  121. para_delim=""
  122. maxdisp=1000000
  123. show_number=1
  124. show_bar=1
  125. expert_mode=0
  126. check_case=0
  127. highlight=1
  128.  
  129. /* get option */
  130. do until options=""
  131.   parse var options an1 '&' options
  132.   parse var  an1 aname '=' avalue
  133.   aname0=aname ; aname=translate(aname)
  134.   avalue0=avalue ; 
  135. /*  avalue=translate(avalue,' ','+'||'0d0a09'x) */
  136.   avalue0=packur(avalue)
  137.   avalue=translate(avalue0)
  138.   avalue=translate(avalue,' ','"')
  139.   avalue=translate(avalue,' ',"'")
  140.  
  141.  
  142.   select
  143.      when pos("DELIM",aname)> 0 then 
  144.          para_delim=avalue0
  145.   
  146.      when pos("LINE",aname)> 0 then
  147.          if datatype(avalue)="NUM" then
  148.               maxdisp=avalue
  149.      when pos("NUM",aname)>0 then
  150.          if left(avalue,1)="N" | avalue=0 then  show_number=0
  151.      when pos("BAR",aname)>0 then
  152.          if left(avalue,1)="N" | avalue=0 then  show_bar=0
  153.      when pos('EXPERT',aname)>0 then
  154.              if left(avalue,1)="Y" | avalue=1 then   expert_mode=1
  155.      when pos('HIGHLIGHT',aname)>0 then do
  156.                 if abbrev(avalue,'Y')=1 then highlight=1
  157.                 if abbrev(avalu,'N')=1 then highlight=0
  158.      end
  159.      when abbrev(aname,'FILE')=1 then do
  160.              if avalue<>"" then do
  161.                  ifiles=ifiles+1
  162.                  files.ifiles=avalue
  163.              end
  164.      end
  165.  
  166.  
  167.      when pos("CASE",aname)>0 then
  168.          if left(avalue,1)="Y" | avalue=1 then  check_case=1
  169.  
  170.      when wordpos(aname,'SEARCH SEARCHFOR STRING NEEDLE TARGET')>0 then do
  171.                searchlist=avalue0
  172.       end
  173.      otherwise
  174.   end
  175. end
  176.  
  177. /* note: default para_delim is "blank lines" */
  178.  
  179. searchlist=translate(searchlist,' ','+'||'000d0a09'x)
  180. searchlist=packur(searchlist)                   /* do it now, to revitalize &'s */
  181. if left(para_delim,1)='"' & right(para_delim,1)='"' then 
  182.     para_delim=strip(para_delim,,'"')
  183. if para_delim="" then para_delim=" "
  184. if para_delim=0 then para_delim=" "
  185. crlf = '0d0a'x
  186.  
  187.  
  188. /* ----------------- Section to do a search   -------------- */
  189.  
  190. /* If here, we have some  stuff in the request string (after a ? )
  191.    (either supplied explicitly, or  as a response to the searchable index created above */
  192.  
  193.  call lineout tempfile, '<!doctype html public "-//IETF//DTD HTML 2.0//EN">'
  194.  CALL LINEOUT TEMPFILE,'<html> <head> <title> Results of search </title>  </head>'
  195.  call lineout tempfile,'<body>'
  196.  
  197.  
  198. /* create list of files to search */
  199. files_todo=0
  200. do ido=1 to ifiles
  201.  
  202.       afilenam=sref_do_virtual(ddir,files.ido,enmadd,1,transaction,HOMEDIR,HOST_NICKNAME)
  203.       if afilenam=0 then iterate               /* error */
  204.       eek=sysfiletree(afilenam,'aflist','F')   /* check for */
  205.       if eek<>0 then iterate            /* error */
  206.       do ido1=1 to aflist.0             /* any matches */
  207.          files_todo=files_todo+1
  208.          file_list.files_todo=word(aflist.ido1,words(aflist.ido1)) /* grab name */
  209.          file_list.files_todo.original=files.ido
  210.       end
  211. end
  212. ith_file=0
  213.  
  214. if files_todo>0 then
  215.    call lineout tempfile,' <h3> Number of files to search: ' files_todo '</h3> <hr>'
  216.  
  217. NEXTFILE:               /* JUMP HERE TO READ NEXT FILE  *****************    */
  218.  
  219. ith_file=ith_File+1
  220. filename=strip(file_list.ith_file)
  221. afilenam=filename
  222. aoriginal=file_list.ith_file.original
  223. goober=filespec('n',filename)
  224.  
  225. /* read in this target file (filename) into filelines stem variable */
  226. filelines.0=0
  227. getit=0
  228.  
  229.  
  230. if filename<>"" then do                 /* check for no filename */
  231.  select
  232.    when para_delim=" " then do
  233.         getit=sref_fileread(afilenam,'filelines',,'e')
  234.    end
  235.    when para_delim="$" then do
  236.         getit=sref_fileread(afilenam,'filelines',,'e')
  237.    end
  238.   otherwise do
  239.        getit=grab_file_lines(afilenam,20,para_delim)
  240.   end
  241.  end
  242.  if VERBOSE>0 then say " DOSEARCH will examine:" afilenam "(# entries= " getit
  243.  
  244. end             /* filename<>"" */
  245.  
  246. /* problem ... */
  247. if getit <= 0 then   do             /*fatal error */
  248.     call lineout tempfile,'<h2> No search target </h2> '
  249.     if VERBOSE>0 then say " No such file " filename
  250.     call lineout tempfile,' <p> <strong> Can not find file: <strong> ' filename
  251.     call lineout tempfile,'</body> </html>'
  252.   call lineout tempfile
  253.  
  254.     return 'FILE  ERASE TYPE text/html NAME ' tempfile
  255. end
  256.  
  257.  
  258.  
  259. /* look for meta flags (they over ride individual  flags*/
  260. matchall=0 ; matchnone=0
  261. if word(searchlist,1)='*&' then do
  262.   matchall=1
  263.   searchlist=delword(searchlist,1,1)
  264. end
  265. else if word(searchlist,1)="*\" then do
  266.   matchnone=1
  267.   searchlist=delword(searchlist,1,1)
  268. end
  269.  
  270. if searchlist="" then do                /*missing searchlist */
  271.   call lineout tempfile,'<h2> No search list </h2> '
  272.    if VERBOSE>0 then say " No searchlist specified."
  273.    call lineout tempfile,' <p> <strong> No search list specified  <strong> ' 
  274.    call lineout tempfile,'</body> </html>'
  275.   call lineout tempfile
  276.  
  277.    return 'FILE  ERASE TYPE text/html NAME ' tempfile
  278. end
  279.  
  280.  
  281. /* write some else, basic facts .. */
  282.  call lineout tempfile,'<h2> Results of  search  </h2> '
  283.  call lineout tempfile,' File searched: <strong> ' goober ' </strong> '
  284.  if pos('*',aoriginal)>0 | pos('?',aoriginal)>0 then
  285.         call lineout tempfile,' <em> ( ' aoriginal ' ) </em> '
  286.  call lineout tempfile,' <br>Search pattern: <strong> ' searchlist ' </strong> '
  287.  if matchall=1 then call lineout tempfile, '<em> (must match all) </em> '
  288.  if matchnone=1 then call lineout tempfile, '<em> (must match none) </em> '
  289.  
  290.  call lineout tempfile,' <hr width= 75%>'
  291.  
  292. /* before extracting phrases, make sure & / ( and ) are spaced out */
  293. searchlist=sref_replacestrg(searchlist,'&',' & ','ALL') ;
  294. searchlist=sref_replacestrg(searchlist,'\',' \ ','ALL') ; 
  295. searchlist=sref_replacestrg(searchlist,'(',' ( ','ALL') ;
  296. searchlist=sref_replacestrg(searchlist,')',' ) ','ALL') ; 
  297. searchlist=sref_replacestrg(searchlist,'|',' | ','ALL') ;
  298.  
  299. if expert_mode=0 then do                /* fairly search scheme */
  300.     ith=get_searchfor(searchlist,check_case)   /* searchfor. and cond. are exposed */
  301.  
  302.     dispdetails=1          /* if a NOT or AND exists, set to 0 (since individual details are inaccurate*/
  303.     /* If there are global conditins, overwrite any spurious local conditions */
  304.     do mm=1 to searchfor.0
  305.       select
  306.         when matchall=1 then
  307.            cond.mm='AND'
  308.         when matchnone=1 then
  309.            cond.mm='ORNOT'
  310.         otherwise
  311.       end
  312.       if  cond.mm<>"OR" then dispdetails=0
  313.     end
  314. end
  315. else  do            /* expert mode: user enters syntatically correct search command */
  316.    searchlist=expert_parse(searchlist,'HAYSTACK',check_case)
  317. end
  318.  
  319.  
  320.  
  321. change_crlf=0
  322. select                  /* now, create "paragraphs" */
  323.    when para_delim=" " then do   /* the default-- blank lines as delimiters */
  324.       nthpara=build_paras()    /* filelines. and paras. are exposed */
  325.       if VERBOSE>0 then say " # paragraphs " nthpara
  326.     end
  327.    /* filelines might be lines of the file, or "delimited" blocks
  328.        Note that "user delimited" blocks retain CRLFs. */
  329.     otherwise  do                  /* use each line, or  para_delim literally */
  330.       do mm=1 to filelines.0
  331.           paras.mm.first=mm
  332.           paras.mm.last=mm
  333.       end
  334.       nthpara=filelines.0
  335.       if para_delim<>'$' then change_crlf=1  /* change to <BR> below */
  336.    end
  337.   end
  338.  
  339. /* Now find 'paragraphs' containing the search patterns */
  340.  
  341. nmatch=0
  342. if expert_mode=0 then
  343.   do jj=1 to searchfor.0
  344.      allmatch.jj=0
  345.   end
  346.  
  347. do mm=1 to nthpara
  348.  
  349.    apara=""
  350.    do mm2=paras.mm.first to paras.mm.last   /* create a paragraph */
  351.       apara=apara||' '||filelines.mm2
  352.    end
  353.  
  354. /* -------- see if this paragraph is a hit */
  355.  
  356.  
  357.      if expert_mode=0 then
  358.          gotems=match_para(apara,checK_case)  /* searchfor. cond. mlist. are exposed */
  359.  
  360.      else do
  361.         haystack=apara
  362.         if check_case<>1 then haystack=translate(haystack)
  363.         signal on syntax name oyvey
  364.         interpret 'gotems='||searchlist
  365.         signal off syntax
  366.      end
  367.  
  368.      if gotems=0 then do
  369.        iterate       /* get next paragraph */
  370.      end
  371.  
  372.  
  373. /* if here, got a match. So write out the paragraph */
  374.      nmatch=nmatch+1         /* summary counter */
  375.      if maxdisp=0 then iterate
  376.  
  377.      if para_delim<>'$' then
  378.          if show_number=1 then
  379.             call lineout tempfile,'<h6 align=center>Paragraph #  '  mm ' </h6> '
  380.          else
  381.              call lineout tempfile,'<p>'    /* make space in output doc */
  382.  
  383.       else do
  384.          call lineout tempfile,'<p>'    /* make space in output doc */
  385.      end
  386.  
  387.      writlin=0
  388.   
  389.      do mm2=paras.mm.first to paras.mm.last  /* output original 'lines' */
  390.                     aline=filelines.mm2         /* that comprise the paragraph */
  391.  
  392.           IF EXPERT_MODE=0 THEN
  393.              do mm3=1 to searchfor.0    /* we know that pre is weren't present*/
  394.                if mlist.mm3 =0 then iterate
  395.                if HIGHLIGHT=1 then
  396.                   aline=sref_make_block(searchfor.mm3,aline,'<b>','</b>',check_case) /* highlight matches */
  397.             end         /* Note: expert mode does NOT have highlighting */
  398.  
  399.           if change_crlf=1 then                 /* convert crlf in custom delimited blocks */
  400.               aline= sref_replacestrg(aline,crlf,'<BR>','ALL')
  401.           if para_delim<>'$' then
  402.              call lineout tempfile, aline ' <br>'
  403.           else
  404.              if show_number=1 then call lineout tempfile, '<cite> ' mm2  ' : </cite>  ' aline
  405.              else call lineout tempfile,  aline
  406.  
  407.           writlin=writlin+1
  408.           if writlin>=maxdisp then leave
  409.      end                     /* output lines of the paragraph */
  410.      if para_delim<>'$' & show_bar=1 then
  411.          call lineout tempfile,' <hr width=10% height=5> '
  412.  
  413.      /* jump here if matchall=1 and not all matches */
  414. end                    /* do next paragraph */
  415.  
  416.  
  417. asummary:
  418.   call lineout tempfile,' <hr width= 75%>'
  419.   call lineout tempfile,' <p> <h3> Summary of results: ' goober ' </h3> '
  420.   call lineout tempfile,'  # "paragraphs" = ' nthpara
  421.   if para_delim=" "  para_delim="$" then do
  422.     call lineout tempfile,' <menu> '
  423.     call lineout tempfile,' <li> # of lines = ' filelines.0
  424.     call lineout tempfile,'</menu> '
  425.   end
  426.   else
  427.     call lineout tempfile,'<br> '
  428.  
  429.   call lineout tempfile,'  # paragraphs with matches= ' nmatch
  430.   if dispdetails=1 then do
  431.     call lineout tempfile,'<menu> '
  432.     do mm=1 to searchfor.0
  433.        call lineout tempfile,'<li> ' searchfor.mm ' = ' allmatch.mm
  434.     end
  435.     call lineout tempfile,'</menu> '
  436.   end
  437.  
  438.  if ith_file<files_todo then do                     /* get next file */
  439.       call lineout tempfile,'  <hr> '
  440.       call lineout tempfile,'  <Hr width=5> '
  441.       call lineout tempfile,' <hr> '
  442.  
  443.       signal nextfile
  444. end
  445.  
  446.   call lineout tempfile,'</body>'
  447.   call lineout tempfile,'</html>'
  448.   call lineout tempfile
  449.  
  450. /* check if "fix expire" should be done */
  451.   FIX_EXPIRE = get_value('FIX_EXPIRE')
  452.   itt=chars(tempfile);aa=stream(tempfile,'c','close')
  453.   IF FIX_EXPIRE>0 THEN DO
  454.           FOO=EXPIRE_response(fix_expire,itt)
  455.   end
  456.   return 'FILE  ERASE TYPE text/html NAME ' tempfile
  457.  
  458. oyvey:                  /* jump here if bad expert mode */
  459.   call lineout tempfile,'<h3> Bad logical search expression </h2> '
  460.    if VERBOSE>0 then  say " Bad  searchlist specified."
  461.    call lineout tempfile,' <p> <strong> A bad logical expression was specified  <strong> '
  462.    call lineout tempfile,'</body> </html>'
  463.   call lineout tempfile
  464.  
  465.    return 'FILE  ERASE TYPE text/html NAME ' tempfile
  466.  
  467.  
  468.  
  469. /* ----------------------------------------------------------------------- */
  470. /* GET_SEARCHFOR: Create the "search for" list (of things to search for ) */
  471. /* ----------------------------------------------------------------------- */
  472.  
  473. get_searchfor: procedure expose searchfor.  cond. verbose
  474. parse arg searchlist, check_case
  475.  
  476. ith=0
  477. if check_case<>1 then searchlist=translate(searchlist)
  478.  
  479. acondstate='OR'                 /* default state */
  480. mm=0
  481. do until mm=words(searchlist)
  482.    mm=mm+1
  483.    aword=word(searchlist,mm)
  484.    a1a=verify('\&(|%',aword,'m')
  485.    select 
  486.      when a1a=0  then do   
  487.         ith=ith+1
  488.         searchfor.ith=aword
  489.         cond.ith=acondstate
  490.         acondstate='OR'            /* reset to OR */
  491.      end
  492.      when a1a=1 then     /*  Not is an AND NOT */
  493.         acondstate='NOT'
  494.      when a1a=2 then
  495.         acondstate='AND'
  496.      when a1a=4 then            /* included for completeness */
  497.         acondstate='OR'
  498.      when a1a=5 then
  499.         acondstate='ORNOT'
  500.      when a1a=3 then do  /* begin a phrase -- find the first ) to end it */
  501.          ajj=wordpos(')',searchlist,mm)
  502.          if ajj=0 then ajj=words(searchlist)+1
  503.          if ajj>mm+1 then do
  504.             ith=ith+1
  505.             searchfor.ith=' '||subword(searchlist,mm+1,ajj-(mm+1))||' '
  506.             cond.ith=acondstate
  507.          end
  508.          mm=ajj
  509.       end
  510.       otherwise
  511.    end
  512. end
  513. searchfor.0=ith
  514. return ith
  515.  
  516.  
  517. /* -------------------------------------------------------- */
  518. /* BUILD_PARAS: Build paragraphs from lines (blank line delimits a paragraph */
  519. /* -------------------------------------------------------- */
  520.  
  521. build_paras: procedure expose filelines. paras. verbose
  522.   
  523.      apara=0
  524.      nthpara=0
  525.      do mm=1 to filelines.0
  526.        if filelines.mm="" then do
  527.           if apara=1 then do    /* second or more of a series of blank lines */
  528.               paras.nthpara.last=mm-1
  529.              apara=0
  530.           end
  531.         end
  532.         else do
  533.           if apara=0  then do
  534.              nthpara=nthpara+1
  535.              paras.nthpara.first=mm
  536.              apara=1
  537.           end
  538.         end
  539.      end  /* Do filelines.0 */
  540.  
  541.      if apara=1 then paras.nthpara.last=filelines.0
  542.      return nthpara
  543.  
  544. /* ------------------------------------------------------------------- */
  545. /* MATCH_PARA: Does this paragraph match the search string(s)  */
  546. /* ------------------------------------------------------------------- */
  547.  
  548. match_para: procedure expose searchfor. cond. mlist. allmatch. verbose
  549.   parse arg apara , check_case
  550.  
  551.   apara2=apara
  552.   if check_case<>1 then apara2=translate(apara2)
  553.  
  554. /* scan for matches in the paragraph */
  555.     gotems=0 ; numors=0
  556.  
  557.     do nn= 1 to searchfor.0                     /*see how many or conditions there are */
  558.         if cond.nn="OR" then numors=numors+1
  559.         mlist.nn=0
  560.     end
  561.  
  562.     do is=1 to searchfor.0   /*search for targets in this paragraph*/
  563.        joe=pos(searchfor.is,apara2)
  564.  
  565.        if joe=0 & cond.is="AND" then do    /* failure of an "all matches" */
  566.            gotems=0
  567.            leave
  568.        end
  569.        if joe>0 & cond.is="NOT" then do   /* failure of a "not any of these*/
  570.            gotems=0
  571.            leave
  572.        end
  573.        if joe>0 & cond.is="ORNOT"  then do  /* or not condition failed */
  574.            gotems=0
  575.            leave
  576.        end
  577.  
  578. /* if here, no fatal flaw */
  579.       if (joe>0 ) & (pos('NOT',cond.is)=0) then mlist.is=1
  580.  
  581.       if  (joe>0 & cond.is="OR") | (joe=0 & cond.is="ORNOT")  then do
  582.               allmatch.is=allmatch.is+1
  583.               gotems=gotems+1
  584.        end
  585.        if (joe>0 & cond.is="AND" & numors=0) then do  /* if no or conditions.. */
  586.               gotems=gotems+1
  587.               allmatch.is=allmatch.is+1
  588.        end
  589.        
  590.      end
  591.      return gotems
  592.  
  593.  
  594.  
  595. /* -------------------------------------------------------------- */
  596. /*  GRAB_FILE_LINES:  Get a file, parse into a "lines" stem variable
  597. .  Read in a file, but first check to see if openable, and if
  598. .  so, open and  read.  After reading, split into logical lines,
  599. .  using the eol character ('0d0a'x  by default), and return
  600. .  each of these lines in the filelines. stem variable.
  601. .  Note: filelines.0 holds # of lines; also, the number of lines
  602. .  is returned (so if 0 returned, failure probably caused by no such file)
  603. .  Usage:
  604. .   filelines.0= 0 ;  nlines=grab_file_lines(afile,30,optional_eol_delimiter)
  605. .   (filelines.1 to filelines.(filelines.0) contain afile)
  606. */
  607. /* ------------------------------------------------------------- */
  608.  
  609. grab_file_lines: procedure expose filelines. verbose
  610.  
  611. parse arg afile, msec, aneol    /* file to get, seconds to wait, eol delimiter */
  612.  
  613. crlf = '0d0a'x
  614.  
  615. if aneol="" then aneol=crlf
  616.  
  617. ause=sref_grab_file(afile,msec)
  618. if ause=0 then                  /* couldn't get it */
  619.   return 0
  620.  
  621. /* got a file, let's parse it */
  622. if filelines.0<>0 & VERBOSE>0 then say " Warning: overwriting filelines stem variable "
  623. filelines.0=0
  624. i=0
  625. aneol=strip(aneol)
  626. do until ause=""
  627.   i=i+1
  628.   parse var ause filelines.i (aneol) ause
  629. end
  630. filelines.0=i
  631. return filelines.0
  632.  
  633. /********************************************************************************/
  634. /***********************************/
  635. /* Tim Osborne's fancy logical parser */
  636.  
  637. expert_parse: procedure  expose verbose
  638.  parse  arg mystring , haystack , check_case
  639.   if check_case<>1 then mystring=translate(mystring)
  640.  
  641.  if haystack="" then haystack="HAYSTACK"
  642.  
  643. /*
  644.   User enters logical search string
  645.  
  646.    User can include any level of nested parentheses to
  647.    override normal order of logical statement.  Parentheses
  648.    are not required however.
  649.  
  650. say 'What are you looking for?'
  651. pull mystring
  652. */
  653.  
  654. mystring='('||mystring||')'
  655. mystring=space(mystring)
  656. if pos('(',mystring)=0 & pos('|',mystring)=0 & pos('\',mystring)=0 & pos('&',mystring)=0 & pos('@',mystring)=0 then do
  657.    mystring='('||mystring||')'
  658.    end
  659. else do
  660.    blanks= pos(' (',mystring)>0 | pos('( ',mystring)>0 | pos(' &',mystring) >0 | pos('& ',mystring)>0 |,
  661.            pos(' |',mystring)>0 | pos('| ',mystring)>0 | pos(' @',mystring) >0 | pos('@ ',mystring)>0 |,
  662.            pos(' \',mystring)>0 | pos('\ ',mystring)>0 | pos(' )',mystring) >0 | pos(') ',mystring)>0
  663.    do while blanks > 0
  664.       if pos(' (',mystring) \=0 then mystring=substr(mystring,1,pos(' (',mystring)-1)||'('||substr(mystring,pos(' (',mystring)+2)
  665.       if pos(' )',mystring) \=0 then mystring=substr(mystring,1,pos(' )',mystring)-1)||')'||substr(mystring,pos(' )',mystring)+2)
  666.       if pos(' |',mystring) \=0 then mystring=substr(mystring,1,pos(' |',mystring)-1)||'|'||substr(mystring,pos(' |',mystring)+2)
  667.       if pos(' &',mystring) \=0 then mystring=substr(mystring,1,pos(' &',mystring)-1)||'&'||substr(mystring,pos(' &',mystring)+2)
  668.       if pos(' @',mystring) \=0 then mystring=substr(mystring,1,pos(' @',mystring)-1)||'@'||substr(mystring,pos(' @',mystring)+2)
  669.       if pos(' \',mystring) \=0 then mystring=substr(mystring,1,pos(' \',mystring)-1)||'\'||substr(mystring,pos(' \',mystring)+2)
  670.       if pos('( ',mystring) \=0 then mystring=substr(mystring,1,pos('( ',mystring)-1)||'('||substr(mystring,pos('( ',mystring)+2)
  671.       if pos(') ',mystring) \=0 then mystring=substr(mystring,1,pos(') ',mystring)-1)||')'||substr(mystring,pos(') ',mystring)+2)
  672.       if pos('| ',mystring) \=0 then mystring=substr(mystring,1,pos('| ',mystring)-1)||'|'||substr(mystring,pos('| ',mystring)+2)
  673.       if pos('& ',mystring) \=0 then mystring=substr(mystring,1,pos('& ',mystring)-1)||'&'||substr(mystring,pos('& ',mystring)+2)
  674.       if pos('@ ',mystring) \=0 then mystring=substr(mystring,1,pos('@ ',mystring)-1)||'@'||substr(mystring,pos('@ ',mystring)+2)
  675.       if pos('\ ',mystring) \=0 then mystring=substr(mystring,1,pos('\ ',mystring)-1)||'\'||substr(mystring,pos('\ ',mystring)+2)
  676.  
  677.            blanks= pos(' (',mystring)>0 | pos('( ',mystring)>0 | pos(' &',mystring) >0 | pos('& ',mystring)>0 |,
  678.               pos(' |',mystring)>0 | pos('| ',mystring)>0 | pos(' @',mystring) >0 | pos('@ ',mystring)>0 |,
  679.               pos(' \',mystring)>0 | pos('\ ',mystring)>0 | pos(' )',mystring) >0 | pos(') ',mystring)>0
  680.     end
  681. end
  682. if lastpos(')',mystring) \= length(mystring) then mystring='('||mystring||')'
  683. mystring=mystring||'*'
  684. pointer=1
  685. notin=1
  686. mychar=substr(mystring,pointer,1)
  687. do until mychar='*'
  688.            if pos(substr(mystring,pointer,1),'()|&@\')=0 & notin then do
  689.               mystring=substr(mystring,1,pointer-1)||'pos('''||substr(mystring,pointer)
  690.               notin=0
  691.               pointer=pointer+4
  692.            end
  693.            else do
  694.               if pos(substr(mystring,pointer,1),'()|&@\')>0 & notin=0 then do
  695.                  mystring=substr(mystring,1,pointer-1)||''',haystack)>0'||substr(mystring,pointer)
  696.                  notin=1
  697.                  pointer=pointer+12
  698.               end
  699.            end
  700.            pointer=pointer+1
  701.            mychar=substr(mystring,pointer,1)
  702. end
  703. mystring=substr(mystring,1,length(mystring)-1)
  704. do while pos('@',mystring)>0
  705.    mystring=insert('&&',mystring,pos('@',mystring))
  706.    mystring=delstr(mystring,pos('@',mystring),1)
  707. end
  708. /*say " mystring: " mystring*/
  709. return mystring
  710.  
  711.  
  712. /* ----------- */                                                        
  713. /* get environment value, possibly host specific */                      
  714. /* ------------ */                                                       
  715. get_value: procedure expose enmadd host_nickname                          
  716. parse arg vname,hname0
  717. if hname0=0 then 
  718.         hname=' '
  719. else                                                    
  720.     hname=strip(host_nickname)                          
  721.  
  722. vname=strip(vname) ;
  723. if hname<>' ' then do
  724.    booger=strip(enmadd||vname||'.'||hname)
  725.    aval=value(booger,,'os2environment')
  726.    if aval<>' ' Then                                                     
  727.         return aval                                                      
  728. end                                                                      
  729. aval=value(enmadd||vname,,'os2environment')                              
  730. return aval   
  731.  
  732.  
  733.  
  734. /* ----------------------------------------------------------------*/
  735. /* Routine to create an "expires" response header from scratch.
  736. Included here to provide support for object rexx.
  737. (the sref_expire macrospace routine could be used instead, but
  738. only if running under classic rexx)
  739. */
  740.  
  741. expire_response: procedure
  742.   parse arg aoffset, alength,am1,adrop,message_id
  743.   if am1="" then am1="text/html"
  744.   if alengh="" then alength=0
  745.   if aoffset="" then aoffset=0.04
  746.   if message_id=' ' then do
  747.         message_id=0
  748.         tst=upper(extract('test'))
  749.         if tst='ON' then do
  750.           p1=date('s')
  751.           p2=time('n') ; p2=delstr(p2,3,1); p2=delstr(p2,5,1)
  752.           p3=extract('serverport')
  753.           p4=extract('transaction')
  754.           p5=extract('serveraddr')
  755.           message_id='<'||p1||p2||'.'||p3||'.'||p4||'@'||p5||'>'
  756.         end
  757.   end
  758.  
  759.  
  760.   adrop1=' '
  761.    if adrop="" | abbrev(translate(adrop),'Y')=1 then adrop1="NOAUTO"
  762.  
  763.   'RESPONSE HTTP/1.0 200 OK EXPIRE OFFSET'     /* Set HTTP response line */
  764.   'HEADER ' adrop1 ' ADD Server: ' server()
  765.    thisdate=sref_new_gmt()' GMT '
  766.    expdate=sref_new_gmt(aoffset)' GMT'
  767.   'HEADER ADD Date: 'thisdate
  768.    if message_id<>'0' then
  769.         'HEADER ADD Message-ID: ' message_id
  770.   'HEADER ADD Content-Type: ' am1
  771.   'HEADER ADD Content-Length:' alength
  772.   'HEADER ADD Expires:'expdate
  773.   'HEADER ADD Content-Transfer-Encoding: binary '
  774. return 0
  775.  
  776.