home *** CD-ROM | disk | FTP | other *** search
/ Aminet 10 / aminetcdnumber101996.iso / Aminet / util / rexx / ScionRexx.lha / Soundex.rexx < prev    next >
OS/2 REXX Batch file  |  1995-10-31  |  13KB  |  383 lines

  1. /****************************************************************************
  2.  *                                                                          *
  3.  * $VER: Soundex 1.05 (28 Oct 1995)
  4.  *                                                                          *
  5.  *                      Written by Freddy Ariës                             *
  6.  * Address: Lindeboomweg 7, NL-7135 KE Harreveld, The Netherlands.          *
  7.  *                                                                          *
  8.  * Program for Scion Genealogist 4.0 and above (no guarantees are given     *
  9.  * for lower versions). This program should ask the user for a surname,     *
  10.  * and output the list of names in the current Scion database that match    *
  11.  * the entered name, using the SOUNDEX method of name comparison.           *
  12.  * Scion Genealogist must be running for this script to work.               *
  13.  *                                                                          *
  14.  * This script uses (by default) the rexxreqtools.library (which requires   *
  15.  * a version of reqtools larger than 2.0 and rexxsyslib.library)            *
  16.  * If you do not have these, run SetDefaults.rexx to change the settings.   *
  17.  *                                                                          *
  18.  * For those who don't know what SOUNDEX is, here is a short intro:         *
  19.  *                                                                          *
  20.  * The Soundex system is the means established by the National Archives     *
  21.  * to index the U.S. censuses (beginning with 1880). It codes together      *
  22.  * surnames of the same and similar sounds but of variant spellings.        *
  23.  * Soundexes are arranged by state, Soundex code of the surname, and        *
  24.  * given name.                                                              *
  25.  *                                                                          *
  26.  * Soundex codes begin with the first letter of the surname followed by a   *
  27.  * three-digit code that represents the (first three) remaining consonants. *
  28.  * This Soundex converter will do the tricky work for you and capture the   *
  29.  * nuances of the coding scheme (such as coding adjacent like letters as    *
  30.  * one). Just enter the surname that you want coded.                        *
  31.  *                                                                          *
  32.  * Soundex Coding Guide                                                     *
  33.  *  1 = B,P,F,V                                                             *
  34.  *  2 = C,S,G,J,K,Q,X,Z                                                     *
  35.  *  3 = D,T                                                                 *
  36.  *  4 = L                                                                   *
  37.  *  5 = M,N                                                                 *
  38.  *  6 = R                                                                   *
  39.  *                                                                          *
  40.  * The letters A,E,I,O,U,Y,H and W are not coded.                           *
  41.  *                                                                          *
  42.  * Note that surname prefixes such as Van, Von, Di, De, Le, D', dela, or    *
  43.  * du are sometimes disregarded in alphabetizing and in coding.             *
  44.  * Therefor it is wise to code it with and without the prefix because it    *
  45.  * may be listed under either code. Eg. Van Hoesen could be coded as        *
  46.  * VanHoesen or as Hoesen.                                                  *
  47.  *                                                                          *
  48.  * DONE:                                                                    *
  49.  * - 2 consecutive letters with the same code are now treated as one        *
  50.  *   eg. LLOYD=LOYD -> [LD=L300], and JACKSON (CKS are all 2) -> [JCN=J250] *
  51.  * - now uses preference file for default settings                          *
  52.  *                                                                          *
  53.  * TO DO (but low priority):                                                *
  54.  *  - Automatically do the above coding (2 alternatives) for prefixes.      *
  55.  *  - Suggestions, comments, bugreports, donations, etc. are appreciated.   *
  56.  *                                                                          *
  57.  ****************************************************************************/
  58.  
  59. options failat 20; options results
  60. arg srchstr outname outval
  61.  
  62. versionstr = "1.05"
  63.  
  64. /* Don't change the settings here! Run SetDefaults.rexx instead! */
  65. usereq = 1; outp = 1; scrdev = stdout
  66. plwidth = 78
  67. PSCR = "SCIONGEN"
  68. scrname = "CON:0//639//Scion Output/AUTO/SCREEN"
  69.  
  70. sxlen = 3;  /* the default length of the soundex-code is 3,
  71.          * but if you insist, you can use a longer code
  72.          */
  73. NL = '0A'x
  74.  
  75. signal on IOERR
  76.  
  77. do while srchstr = '?'
  78.   writeln(stdout, "SEARCHNAME/A,OUTFILE/A,QUIET/S,NOREQ/S ")
  79.   pull srchstr outname outval
  80. end
  81.  
  82. /* read preferences file */
  83.  
  84. if open(pfile, 'ENV:Scion/ScionRexx.prefs', 'r') then do
  85.   do while ~eof(pfile)
  86.     inln = readln(pfile)
  87.     if inln ~= "" then do
  88.       wstr = upper(word(inln, 1))
  89.       if wstr = "USEREQ" then
  90.         usereq = 1
  91.       else if wstr = "NOUSEREQ" then
  92.         usereq = 0
  93.       else if wstr = "PUBSCREEN" then
  94.         PSCR = strip(delstr(inln, 1, length(wstr)), 'b', ' "')
  95.       else if wstr = "LINEWIDTH" then do
  96.         wstr = word(inln, 2)
  97.         if datatype(wstr, 'w') then plwidth = wstr
  98.       end
  99.     end
  100.   end
  101.   close(pfile)
  102. end
  103.  
  104. if pscr = "" | (pscr ~= "WORKBENCH" & ~show('p', pscr)) then
  105.   pscr = "SCIONGEN"
  106. scrname = scrname||pscr
  107.  
  108. /* Command line options get priority over global settings */
  109.  
  110. if srchstr ~= "" then do
  111.   if srchstr = "QUIET" | srchstr = "NOREQ" then do
  112.     outval = srchstr; srchstr = ""
  113.   end
  114. end
  115.  
  116. if outval = "QUIET" then do
  117.   outp = 0; usereq = 0
  118. end
  119. else if outval = "NOREQ" then usereq = 0
  120.  
  121. if ~show('l','rexxarplib.library') then do
  122.   if exists('libs:rexxarplib.library') then
  123.     call addlib('rexxarplib.library',0,-30,0)
  124. end
  125.  
  126. screentofront(pscr)
  127.  
  128. if usereq & ~show('l','rexxreqtools.library') then do
  129.   if exists('libs:rexxreqtools.library') then
  130.     call addlib('rexxreqtools.library',0,-30,0)
  131.   else do
  132.     usereq = 0; outp = 1
  133.     Tell("Unable to open rexxreqtools.library - using text output")
  134.   end
  135. end
  136.  
  137. /* Originally stolen from Peter Billing - thanks Peter ;-) */
  138. if ~show('P','SCIONGEN') then do
  139.   EndString('I am sorry to say that the SCION Genealogist' || NL ||,
  140.     'database is not available. Please start the' || NL ||,
  141.     'SCION program BEFORE using this script!')
  142. end
  143.  
  144. /* Printer Codes (some of which are currently unused): */
  145. ESC = '1B'x
  146. prtinit = ESC||"#1";     /* ESC#1 initialize      */
  147. prtundon = ESC||"[4m";   /* ESC[4m underline on   */
  148. prtundoff = ESC||"[24m"; /* ESC[24m underline off */
  149. prtdson = ESC||"[1m";    /* ESC[1m boldface on    */
  150. prtdsoff = ESC||"[22m";  /* ESC[22m boldface off  */
  151. prtnlqon = ESC||"[2"||'22'x||"z";  /* ESC[2"z NLQ on  */
  152. prtnlqoff = ESC||"[1"||'22'x||"z"; /* ESC[1"z NLQ off */
  153.  
  154. MyPort = "SCIONGEN"
  155. Address value MyPort
  156. GETDBNAME
  157. dbname = upper(RESULT)
  158.  
  159. if outp & ~usereq then do
  160.   if pscr ~= "WORKBENCH" then do
  161.     scrdev = 'SCNSDXSCR'
  162.     if ~open(scrdev, scrname, 'w') then scrdev = stdout
  163.   end
  164.   Tell("Scion SOUNDEX script v"||versionstr||" by Freddy Ariës")
  165.   Tell("Database: "||dbname|| NL)
  166. end
  167.  
  168. if srchstr = '' then do
  169.   if usereq then do
  170.     srchname = rtgetstring(,'Enter the surname to search for: '||,
  171.             NL,'Input Request:','_Continue','rt_pubscrname = '||PSCR)
  172.     if srchname = '' then EXIT
  173.   end
  174.   else do
  175.     TellNN("Enter the surname to search for: ")
  176.     srchname = readln(scrdev)
  177.   end
  178.   srchname = upper(srchname)
  179. end
  180. else do
  181.   srchname = upper(srchstr)
  182. end
  183.  
  184. if usereq then do
  185.   if outname = "" then do
  186.     odev = rtezrequest('Current Scion database: '||dbname||,
  187.       NL||'Where should the output be sent to?'||,
  188.       NL,' _File |_Printer|_Screen|_Nowhere','Scion SOUNDEX script v'||versionstr||' by Freddy Ariës','rt_pubscrname = '||PSCR)
  189.     select
  190.       when odev = 1 then do
  191.         /* We need a file requester for further data */
  192.         dblen = length(dbname)
  193.         if dblen>6 & right(dbname, 6)=".SCION" then
  194.           dbname=left(dbname, dblen - 6)
  195.         outname = rtfilerequest(,dbname||'.SDX','Output filename',,'rtfi_buffer = true   rt_pubscrname = '||PSCR||'   rtfi_initialpath = RAM:',)
  196.         if outname = '' then
  197.           outname = dbname||'.SDX'
  198.       end
  199.       when odev = 2 then
  200.         outname = 'PRT:'
  201.       when odev = 3 then
  202.         outname = 'STDOUT'
  203.       otherwise
  204.         EXIT
  205.         /* You selected 'Nowhere' */
  206.     end
  207.   end
  208.  
  209.   useirn = rtezrequest('Do you want to output the IRNs'||,
  210.             NL||'(the record numbers) as well?'||,
  211.             '',' _Yes| _No ','Input Request:','rt_pubscrname = '||PSCR)
  212. end
  213. else do
  214.   if outname = "" then do
  215.     Tell("Enter output file (filename with complete path, or PRT: for printer,")
  216.     TellNN("or STDOUT for screen): ")
  217.     outname = readln(scrdev)
  218.     outname = strip(outname, 'b', ' "')
  219.     if outname = "" then outname = "STDOUT"
  220.   end
  221.  
  222.   TellNN("Do you want to output the IRNs (numbers) as well (y/n)? ")
  223.   instr = readln(scrdev)
  224.   instr = upper(left(instr, 1))
  225.   Tell("")
  226.   if instr = "Y" then useirn = 1
  227.   else useirn = 0
  228. end
  229.  
  230. /* convert the entered string to a SOUNDEX search pattern */
  231. spat = GetSoundex(srchname)
  232. if spat = 'A' then do
  233.   EndString("Unable to create soundex code for name string!")
  234. end
  235.  
  236. /* Make a list of all the people in the database whose surname matches
  237.  * the given lastname (ie. matching soundex codes)
  238.  */
  239.  
  240. OpenPrinter()
  241.  
  242. GETTOTALIRN
  243. TotalIRN = RESULT
  244. do i = 1 to TotalIRN
  245.   EXISTPERSON i
  246.   if RESULT = 'YES' then
  247.   do
  248.     GETLASTNAME i
  249.     lname = upper(RESULT)
  250.     ccode = GetSoundex(lname)
  251.     if ccode = spat then do
  252.       /* Found a match - output the name */
  253.       GETFIRSTNAME i
  254.       fnames = RESULT
  255.       if useirn then
  256.     oline = left(i||".     ",6)
  257.       else
  258.         oline = ""
  259.       oline = oline||lname||", "||fnames
  260.       writeln(prtdev, oline)
  261.     end
  262.   end
  263. end
  264.  
  265. writeln(prtdev, prtnlqoff); /* ESC[1"z NLQ off */
  266.  
  267. EndString("Done.")
  268. EXIT
  269.  
  270. /* Some special purpose routines for Soundex */
  271.  
  272. GetSoundex: PROCEDURE EXPOSE sxlen
  273. parse arg nstr
  274.   found = 0
  275.   wstr = upper(nstr)
  276.  
  277.   ix = 1; wix = 0; wval = 0
  278.   wlen = length(wstr)
  279.   code = 'A';
  280.  
  281.   /* Find first letter from the string */
  282.   do while ~found & (wix < wlen)
  283.     wix = wix + 1
  284.     c = substr(wstr,wix,1)
  285.     if c >= 'A' & c <= 'Z' then do
  286.       found = 1
  287.       code = c
  288.     end
  289.     else if c = ',' then wix = wlen
  290.     /* Everything after a comma is skipped - for now.
  291.      * The assumption is made that everything after a comma is prefixes.
  292.      * eg. Von Hoesen can be stored as "Von Hoesen", or as "Hoesen, Von"
  293.      * In the first case, it will become "V525", in the 2nd "H250"
  294.      */
  295.   end
  296.   if ~found then return code
  297.   pv = GetValue(code)
  298.  
  299.   /* Append a 3-digit (sxlen-size) code to the letter */
  300.   do while ix <= sxlen & wix < wlen
  301.     wix = wix + 1
  302.     wval = GetValue(substr(wstr,wix,1))
  303.     if wval > 0 & wval ~= pv then do
  304.       code = code||wval
  305.       pv = wval
  306.       ix = ix + 1
  307.     end
  308.     else if wval ~= pv then pv = ''
  309.   end
  310.  
  311.   do while ix <= sxlen
  312.     code = code||"0"
  313.     ix = ix + 1
  314.   end
  315. return code
  316.  
  317. GetValue: PROCEDURE
  318. parse arg c
  319.   if c = 'B' | c = 'F' | c = 'P' | c = 'V' then return 1
  320.   if c = 'C' | c = 'G' | c = 'J' | c = 'K' | c = 'Q' | c = 'S' | c = 'X' | c = 'Z' then return 2
  321.   if c = 'D' | c = 'T' then return 3
  322.   if c = 'L' then return 4
  323.   if c = 'M' | c = 'N' then return 5
  324.   if c = 'R' then return 6
  325.  
  326. return 0
  327.  
  328. /* General purpose requesters */
  329.  
  330. OpenPrinter:
  331. /* Open the printer device and print out a nice header */
  332. if outname = "STDOUT" then
  333.   prtdev = scrdev
  334. else do
  335.   prtdev = 'PRINTER'
  336.   if ~open(prtdev, outname, 'w') then
  337.     EndString("ERROR: Failed to open output file!")
  338. end
  339. writeln(prtdev, prtinit||prtnlqon)
  340. prtstr = prtundon||prtdson||"SOUNDEX listing for "||srchname||" (Soundex code: "||spat||")"||prtdsoff||prtundoff
  341. writeln(prtdev, prtstr)
  342. prtstr = prtdson||"Report printed on: "||date()||"        "||"database: "||dbname||prtdsoff
  343. writeln(prtdev, prtstr)
  344. prtstr = copies('=', plwidth)
  345. writeln(prtdev, prtstr)
  346. return 0
  347.  
  348. Tell: PROCEDURE EXPOSE outp scrdev
  349. parse arg str
  350. if outp then
  351.   writeln(scrdev, str)
  352. return 0
  353.  
  354. TellNN: PROCEDURE EXPOSE outp scrdev
  355. parse arg str
  356. if outp then
  357.   writech(scrdev, str)
  358. return 0
  359.  
  360. EndString: PROCEDURE EXPOSE outp prtdev usereq scrdev pscr
  361. parse arg str
  362. /* If you turned off stdout, no error messages will be shown! */
  363. if usereq then
  364.   rtezrequest(str,'E_xit','Soundex Message:','rt_pubscrname = '||PSCR)
  365. else do
  366.   Tell(str || '0A'x)
  367. end
  368. if outp & ~usereq & (scrdev ~= stdout) then do
  369.   Tell("Press <return> to exit.")
  370.   readln(scrdev)
  371.   close(scrdev)
  372. end
  373. close(prtdev)
  374. EXIT
  375.  
  376. /* Let's make sure you get a nice message when you turn off the printer :-) */
  377.  
  378. IOERR:
  379. bline = SIGL
  380. say "I/O error #"||RC||" detected in line "||bline||":"
  381. say sourceline(bline)
  382. EXIT
  383.