!			     RENAME.TES					!
!									!
! Copyright (c) 1986 by Kelvin Smith.  General permission to copy or	!
! modify, but not for profit, is hereby given, as long as this copy-	!
! right notice is included.						!
!									!
! This program is totally unsupported, although it is believed to	!
! work as described.  Please report any problems to:			!
!									!
!	Kelvin Smith							!
!	Financial Computer Systems					!
!	1 Strawberry Hill Ct.						!
!	Stamford, CT  06902						!
!	(203) 357-0504							!
!									!
!									!
! Q-registers used:							!
! A% - During input:  Position of "/", type of error if found		!
!      During run:  Beginning of word being checked			!
! A$ - During input:  Name of file to change, old variable name		!
!      During run:  Word to check against list of old names		!
! C% - During input:  "No confirm necessary" flag (from /N qualifier)	!
!      During run:  Number of variable name changes done		!
! F% - Bit-encoded flag regarding form of input:			!
!	1 - set if old name is an array					!
!	2 - set if old name is a string (has $)				!
!	4 - set if old name is an integer (has %)			!
!	8 - set if 2 or 4 bit refers to new name, not old (for confirm)	!
! I% - Flag set during input when reading from indirect input file	!
! I$ - Name of indirect input file					!
! M% - Set if we should change matches in comments (from /C qualifier)	!
! N% - Set if within a comment (don't skip over quoted strings)		!
! R% - Position to return to after checking word			!
! R$ - During input:  Deletion routine (video/hardcopy)			!
!      During run:  Replacement variable name if a match		!
! S$ - Keyboard input routine						!
!      Returns: S% = Beginning of input					!
!               .  = End of input					!
! Z% - End of list of old and new names; one line of program follows	!

@O!INPUT!                          ! Get user input !


! Main program loop begins here . . . !


!LIN!                              ! Get next line !
1:A"U                              ! No more to get !
     @^A/Finished.  / QC:= @^A/ changes made./ 13^T 10^T
     @O!END!
   '
^E"T                               ! A form feed after !
    ZJ                             ! 1:A eliminates form feed, so replace it !
    12@I%%
  '
0UN                                ! Clear comment flag if set !

! Compare next character: !
! Skip any numbers, spaces, and tabs. !
! Skip comments and quoted strings by looking for their match. !
! Skip any punctuation. !
! At end of line, send line to output file. !

<
<::@S/D/;>                       ! Skip any numbers !
::@S/S/                          ! Skip any spaces and tabs !
0A-14"L                            ! End of line: <CR>, <LF>, <FF> !
       @O!OUT!                     ! Put to output file !
     '
0A-33"E                            ! Start of comment !
       QM"E                        ! We should ignore comments !
           :@2S/!/                 ! Does it end on the line? !
              "S
                F<                 ! Yes--keep checking after !
              | @O!OUT!            ! No--on to next line !
              '
         | C                       ! Skip the exclamation point !
           QN^_UN                  ! Toggle "in comment" flag !
           F<                      ! Continue !
     '   '
0A-34"E                            ! Start of quoted string !
       QN"N                        ! Inside a comment? !
           C                       ! Yes--skip the punctuation !
           F<                      !  and continue !
         '
       :@2S/"/                     ! Find end !
          "S
            F<                     ! Continue checking !
          | @^A/%Unterminated string in line:/ 13^T 10^T @^A/>>>/ QZ,ZT
            @O!OUT!                ! On to next line !       
     '    '
0A-39"E                            ! Start of quoted string !
       QN"N                        ! Inside a comment? !
           C                       ! Yes--skip the punctuation !
           F<                      !  and continue !
         '
       :@2S/'/                     ! Find end !
          "S
            F<                     ! Continue checking !
          | @^A/%Unterminated string in line:/ 13^T 10^T @^A/>>>/ QZ,ZT
            @O!OUT!                ! On to next line !       
     '    '
0A"A                               ! Is it a letter? !
  | C                              ! No - it's punctuation:  skip it !
    F<                             ! Try next !
  '

! Found a word to check.  It could be a normal BASIC keyword, or it	!
! could be a variable name; we don't really care.  Legal programming	!
! style doesn't allow using keywords for variable names anyway, so	!
! our search through the list of names to change will fail.   We make	!
! sure we add any % and/or ( at end--the search "S/^N^EC/"  includes	!
! . and $ along with alphanumerics, but we need all possibilities 	!
! covered for the variable name.  Once the word is assembled, see	!
! if it's in our list of names to change.  If so, change it.		!
!	There's one special case.  The CHANGE statement does not use	!
! the parentheses to refer to arrays, determining them instead from	!
! context.  (The same is true for MAT functions, but I never use them.)	!
! Therefore, a special check is done for them.				!

.UA                                ! Beginning of word to check !
!FNDEND!
@S/C/                          ! Find end char !
R                                  ! Get before it !
0A-95"E                            ! It's an underscore - legal part of name !
       C                           ! Skip it !
       @O!FNDEND!                  !  and continue to true end !
     '
0A-37"E                            ! It's a percent--integer suffix !
       C                           ! Add it on !
     '
0A-40"E                            ! Open paren--start array ref !
       C                           ! Add it on !
     '
.UR                                ! Position to return to !
QAJ                                ! Return to beginning of word for checks !
::@S/SUB^ES/                       ! Subroutine name following - don't match !
   "S
     !SUBR!
     @S/^N^EC/                     ! Find char after subr name end !
     F<                            ! Try words following !
   '
::@S/CALL^ES/                      ! Call; also a subroutine name coming !
   "S
     @O!SUBR!                      ! Use code above !
   '
::@S/MAP^ES/                       ! Skip map names too !
   "S
     0A-40"E                       ! Followed by a "("? !
            C                      ! If so, skip it !
            ::@S/^ES/ ^[           !  and any following spaces !
          '
     @S/^N^EC/                     ! Skip the actual map name !
     F<                            ! Try what follows !
   '
QA,QRXA                            ! Copy the word !
J                                  ! To start of list of changes !
QZ,@:S%LQA/%                   ! Is it in list? !
     "S                            ! Yes !
       .,.+(1^Q)-2XR               ! Copy the replacement !
       QAJ                         ! Return to beginning of word !
       .,QRD                       ! Delete it !
       GR                          ! Insert replacement !
       %C ^[                       ! Count number of changes !
     | QAJ                         ! No match - return to word !
       ::@S/CHANGES/             ! Is it a change command? !
          "S                       ! Yes - arrays lack ( !
            .UA                    ! Start of next word !
            @S/C/              ! Go to its end !
            -2A-36"E               ! Is last char a $? !
                    @S/TOS/      ! Yes - numeric array is second !
                    .UA            ! Mark its beginning !
                    @S/C/      ! Go to its end !
                  '
            -1A-37"E               ! Add integer suffix if present !
                    C
                  '
            R                      ! Back over terminating char !
            QA,.XA                 ! Copy the word !
            .UR                    ! Mark end position !
            J                      ! To start of list of changes !
            QZ,@:S%LQA(/%      ! Is it in list? !
                 "S                ! Yes !
                   .,.+(1^Q)-2XR   ! Copy the replacement !
                   QAJ             ! Return to beginning of word !
                   .,QRD           ! Delete it !
                   GR              ! Insert replacement !
                   -D              ! Delete extra "(" !
                   %C ^[           ! Count number of changes !
                 | QRJ             ! No match - return to word !
                 '
          | QRJ                    ! Not CHANGE - go to point following !
     '    '
>                                  ! Start compare again !

! Output - we're done checking the line, so send it to the output file !
! and wipe it out of the buffer, then get a new line to check. !

!OUT!                              ! Put the line out !
QZ,ZPW                             ! Write the line !
QZ,ZK                              ! Delete it !
@O!LIN!                            ! Get a new one !


! INPUT - Put it down here so tag searches in main body of the macro !
! don't have to scan it. !

!INPUT!
Z"N                             ! Something in the buffer !
   HK                           ! Wipe it out !
 '

^D                              ! Force decimal !

! Set up our input macros - R for deletion routine & S for input !

ET&2"F @^UR/ -1A^T/             ! Hardcopy delete - echo deleted letter !
     | @^UR/ 8^T 32^T 8^T/      ! Video delete - wipe it out !
     '
@^US/
.US
< ^TUT QT-127"E .-QS"> MR -D '
     | QT- 27"E 13^T 10^T 1;
     | QT- 21"E ET&2"F 13^T 10^T | .-QS+2<MR>' QS,.K
     | QT- 13"E ^T;
     | QT@I%% '''' >/

@^A/Rename variables in BP2 programs/ 13^T 10^T 10^T

!FILE!
@^A%File to fix <.B2S>? %
MS                                 ! Get a file name !
J                                  ! To beginning of name !
@:S%/C%                            ! /C qualifier? !
  "S                               !  Yes - include comments in changes !
    -1UM                           ! Set flag !
    @FR//                          !  and delete qualifier !
    J                              ! Return to beginning !
  '
@:S/./                             ! Dot for file type? !
  "U                               ! No !
    ZJ                             ! Go to end of name !
    @I%.B2S%                       ! Add default !
  '
HXA HK                             ! Cut file name to q-reg A !
@:EB/^EQA/                         ! Try to open file !
   "U
     @^A/?No such file/ 13^T 10^T  ! Doesn't exist !
     0UM                           ! Clear flag if set !
     @O!FILE!                      ! Try again !
   '
0,0XA                              ! Clear q-reg A !

! Main input - get list of variable names to change !

13^T 10^T
@^A%Enter old and new variable name, separated by "/".% 13^T 10^T
@^A%Enter "@filnam" to use list of names in a file.% 13^T 10^T
@^A%Press <CR> to end list.% 13^T 10^T
10@I//                             ! Need line terminator before first !

!INP!
QI"N                               ! Indirect file input !
    1:A                            ! Get next line !
      "U                           ! Nothing more !
        @^A/End of indirect file / :G* 13^T 10^T
        @ER//                      ! Back to normal input !
        0UI                        ! Clear the flags !
        0UC
        @O!INP!
      '
    0A-33"E                        ! Starts with exclamation mark !
           K                       ! Ignore it: wipe it out !
           @O!INP!                 !  and get next line !
         '
    .US                            ! Mark beginning of next line !
    @^A/  /                        ! Indent indirect file input !
    T                              ! Print current line !
    ZJ
    -2D                            ! Delete <CR><LF> !

  | @^A%Old name/new name? %       ! Interactive input !
    MS                             ! Get a line !
    QS-."E                         ! No response !
          .UZ                      ! End of search/replace list !
          @^A/Working. . ./ 13^T 10^T
          @O!LIN!                  ! Process the list !
        '
  '
QSJ                                ! To beginning to parse !

! Look for indirect file name !

0A-64"E                            ! Indirect file request !
       QI"N                        ! Already doing one !
           @^A/Nested indirect files not allowed.  Ignoring line: /
           QS,ZT 13^T 10^T
           @O!INP!
         '
       .UA
       :@S%/N%                     ! Look for switch !
         "S                        ! Found /N - no confirm !
           1UC                     ! Set flag !
           @FR//                   ! Delete switch !
         '
       QAJ
       EP                          ! Switch to secondary input stream !
       .+1,ZXI                     ! Copy file name !
       .,ZK                        ! Delete it and preceding "@" !
       @:ER/^EQI/                  ! Open it !
          "U                       ! No luck !
            @^A/Can't find file / :G* 13^T 10^T
            @ER//                  ! Return to normal input !
            0UC                    ! Clear no confirm flag !
            @O!INP!
          '
       1UI                         ! Mark indirect file open !
       @^A/From indirect file:/ 13^T 10^T
       @O!INP!                     ! Get first line !
     '

! Basic format checking on variable names--must start with letter, !
! must be separated by "/". !

0A"A
  | 1UA
    @O!ERRINP!                     ! Must start with letter !
  '
@:S%/%                             ! Find separator !
 "U                                ! None there !
   2UA
   @O!ERRINP!
 '
0A"A                               ! Does new name start with letter? !
  | 3UA
    @O!ERRINP!
  '

! Check old and new names to make sure they haven't been used before !

QS-1"N                             ! First entry?  If not, check it !
      .UA
      QS,.-1XA                     ! Copy old name !
      QS-2J                        ! Go before it !
      -@:S%LQA/%               ! Does the old name already exist? !
         "S                        ! Yes !
           8UA                     ! Print an error !
           @O!ERRINP!
         '                         ! No - we're at beginning of buffer !
      QA,ZXA                       ! Copy new name !
      13:@^UA//                    ! Append <CR> for search !
      QA-1,@:S%/QA%              ! Does it already exist? !
             "S                    ! Yes !
               QC"N                ! No confirm flag set !
                   @O!ENDINP!      ! Accept the input without question !
                 '
               @^A/%New name has already been used.  Repeat it <N>? /
               @O!QCONF!           ! Get confirmation !
           '
      QAJ
    '

! Check for consistency between names: !
!  1) Arrays must be arrays in both. !
!  2) Cannot switch from $ to % or vice versa. !
!  3) Confirm validity of a switch from nothing to $ or % or vice versa. !

0UF                                ! Zero a flag variable !
-2A-40"E                           ! Old name is an array--ends with ( !
        1UF                        ! Note it !
        R                          !  and back up one char !
      '
-2A-36"E                           ! Old name is a string (ends with $) !
        QF#2UF                     ! Turn on "$" bit !
      '
-2A-37"E                           ! Old name is an integer (ends with %) !
        QF#4UF                     ! Turn on "%" bit !
      '
ZJ                                 ! Go to end of new name !
QF&1">                             ! Should it be an array? !
      -1A-40"N                     ! Yes, but no ( at end !
              4UA                  ! Print an error !
              @O!ERRINP!      
            | R                    ! Back up one char !
            '
    | -1A-40"E                     ! New is array, but old is not !
              5UA                  ! Print an error !
              @O!ERRINP!
            '
    '
QF&2">                             ! Should it be a string? !
      -1A-36"N                     ! Yes, but no $ at end !
              @O!CONFIRM!          ! User may want it (using DECLAREd var) !
            '
    | -1A-36"E                     ! Old wasn't string but new has a $ !
              QF&4">               ! Old was % - definite conflict !
                    6UA            ! Print an error !
                    @O!ERRINP!
                  '
              2+8UF                ! Note the situation !
              @O!CONFIRM!          !  and ask for verification !
    '       '
QF&4">                             ! Should it be an integer? !
      -1A-37"N                     ! Yes, but no % at end !
              @O!CONFIRM!          ! User may want it (using DECLAREd var) !
            '
    | -1A-37"E                     ! Old wasn't integer but new has a % !
              QF&2">               ! Old was $ - definite conflict !
                    7UA            ! Print an error !
                    @O!ERRINP!
                  '
              4+8UF                ! Note the situation !
              @O!CONFIRM!          !  and ask for verification !
    '       '
!ENDINP!
ZJ                                 ! Make sure we're at end !
13@I%%                             ! Input good-separate with CR-LF !
10@I%%
@O!INP!                            ! Get another !

! Print input error message !

!ERRINP!
@^A/?Input error: /
QA+48UA                            ! 1 becomes "1" (ASCII 49), etc. !
@O!ERR^EUA!                        ! Tell which type !
  !ERR1! @^A\Old name doesn't start with letter\ @O!ERREND!
  !ERR2! @^A\No "/" separator\                   @O!ERREND!
  !ERR3! @^A\New name doesn't start with letter\ @O!ERREND!
  !ERR4! @^A\Old is array, but new is not\       @O!ERREND!
  !ERR5! @^A\New is array, but old is not\       @O!ERREND!
  !ERR6! @^A\Old name has % and new has $\       @O!ERREND!
  !ERR7! @^A\Old name has $ and new has %\       @O!ERREND!
  !ERR8! @^A\Old name was already input\
!ERREND!
13^T 10^T
QS,ZK                              ! Wipe out offending line !
@O!INP!                            ! Try again !

! Questionable input - we want confirmation !

!CONFIRM!
QC"N                               ! No confirm flag set !
    @O!ENDINP!                     ! Accept the input without question !
  '
ZJ                                 ! Make sure we're at end !
QF-8"<                             ! Old name has suffix !
      @^A/%Old/
    | @^A/%New/                    ! New name has suffix !
    '
@^A/ name has /
QF&2"N                             ! Did we have $? !
      @^A/$/                       !  Yes !
    | @^A/%/                       ! It was a % !
    '
@^A/ suffix, but /
QF-8"<
      @^A/new/
    | @^A/old/
    '
@^A/ does not.  Is this OK <N>? /
!QCONF!
^TUA
QA-13"E                            ! Carriage return - line feed follows !
       ^T ^[                       ! Swallow it !
     | 13^T 10^T                   ! Otherwise do <CR>-<LF> !
     '
QA-89"E                            ! Y - User wants it !
       @O!ENDINP!
     '
QA-121"E                           ! Small y - same as above !
       @O!ENDINP!
      '
QS,ZK                              ! "No" input (explicit or implicit) !
@O!INP!                            ! Delete and try again !

!END!
0,QZK                              ! Delete variable list !
EX                                 ! Close the file and exit !

