home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 8 / FreshFishVol8-CD1.bin / new / biz / dbase / genealogist / arexx / gedcom2scion.rexx < prev    next >
OS/2 REXX Batch file  |  1994-05-21  |  21KB  |  730 lines

  1. /****************************************************************************
  2.  *                                                                          *
  3.  *                                                                          *
  4.  * $VER: GEDCOM2Scion.rexx 1.08 (1 Mar 1994)
  5.  *                                                                          *
  6.  *                      Written by Freddy Ariës                             *
  7.  *                                                                          *
  8.  * This program was created to import GEDCOM data into the Scion database.  *
  9.  * It is still very basic and not user-friendly at all.                     *
  10.  * I assume it will only be able to parse the most basic GEDCOM files, and  *
  11.  * I can't even guarantee that it will handle these correctly...            *
  12.  *                                                                          *
  13.  * Even though this script does no parsing of dates, it's safer if they are *
  14.  * in the exact format "DD MMM YYYY".                                       *
  15.  * All unrecognized fields or fields that Scion doesn't use, are skipped.   *
  16.  * The database must be running for this AREXX script to work.              *
  17.  * NOTE: The program generates a file DATABASE.err (where DATABASE is the   *
  18.  *  name of the current Scion database), containing parsing info about      *
  19.  *  which lines were skipped and which non-fatal errors were encountered.   *
  20.  *  It may be a good idea to read this file!                                *
  21.  *                                                                          *
  22.  * TO DO:                                                                   *
  23.  *  - Better solution for the user-defined PERSONAL and FAMILY fields       *
  24.  *    (PERSUSER1, PERSUSER2, PERSUSER3, FAMUSER1, FAMUSER2)                 *
  25.  *    Current solution: assume defaults                                     *
  26.  *  - Better parsing of dates                                               *
  27.  *    Recognition and use of ABT, BEF, AFT notations                        *
  28.  *                                                                          *
  29.  ****************************************************************************/
  30.  
  31. options failat 20; options results
  32. arg inname inval
  33.  
  34. versionstr = "1.08"
  35. outp = 1; usereq = 1; output = stdout
  36. NL = '0A'x
  37.  
  38. signal on IOERR
  39.  
  40. /* parse command line options, to enable calling the script automatically,
  41.  * eg. from a function key
  42.  */
  43.  
  44. do while inname = '?'
  45.   writeln(stdout, "INFILE/A,QUIET/S,NOREQ/S ")
  46.   pull inname inval
  47. end
  48.  
  49. if inname ~= "" then do
  50.   if inname = "QUIET" | inname = "NOREQ" then do
  51.     inval = inname; inname = ""
  52.   end
  53. end
  54.  
  55. if inval = "QUIET" then do
  56.   outp = 0; usereq = 0
  57. end
  58. else if inval = "NOREQ" then usereq = 0
  59.  
  60. if usereq & ~show('l','rexxreqtools.library') then do
  61.   if exists('libs:rexxreqtools.library') then
  62.     call addlib('rexxreqtools.library',0,-30,0)
  63.   else do
  64.     usereq = 0; outp = 1
  65.     Tell("Unable to open rexxreqtools.library - using text output")
  66.   end
  67. end
  68.  
  69.  
  70. /* These first few lines are stolen from Peter Billings - thanks Peter ;-) */
  71. if ~show('P','SCIONGEN') then do
  72.   TermError('I am sorry to say that the SCION Genealogist' || NL ||,
  73.     'database is not available. Please start the' || NL ||,
  74.     'SCION program BEFORE using this script!')
  75. end
  76.  
  77. myport = "SCIONGEN"
  78. address value myport
  79. GETDBNAME
  80. dbname = upper(RESULT)
  81.  
  82. if outp & ~usereq then do
  83.   Tell("GEDCOM to Scion conversion script v"||versionstr||" by Freddy Ariës")
  84.   Tell("Scion (output) database: "||dbname)
  85. end
  86.  
  87. if inname = "" then do
  88.   /* ignore the value of outp; if we can't ask for the input file,
  89.    * we can't do anything!
  90.    */
  91.   if usereq then do
  92.     /* We need a file requester for further data */
  93.     inname = rtfilerequest('RAM:',,"GEDCOM Input File")
  94.   end
  95.   else do
  96.     Tell("Please enter the filename (with complete path) of the GEDCOM file:")
  97.     TellNN("Input file: ")
  98.     pull inname
  99.   end    
  100.   if inname = '' then
  101.     TermError("ERROR: No Input File!")
  102. end
  103.   
  104. if ~open(infile, inname, "r") then
  105.   TermError("ERROR: Input file '"inname"' not found!")
  106.  
  107. if ~open(errfile, dbname||".err", "w") then
  108.   errfile = stdout
  109.  
  110. if ~usereq then
  111.   Tell("Be patient - this may take a while...")
  112.  
  113. /* Initialize line count, individual counter and family counter */
  114. ink = GetNextLine()
  115. if left(ink, 6) ~= "0 HEAD" then do
  116.   close(infile)
  117.   TermError("ERROR: Invalid beginning of file - not a valid GEDCOM format")
  118. end
  119.  
  120. lvlstr = '0'; lvl = 1; atlvl = 1
  121. IRNArr. = 0; FGRNArr. = 0
  122.  
  123. /* Read the "HEAD" section until we find something else of level "0" */
  124.  
  125. prstot = ""
  126. ink = ParseHeader(atlvl)
  127. GETPROGVERSION
  128. prsr = RESULT
  129. prsr = "Destination:   Scion Genealogist "||prsr
  130. if ~usereq then
  131.   Tell(prsr)
  132. else
  133.   prstot = prstot||prsr||NL
  134. prsr = "Dest. file:    "||dbname
  135. if ~usereq then
  136.   Tell(prsr)
  137. else do
  138.   prstot=prstot||prsr||NL||NL||"Parsing will take a while - be patient."||,
  139.     NL||"Click to start parsing..."
  140.   rtezrequest(prstot,'_Continue','Converter Message:')
  141. end
  142.  
  143. /* Now scan the following level "0" fields for individuals;
  144.  * skip the families, for the moment
  145.  */
  146.  
  147. irn = 0
  148.  
  149. replay = 0
  150. do while ~eof(infile)
  151.   lvlstr = word(ink, 1)
  152.   lvl = GetNumType(lvlstr)
  153.  
  154.   if lvl = atlvl then do
  155.     tagstr = upper(word(ink, words(ink)))
  156.     if tagstr = "INDI" then do
  157.       nstr = strip(word(ink, 2),'B','@'||xrange('A','Z'))
  158.       if DATATYPE(nstr) = 'NUM' then do
  159.         tp = GGetIRN(nstr)
  160.         if tp ~= 0 then
  161.           writeln(errfile, "ERROR: Duplicate person encountered: "||nstr||" (IRN "||tp||")")
  162.         irn = irn + 1
  163.         ink = ParsePerson(nstr, lvl)
  164.         if ink ~= "" then replay = 1
  165.       end
  166.       else TermError("ERROR: Cannot determine the Individual Record Number!")
  167.     end
  168.   end
  169.   /* Skip all lines with level ~= current level (0) */
  170.   if replay = 0 then ink = GetNextLine()
  171.   else replay = 0
  172. end
  173.  
  174. if ~usereq then do
  175.   Tell("Number of persons parsed: "||irn)
  176.   GETTOTALIRN
  177.   tot = RESULT
  178.   Tell("Total number of persons in the Scion database: "||tot)
  179. end
  180.  
  181. /* Now rescan the entire file for families; I know it is quite
  182.  * inefficient this way, but it's better to add all the persons first,
  183.  * and then establish the relations...
  184.  */
  185.  
  186. close(infile)
  187. if ~open(infile, inname, "r") then
  188.   TermError("ERROR: Unable to read relations!")
  189.  
  190. if ~usereq then
  191.   Tell("Scanning file again to establish relations...")
  192.  
  193. lvlstr = '0'; lvl = 1; atlvl = 1
  194. fgrn = 0
  195.  
  196. replay = 0
  197. do while ~eof(infile)
  198.   if replay = 0 then ink = GetNextLine()
  199.   else replay = 0
  200.  
  201.   lvlstr = word(ink, 1)
  202.   lvl = GetNumType(lvlstr)
  203.  
  204.   if lvl = atlvl then do
  205.     tagstr = upper(word(ink, words(ink)))
  206.     if tagstr = "FAM" then do
  207.       nstr = strip(word(ink, 2),'B','@'||xrange('A','Z'))
  208.       if DATATYPE(nstr) = 'NUM' then do
  209.         fp = GGetFGRN(nstr)
  210.         if fp ~= 0 then
  211.           writeln(errfile, "ERROR: Duplicate family encountered: "||nstr||" (FGRN "||fp||")")
  212.         fgrn = fgrn + 1
  213.         ink = ParseFamily(nstr, lvl)
  214.         if ink ~= "" then replay = 1
  215.       end
  216.       else TermError("ERROR: Cannot determine the Family Group Record Number!")
  217.     end
  218.     else if tagstr = "TRLR" then do
  219.       close(infile)
  220.       GETTOTALFGRN
  221.       ftot = RESULT
  222.       if usereq then do
  223.     GETTOTALIRN
  224.     itot = RESULT
  225.         TermError("PARSING DONE:"||NL||"Number of persons parsed: "||irn||,
  226.       NL||"Total number of persons in the Scion database: "||itot||,
  227.           NL||"Number of families parsed: "||fgrn||,
  228.       NL||"Total number of families in the Scion database: "||ftot||,
  229.       NL||NL||"DON'T FORGET TO SAVE YOUR SCION FILE!!!")
  230.       end
  231.       else do
  232.     Tell("Number of families parsed: "||fgrn)
  233.     Tell("Total number of families in the Scion database: "||ftot)
  234.         TermError("DONE! DON'T FORGET TO SAVE YOUR SCION FILE!!!")
  235.       end
  236.     end
  237.   end
  238.   /* Skip all the fields at lvl ~= this level */
  239. end
  240. close(infile)
  241. if ink ~= "0 TRLR" then
  242.   TermError("ERROR: Unexpected end of file")
  243. else
  244.   TermError("ERROR: Trailer not recognized!")
  245.  
  246. ParseHeader: PROCEDURE EXPOSE infile prstot NL outp usereq
  247. parse arg inilvl
  248. do while ~eof(infile)
  249.   ins = GetNextLine()
  250.   if ins = "" then
  251.     TermError("ERROR: Unexpected end of file")
  252.   lvlstr = word(ins, 1)