home *** CD-ROM | disk | FTP | other *** search
/ Inside Multimedia 1995 February / IMM0295.ISO / share / os2 / albatros / albatros.@ / STEALTXT.CMD < prev   
Encoding:
Text File  |  1994-04-26  |  22.3 KB  |  609 lines

  1. /*╔════════════════════════════════════════════════════════════════════╗
  2.   ║                                                                    ║
  3.   ║   Program : StealTXT.CMD                                           ║
  4.   ║                                                                    ║
  5.   ║   Purpose : Add On for Albatros CD Player to "steal" the INI       ║
  6.   ║             Entries of the following CD Player                     ║
  7.   ║                                                                    ║
  8.   ║                                                                    ║
  9.   ║            - Michael Bock CDPLAYER                                 ║
  10.   ║                                                                    ║
  11.   ║            - CD EXPLORER ( IBM EWS, tested with Version 2.3 )      ║
  12.   ║                                                                    ║
  13.   ║            - Albatros CD Player ( Hey, Mine ? )                    ║
  14.   ║                                                                    ║
  15.   ║                                                                    ║
  16.   ║            And to convert into the ALBATROS Format                 ║
  17.   ║                                                                    ║
  18.   ║                                                                    ║
  19.   ║                                                                    ║
  20.   ║   Autor : Norbert Heller (c) 1994                                  ║
  21.   ║                                                                    ║
  22.   ║                                                                    ║
  23.   ║                                                                    ║
  24.   ║                                                                    ║
  25.   ║   Usage : StealTXT /x INIFILE                                      ║
  26.   ║                                                                    ║
  27.   ║                                                                    ║
  28.   ║   /x : Switch where                                                ║
  29.   ║                                                                    ║
  30.   ║         /A : Source is from Albatros                               ║
  31.   ║         /C : Source is from Michael Bocks CDPLAYER                 ║
  32.   ║         /E : Source is from IBM CD Explorer                        ║
  33.   ║                                                                    ║
  34.   ║   Example : StealTXT /C CDPLAYER.INI                               ║
  35.   ║                                                                    ║
  36.   ║   StealTXT will then produce a backup TXT file named CDPLAYER.TX0  ║
  37.   ║                                                                    ║
  38.   ║                                                                    ║
  39.   ║                                                                    ║
  40.   ║   Based on the file SHOWINI.CMD by RONY G. Flatscher               ║
  41.   ║   Though my conversion is probably not the very best :-))          ║
  42.   ║                                                                    ║
  43.   ╚════════════════════════════════════════════════════════════════════╝*/
  44.  
  45.  
  46. SIGNAL ON HALT
  47. SIGNAL ON ERROR
  48.  
  49. global. = ""                    /* default to empty string */
  50.  
  51. PARSE SOURCE . . name_path      /* get full name & path of this program */
  52.  
  53. CALL initialize                 /* initialize array "global."           */
  54.  
  55. IF ARG(1) <> "" THEN         /* arguments are given */
  56.    CALL backup_restore_update ARG(1)
  57.  
  58. IF ARG(1) = "" THEN SIGNAL usage    /* No Arguments -> Show Usage */
  59.  
  60. EXIT 0                          /* normal exit */
  61.  
  62.  
  63.  
  64. /************************************************************/
  65.  
  66. INITIALIZE: PROCEDURE EXPOSE global.
  67.     /* check whether RxFuncs are loaded, if not, load them */
  68.     IF RxFuncQuery('SysLoadFuncs') THEN
  69.     DO
  70.         /* load the load-function */
  71.         CALL RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs'       
  72.  
  73.         /* load the Sys* utilities */
  74.         CALL SysLoadFuncs                                                 
  75.     END
  76.  
  77.  
  78.     global.iNonPrintable = XRANGE("00"x, "1F"x) || D2C(255)
  79.     global.iFilter       = COPIES("FA"x, 256)
  80.     global.iFiletype     = "";
  81.  
  82.  
  83.     RETURN
  84.  
  85.  
  86.  
  87.  
  88.  
  89. /* 
  90.    one of Knuth's algorithms to sort
  91.    ARG(1) ... stemname of array to sort
  92.    ARG(2) ... optional, if given, exact comparison (no forced uppercase), taking leading
  93.               and trailing blanks into account
  94. */
  95. SORT_GENERIC: PROCEDURE EXPOSE stemIni. stemTopLevel. stemKey. stemTargetTopLevel. stemTargetKey. 
  96.  
  97.    /* define M for passes, build REXX-code */
  98.    dynCode = "M = 1; DO WHILE (9 * M + 4) <" ARG(1) || ".0 ; M = M * 3 + 1; END"
  99.    INTERPRET dynCode                /* execute REXX-code in variable dynCode */
  100.  
  101.    /* sort stem, build REXX-code */
  102.    dynCode = "DO WHILE M > 0; K = " ARG(1) || ".0 - M; DO J = 1 TO K; Q = J;"
  103.    dynCode = dynCode "DO WHILE Q > 0; L = Q + M;"
  104.  
  105.    IF ARG() < 2 THEN    /* uppercase comparison, ignore leading and trailing blanks */
  106.       dynCode = dynCode "IF TRANSLATE(" || ARG(1) || ".Q) <= TRANSLATE(" || ARG(1) || ".L) THEN LEAVE;"
  107.    ELSE                 /* exact comparison */ 
  108.       dynCode = dynCode "IF" ARG(1) || ".Q <<=" ARG(1) || ".L THEN LEAVE;"
  109.  
  110.    dynCode = dynCode "tmp =" ARG(1) || ".Q; tmp.origValue =" ARG(1) || ".Q.origValue;"
  111.    dynCode = dynCode "tmp.type =" ARG(1) || ".Q.type; tmp.filterValue =" ARG(1) || ".Q.filterValue;"
  112.  
  113.    dynCode = dynCode ARG(1) || ".Q =" ARG(1) || ".L;" ARG(1) || ".Q.origValue =" ARG(1) || ".L.origValue;"
  114.    dynCode = dynCode ARG(1) || ".Q.type =" ARG(1) || ".L.type;" ARG(1) || ".Q.filterValue =" ARG(1) || ".L.filterValue;"
  115.  
  116.    dynCode = dynCode ARG(1) || ".L = tmp;" ARG(1) || ".L.origValue = tmp.origValue;"
  117.    dynCode = dynCode ARG(1) || ".L.type = tmp.type;" ARG(1) || ".L.filterValue  = tmp.filterValue;"
  118.  
  119.    dynCode = dynCode "Q = Q - M; END; END; M = M % 3; END"
  120.  
  121.    INTERPRET dynCode                /* execute REXX-code in variable dynCode */
  122.  
  123.    RETURN
  124.  
  125.  
  126.  
  127. /*
  128.         read TopLevel-entries
  129. */
  130. READ_TOPLEVEL: PROCEDURE EXPOSE stemIni. stemTopLevel. stemKey. global. 
  131.     DROP stemTopLevel.
  132.     stemTopLevel. = ""
  133.  
  134.     iIni = ARG(1)
  135.     ok = SysIni(stemIni.iIni, 'ALL:', 'stemTopLevel')
  136.     IF ok = "ERROR:" THEN
  137.     DO
  138.        stemTopLevel.0 = 0
  139.     END
  140.     ELSE
  141.     DO i = 1 TO stemTopLevel.0
  142.        CALL check_value stemTopLevel.i  /* determine and prepare value in hand */
  143.        stemTopLevel.i.origValue   = stemTopLevel.i
  144.        stemTopLevel.i             = strings.displayValue
  145.        stemTopLevel.i.type        = strings.type
  146.        stemTopLevel.i.filterValue = strings.filterValue
  147.     END
  148.  
  149.     RETURN 
  150.  
  151.  
  152.  
  153. /*
  154.         read KEY-entries
  155. */
  156. READ_KEY: PROCEDURE EXPOSE stemIni. stemTopLevel. stemKey. global. strings. 
  157.     DROP stemKey.
  158.     stemKey. = ""
  159.  
  160.     iIni     = ARG(1)
  161.     iTopL    = ARG(2)
  162.  
  163.     ok = SysIni(stemIni.iIni, stemTopLevel.iTopL.origValue, 'ALL:', 'stemKey')
  164.     IF ok = "ERROR:" THEN
  165.     DO
  166.        stemKey.0 = 0
  167.     END
  168.     ELSE
  169.     DO i = 1 TO stemKey.0
  170.        CALL check_value stemKey.i  /* determine and prepare value in hand */
  171.        stemKey.i.origValue   = stemKey.i
  172.        stemKey.i             = strings.displayValue
  173.        stemKey.i.type        = strings.type
  174.        stemKey.i.filterValue = strings.filterValue
  175.     END
  176.  
  177.     RETURN 
  178.  
  179.  
  180.  
  181. /* 
  182.    check data-type of argument and set up a structure containing different representations
  183.    of it
  184. */
  185. CHECK_VALUE: PROCEDURE EXPOSE global. strings. 
  186.    DROP strings.
  187.    strings. = ""
  188.  
  189.    length_arg1 = LENGTH(ARG(1))         /* length of ARG(1) */
  190.  
  191.    IF length_arg1 = 0 THEN              /* unknown key-value, key-value not set. */
  192.    DO
  193.       strings.type = "H"
  194.       strings.displayValue = "x''"
  195.       strings.filterValue = ""
  196.       RETURN
  197.    END
  198.  
  199.    /* last character \0 ? */
  200.  
  201.    IF SUBSTR(ARG(1), length_arg1, 1) = "00"x THEN    /* ASCIIZ ? */
  202.    DO
  203.       work = SUBSTR(ARG(1), 1, length_arg1 - 1)
  204.       asciiz = "0"
  205.    END
  206.    ELSE                                                 
  207.    DO
  208.       work = ARG(1)
  209.       asciiz = ""
  210.    END
  211.  
  212.    ascii = (VERIFY(work, global.iNonPrintable, "Match") = 0)    /* plain ASCII ? */
  213.  
  214.    IF ascii THEN                                        /* ASCII-type value in hand */
  215.    DO
  216.       IF asciiz = "0" THEN strings.type = "A0"
  217.                       ELSE strings.type = "A"
  218.       strings.displayValue = work
  219.    END
  220.    ELSE                                                 /* hexadecimal value in hand */
  221.    DO
  222.       strings.type = "H"
  223.       strings.displayValue = "x'" || C2X(ARG(1)) || "'"
  224.       strings.filterValue = TRANSLATE(ARG(1), global.iFilter, global.iNonPrintable)
  225.    END
  226.    RETURN
  227.  
  228.  
  229.  
  230.  
  231. /***************************************************************************/
  232. /*
  233.     print to file
  234. */
  235. PRINT: PROCEDURE EXPOSE global. strings. stemIni. stemTopLevel. stemKey. 
  236.     iIni  = ARG(1)      /* INI-file to be printed */
  237.     iTopL = ARG(2)      /* TopLevel to be printed */
  238.     iKey  = ARG(3)      /* Key to be printed */
  239.  
  240.  
  241.     DO
  242.               i = iIni
  243.  
  244.                CALL sort_generic "stemTopLevel"         /* sort them */
  245.                                                        
  246.                DO j = 1 TO stemTopLevel.0              
  247.  
  248.                   IF POS(global.config.showDepth, "KV") > 0 THEN    /* show more than TopLevel ? */
  249.                   DO
  250.                      CALL read_key i, j                   /* read keys */
  251.                      CALL sort_generic "stemKey"    /* sort them */
  252.  
  253.  
  254.  
  255.                SELECT
  256.  
  257.                   WHEN     global.iFiletype     = "E" THEN
  258.                   DO
  259.  
  260.                      /* Fuer die Eintraege des CD EXPLORER */
  261.                      /*
  262.  
  263.                         Beim CD Explorer sind die eintraege anders : alles steht unter einem
  264.                         Key eintrag als value mit <RETURN> getrennt
  265.  
  266.                      */
  267.  
  268.                      DO k = 1 TO stemKey.0            /* k = Variable fuer key name */
  269.  
  270.                         IF POS(global.config.showDepth, "V") > 0 THEN      /* show key-values too ? */
  271.                         DO
  272.  
  273.                            SAY "Track"||k
  274.                            val = SysIni(stemIni.i, stemTopLevel.j.origValue, stemKey.i.origValue)
  275.  
  276.                            IF val = "ERROR:" THEN
  277.                            DO
  278.                               LEAVE    /* schleife verlassen */
  279.                            END
  280.                            ELSE
  281.                               DO
  282.                                  CALL LINEOUT global.outFile, val /* write value to file */
  283.                                  /* CALL LINEOUT global.outFile, "#"  write separator   */
  284.                               END
  285.                         END
  286.                      END
  287.                   END      /* CDEXPLORER CD Player */
  288.  
  289.  
  290.                   WHEN     global.iFiletype     = "C" THEN
  291.                   DO
  292.  
  293.                      /* Fuer die Eintraege des Michael Bock CD Player */
  294.  
  295.                      val = SysIni(stemIni.i, stemTopLevel.j.origValue, "CDTitle")
  296.                      CALL LINEOUT global.outFile, val /* write Value to File */
  297.  
  298.                      DO k = 1 TO stemKey.0            /* k = Variable fuer key name */
  299.  
  300.                         IF POS(global.config.showDepth, "V") > 0 THEN      /* show key-values too ? */
  301.                         DO
  302.  
  303.                            SAY "Track"||k
  304.                            val = SysIni(stemIni.i, stemTopLevel.j.origValue, 'Track'||k)
  305.  
  306.                            IF val = "ERROR:" THEN
  307.                            DO
  308.                               LEAVE    /* schleife verlassen */
  309.                            END
  310.                            ELSE
  311.                               DO
  312.                                  CALL LINEOUT global.outFile, val /* write value to file */
  313.                                  CALL LINEOUT global.outFile, "#" /* write separator   */
  314.                              END
  315.                         END
  316.                      END
  317.                   END      /* When Bock CD Player */
  318.  
  319.  
  320.  
  321.                   WHEN global.iFiletype     = "A" THEN
  322.                   DO
  323.  
  324.                      /* Fuer die Eintraege des Albatros CD Player */
  325.  
  326.                      val = SysIni(stemIni.i, stemTopLevel.j.origValue, "CD-Titel")
  327.                      CALL LINEOUT global.outFile, val /* write Value to File */
  328.  
  329.                      DO k = 1 TO stemKey.0            /* k = Variable fuer key name */
  330.  
  331.                         IF POS(global.config.showDepth, "V") > 0 THEN      /* show key-values too ? */
  332.                         DO
  333.  
  334.                            SAY "Track"||k
  335.                            val = SysIni(stemIni.i, stemTopLevel.j.origValue, 'TITEL'||k)
  336.  
  337.                            IF val = "ERROR:" THEN
  338.                            DO
  339.                               LEAVE    /* schleife verlassen */
  340.                            END
  341.                            ELSE
  342.                               DO
  343.                                  CALL LINEOUT global.outFile, val /* write value to file */
  344.  
  345.                          /* noch schauen ob Interpret angegeben worden ist */
  346.                                     val = SysIni(stemIni.i, stemTopLevel.j.origValue, 'INTERPRET'||k)
  347.                                     IF LENGTH(val) > 2 THEN
  348.                                        IF val = "ERROR:"  THEN
  349.                                           CALL LINEOUT global.outFile, "#" /* write separator   */
  350.                                        ELSE
  351.                                           CALL LINEOUT global.outFile, val /* write value */
  352.                                     ELSE
  353.                                         CALL LINEOUT global.outFile, "#" /* write separator   */
  354.                                     END
  355.                               END
  356.                         END
  357.                      END
  358.                  /* END      When ALBATROS CD Player */
  359.  
  360.           OTHERWISE NOP
  361.           END
  362.  
  363.                      SAY
  364.                      SAY   ' ******  Processing Next Entry ****** '
  365.                      SAY
  366.  
  367.                      CALL LINEOUT global.outFile, ""    /* write empty line */
  368.                      CALL LINEOUT global.outFile, ""    /* write empty line */
  369.                      CALL LINEOUT global.outFile, ""    /* write empty line */
  370.                   END
  371.                END
  372.             END
  373.     SAY
  374.     CALL STREAM global.outFile, "C", "CLOSE"            /* close output file */
  375.  
  376.     RETURN
  377.  
  378.  
  379.  
  380.  
  381. HALT:
  382.    IF global.outFile <> "" THEN         /* interrupted while writing to file */
  383.    DO
  384.       CALL STREAM global.outFile, "C", "CLOSE"  /* close file */
  385.    END
  386.  
  387.  
  388.    SAY 
  389.    SAY   "User interrupted application."
  390.    EXIT -1                              /* user interrupt       */
  391.  
  392.  
  393.  
  394.  
  395. /* ********************** ********************** *********************** ****************** */
  396.  
  397. BACKUP_RESTORE_UPDATE: PROCEDURE EXPOSE global. 
  398.  
  399. command_line = ARG(1)
  400.  
  401. IF command_line = "?" |  TRANSLATE(command_line) = "H" THEN SIGNAL usage
  402.  
  403. /* PARSE ARG filename */
  404.  
  405. PARSE ARG WITH '/'switch filename 
  406.  
  407. /* defaults */
  408. stemFiles. = ""                 /* set default to empty */
  409. stemFiles.0 = 0                 /* no element in array  */
  410.  
  411. /* defaults for ASCII-backup */
  412. IF global.config.showDepth <> "V" THEN       /* show everything ? */
  413.    global.config.showDepth = "V"     /* set switch to show everything */
  414.  
  415. IF global.config.showHexAs = "F" THEN        /* show filtered ASCII-string only ? */               
  416.    global.config.showHexAs = "B"             /* show both, hexadecimal and filtered value */
  417.  
  418.  
  419. /* check  arguments */
  420. switch = TRANSLATE(switch)
  421.  
  422. /* extract number of generations */
  423. generations = ""
  424. DO i = LENGTH(switch) TO 1 BY -1
  425.    tmp = SUBSTR(switch, i, 1)
  426.    IF DATATYPE(tmp, "N") THEN generations = generations || tmp
  427.    ELSE LEAVE
  428. END
  429.  
  430.  
  431. IF generations = "" THEN generations = 10               /* 10 generations, numbered from 0 thru 9 by default */
  432. ELSE IF generations < 1 | generations > 10 THEN
  433. DO
  434.    SAY "Invalid number of generations (minimum = 1, maximum = 10):" || generations ||  
  435.    EXIT -2
  436. END
  437.  
  438. switch = SUBSTR(switch, 1, i)           /* remaining switch */
  439.  
  440. /* check whether switch is valid */
  441. IF switch <> "A" & switch <> "C" & switch <> "E" THEN
  442. DO
  443.    SIGNAL usage    /* WRONG Arguments -> Show Usage */
  444.    EXIT -2
  445. END
  446. ELSE global.iFiletype     = switch     /* ansonsten den Switch ins Globale Feld Kopieren */
  447.  
  448.  
  449. filename = STRIP(filename)              /* get rid of blanks */
  450.  
  451. global.eMultipleFiles = 1               /* default: multiple files to process */
  452.  
  453.  
  454. DO
  455.    /* check whether file exists */
  456.    IF filename = "" THEN sourceFile = ""
  457.    ELSE sourceFile = STREAM(filename, "C", "QUERY EXISTS")
  458.  
  459.    IF sourceFile = "" THEN
  460.    DO
  461.       SAY "Error: file does not exist !"
  462.       EXIT -3
  463.    END
  464.  
  465.    stemFiles.0 = 1              /* default, one entry only     */
  466.    stemFiles.1 = sourceFile
  467.    global.eMultipleFiles = 0    /* one distinct file to process */
  468. END
  469.  
  470.  
  471. global.iBackupMode = "Quiet !"
  472. DO  iI = 1 TO stemFiles.0               /* cycle thru all given files */
  473.    sourceFile = stemFiles.iI            /* assign file to work-variable */
  474.    SAY COPIES("=", 20)
  475.  
  476.    global.iBackupMode.iDrive = FILESPEC("drive", sourceFile)
  477.    global.iBackupMode.iPath  = FILESPEC("path",  sourceFile)
  478.  
  479.            DO
  480.               tmp = "Albatros INI-STEALER"
  481.               SAY   tmp 
  482.               SAY
  483. /*
  484.               IF \global.eMultipleFiles & check_if_ini(sourceFile) < 0 THEN
  485.               DO
  486.                  SAY "***Error: not an OS/2-INI-file !"  
  487.               END
  488.               ELSE      // single file 
  489.               DO
  490. */
  491.                  /* backup-ASCII-file gets a file extension of "TXT", hence 10 backups from "TX0" thru "TX9" */
  492.                  tmpName  = FILESPEC("name",  sourceFile)
  493.       
  494.                  pointPos = LASTPOS(".", tmpName)
  495.                  IF pointPos = 0 THEN tmpName = tmpName || ".TXT"
  496.                                  ELSE tmpName = SUBSTR(tmpName, 1, pointPos) || "txt"
  497.       
  498.                  /* build name of the new backup-file */
  499.                  global.outFile = get_next_file(global.iBackupMode.iDrive ||, /* get name of the new backup-file */
  500.                                                 global.iBackupMode.iPath ||,
  501.                                                 tmpName, generations)
  502.    
  503.       
  504.                  stemIni.0 = 1                  /* number of entries */
  505.                  stemIni.1 = sourceFile         /* assign OS/2-INI-file-name to be printed into an ASCII-file */
  506.       
  507.                  SAY
  508.                  SAY   "Source " || sourceFile
  509.                  SAY   "Target " || global.outFile 
  510.                  SAY
  511.       
  512.                  CALL read_toplevel 1           /* read & prepare TopLevel entries, do not sort them */
  513.       
  514.                  CALL print 1                   /* call print-procedure, have all TopLevels printed */
  515.   /*            END */
  516.    
  517.               CALL STREAM global.outFile, "C", "CLOSE"     /* close output file */
  518.            END
  519.  
  520. END 
  521.  
  522. EXIT 0          /* finished batch-mode */
  523.  
  524.  
  525.  
  526. /*
  527.         Backup-files contain at the last character position a number ranging
  528.         from 0 (oldest) to 9 (youngest backup) == total of 10 generations
  529.  
  530.         ARG(1): filename with full path, e.g. "D:\OS2\OS2.INI" or "D:\OS2\OS2.TXT"
  531.         ARG(2): number of maximum generations (1-10, expressed in filetype as 0-9)
  532.  
  533. */
  534. GET_NEXT_FILE: PROCEDURE EXPOSE global. 
  535.      file        = ARG(1)
  536.      generations = ARG(2)
  537.  
  538.      testname    = SUBSTR(file, 1, LENGTH(file)-1)
  539.  
  540.      /* find number of backups already present */
  541.      DO last_backup = 9 TO 0 BY -1
  542.         new_name = testname || last_backup
  543.         IF STREAM(new_name, "C", "QUERY EXISTS") <> "" THEN LEAVE       /* last backup found ! */
  544.      END
  545.  
  546.      to_delete = (last_backup + 1) - generations 
  547.      IF to_delete >= 0 THEN                                             /* erase superfluos backups */
  548.      DO
  549.         DO i = 0 TO to_delete
  550.            ADDRESS CMD "@erase" '"' || testname || i || '" 2>nul'       /* erase oldest file */
  551.  
  552.         END
  553.  
  554.         /* move youngest backups down */
  555.         j = 0
  556.         DO i = i TO last_backup
  557.            old_name = testname || i
  558.            new_name = testname || j
  559.            ADDRESS CMD "@ren" '"' || old_name || '" "' || FILESPEC("Name",new_name) || '"'
  560.            j = j + 1
  561.         END
  562.         new_name = testname || (generations - 1)
  563.      END
  564.      ELSE new_name = testname || (last_backup + 1)
  565.  
  566.      RETURN new_name
  567.  
  568.  
  569.  
  570.  
  571.  
  572. USAGE:
  573.    CLS
  574.    SAY
  575.    SAY '╔════════════════════════════════════════════════════════════════════╗'
  576.    SAY '║   Program : StealTXT.CMD                                           ║'
  577.    SAY '║                                                                    ║'
  578.    SAY '║   Autor : Norbert Heller (c) 1994                                  ║'
  579.    SAY '║                                                                    ║'
  580.    SAY '║   Usage : StealTXT /x INIFILE                                      ║'
  581.    SAY '║                                                                    ║'
  582.    SAY '║   /x : Switch where                                                ║'
  583.    SAY '║                                                                    ║'
  584.    SAY '║         /A : Source is from Albatros                               ║'
  585.    SAY '║         /C : Source is from Michael Bocks CDPLAYER                 ║'
  586.    SAY '║         /E : Source is from IBM CD Explorer                        ║'
  587.    SAY '║                                                                    ║'
  588.    SAY '║                                                                    ║'
  589.    SAY '║   Example : StealTXT /C CDPLAYER.INI                               ║'
  590.    SAY '║                                                                    ║'
  591.    SAY '║   StealTXT will then produce a backup TXT file named CDPLAYER.TX0  ║'
  592.    SAY '║                                                                    ║'
  593.    SAY '╚════════════════════════════════════════════════════════════════════╝'
  594.  
  595.    EXIT 0
  596.  
  597.  
  598.  
  599. ERROR:        
  600.    myrc = RC
  601.    SAY 'StealTXT.CMD: error occurred !'
  602.    SAY
  603.    SAY 'REXX error' myrc 'in line' SIGL':' ERRORTEXT(myrc)
  604.    SAY Substr('     ',1,6-Length(SIGL))(SIGL)' *-*   'Sourceline(sigl)
  605.    SAY
  606.    SAY 'Please contact the author with a description of the error.'
  607.  
  608.    EXIT -99
  609.