.TITLE RETAB - Redo tabbing in a file .IDENT /1.00/ ;++ ; Title: ; RETAB - Redo tabbing in a file ; ; Facility: ; General utility for file processing. ; ; Abstract: ; RETAB is a utility for altering the tabbing in a file. It reads each ; record from an input file and converts all tabs to spaces, based on ; an input tab set description. Tabs and spaces are then reinserted ; based on the the tab stops given in an output tab set description, so ; as to minimize the number of characters in the record. The command ; provides various options for specifying the input and output tab ; sets. The input file or files can be specified using wildcards. ; If no output file spec is given, it defaults to inputfile.RTB. ; ; This program uses a set of FORTRAN subroutines obtained from ; the Fall 1981 VAX SIG tape. The routines, based on the algorithms ; in Kernighan and Plaugher, "Software Tools", were take from the ; program [VAXF81.MUDD.TABBER]TABBER.FOR, written by Ned Freed. ; ; This program also uses a set of utility routines for LIB$TPARSE. ; This program must be assembled with DEV$SSG:[SSG.SOURCE.SMAC]SMAC.MLB. ; ; Environment: ; Native Mode. No other considerations. ; ; Author: ; Gary L. Grebus, Creation date: 19-Mar-1982 ; Battelle Columbus Labs ; ; Modified by: ; ;-- .PAGE .SBTTL Symbol definitions ; System symbols $TPADEF ; LIB$TPARSE symbols $STSDEF ; Status value symbols $CHFDEF ; Condition handler arguments ; Local symbols COMMAND_BUFFER_SZ = 255 ; Size of buffer for command line LINE_BUFFER_SZ = 255 ; Size of larges line we can process STANDARD_TAB_INTERVAL = 8 ; Interval between standard tabs .PAGE .SBTTL Read only data .PSECT RODATA RD,NOWRT,NOEXE,SHR,LONG ; Read only data FIRST_PROMPT: INPUT_PROMPT: .ASCID /_Input file: / ; Prompt if no command line or if ; no first parameter OUTPUT_PROMPT: .ASCID /_Output file: / ; Prompt if no second parameter .PAGE .SBTTL Read/write data .PSECT RWDATA RD,WRT,NOEXE,NOSHR,LONG ; Read/write data ; RMS data structures IN_FAB: $FAB FAC=GET,- FOP=NAM,- NAM=IN_NAM ; Input file FAB IN_RAB: $RAB FAB=IN_FAB,- ROP=RAH,- UBF=LINE_BUFFER_IN,- USZ=LINE_BUFFER_SZ ; Input file RAB IN_NAM: $NAM ESA=IN_ES,- ESS=NAM$C_MAXRSS,- RSA=IN_RS,- RSS=NAM$C_MAXRSS ; Input file NAM block OUT_FAB: $FAB FAC=PUT,- NAM=OUT_NAM,- DNM=<.RTB>,- FOP=,- ORG=SEQ ; Output file FAB OUT_RAB: $RAB FAB=OUT_FAB,- ROP=WBH,- RBF=LINE_BUFFER_IN ; Output file RAB OUT_NAM: $NAM RLF=IN_NAM,- ESA=OUT_ES,- ESS=NAM$C_MAXRSS,- RSA=OUT_RS,- RSS=NAM$C_MAXRSS ; Output file NAM IN_ES: .BLKB NAM$C_MAXRSS ; Input file expanded filespec IN_RS: .BLKB NAM$C_MAXRSS ; Input file resultant filespec IN_RS_DESC: .LONG 0 .ADDRESS IN_RS ; Skeleton descriptor to above string OUT_ES: .BLKB NAM$C_MAXRSS ; Output file expanded filespec OUT_RS: .BLKB NAM$C_MAXRSS ; Output file resultant filespec OUT_RS_DESC: .LONG 0 ; Skeleton descriptor to above string .ADDRESS OUT_RS ; Parameter block for LIB$TPARSE TPARSE_BLOCK: .LONG TPA$K_COUNT0 .LONG TPA$M_ABBREV ; Allow abbreviations .BLKL TPA$K_LENGTH0-8 ; Remainder of block COMMAND_BUFFER: STRING COMMAND_BUFFER_SZ ; Descriptor and buffer for command ; Line buffers LINE_BUFFER_IN: .BLKB LINE_BUFFER_SZ ; Buffer for input line LINE_SIZE_IN: .BLKL 1 ; Size of data in above buffer LINE_BUFFER_OUT: .BLKB LINE_BUFFER_SZ ; Buffer for output line LINE_SIZE_OUT: .BLKL 1 ; Size of data in above buffer ; Tab descriptor arrays. One longword for each possible line position INTAB_ARRAY: .BLKL LINE_BUFFER_SZ ; Input tabs OUTTAB_ARRAY: .BLKL LINE_BUFFER_SZ ; Output tabs MAX_COL: .LONG LINE_BUFFER_SZ ; The maximum tab column TAB_INC: .LONG STANDARD_TAB_INTERVAL ; Inverval between standard tabs CURRENT_TAB_ARRAY: .BLKL 1 ; Space for address of tab array ; currently being filled. PARSE_ACTION_ERROR: .BLKL 1 ; Flag that an action routine detected ; an error INPUT_FILE_DESC: .BLKQ 1 ; Space for descriptor to input file ; spec OUTPUT_FILE_DESC: .BLKQ 1 ; Space for descriptor to output file ; spec FINAL_STATUS: .BLKL 1 ; Final status to return on exit. ; Set by condition handler. .PAGE .SBTTL RETAB Parse Tables .PSECT RODATA RD,NOWRT,NOEXE,SHR,LONG ; LIB$TPARSE parse tables for RETAB COMMA = ^A/,/ R_PAREN = ^A/)/ $INIT_STATE STATE_TABLE,KEY_TABLE $STATE START $TRAN TPA$_EOS,TPA$_FAIL,TPA_FIRST_INPUT,,,FIRST_PROMPT ; Read input $TRAN TPA$_EOS,TPA$_FAIL,TPA_PARSE_ERR,,,RETAB_INPREQ $TRAN TPA$_LAMBDA,CMD_QUAL $STATE CMD_QUAL $TRAN !QUALIF $STATE INPUT_FILE $TRAN !FILE_SPEC,INP_QUAL,,,INPUT_FILE_DESC $TRAN TPA$_EOS,INPUT_FILE,TPA_PARAM_INPUT,,,INPUT_PROMPT $TRAN TPA$_LAMBDA,TPA$_FAIL,TPA_PARSE_ERR,,,RETAB_INPREQ $STATE INP_QUAL $TRAN !QUALIF $STATE OUTPUT_FILE $TRAN !FILE_SPEC,OUT_QUAL,,,OUTPUT_FILE_DESC $TRAN TPA$_EOS,OUTPUT_FILE,TPA_PARAM_INPUT,,,OUTPUT_PROMPT $TRAN TPA$_LAMBDA,TPA$_FAIL,TPA_PARSE_ERR,,,RETAB_OUTREQ $STATE OUT_QUAL $TRAN !QUALIF $TRAN TPA$_EOS,TPA$_EXIT $TRAN TPA$_LAMBDA,TPA$_FAIL,TPA_PARSE_ERR,,,RETAB_PARAMS ; Parse any optional qualifiers. Succeeds even if no qualifiers found $STATE QUALIF $TRAN '/' $TRAN TPA$_LAMBDA,TPA$_EXIT $STATE QUAL_NAMES $TRAN 'INTABS',,SELECT_TAB_ARRAY,,,INTAB_ARRAY $TRAN 'OUTTABS',,SELECT_TAB_ARRAY,,,OUTTAB_ARRAY $TRAN TPA$_LAMBDA,TPA$_FAIL,TPA_PARSE_ERR,,,RETAB_UNKQUAL $STATE $TRAN '=' $TRAN TPA$_LAMBDA,TPA$_FAIL,TPA_PARSE_ERR,,,RETAB_VALREQ $STATE $TRAN !INTERVAL,TPA$_EXIT $TRAN 'STANDARD',TPA$_EXIT,SETTAB_STD $TRAN 'NONE',TPA$_EXIT,SETTAB_NONE $TRAN !ONE_TAB,TPA$_EXIT $TRAN '(',TAB_LIST $TRAN TPA$_LAMBDA,TPA$_FAIL,CHK_ACTION_ERROR ; Abort if bad tab value $TRAN TPA$_LAMBDA,TPA$_FAIL,TPA_PARSE_ERR,,,RETAB_BADFMT $STATE TAB_LIST $TRAN 'STANDARD',NUM_LIST,SETTAB_STD $TRAN 'NONE',NUM_LIST,SETTAB_NONE $TRAN !INTERVAL,NUM_LIST $TRAN TPA$_LAMBDA,NUM_LIST $STATE NUM_LIST $TRAN !ONE_TAB,NUM_LIST $TRAN COMMA,NUM_LIST $TRAN R_PAREN,TPA$_EXIT $TRAN TPA$_LAMBDA,TPA$_FAIL,CHK_ACTION_ERROR ; Abort if bad tab value $TRAN TPA$_LAMBDA,TPA$_FAIL,TPA_PARSE_ERR,,,RETAB_BADFMT $STATE ONE_TAB $TRAN '-' $TRAN TPA$_DECIMAL,TPA$_EXIT,SETTAB_ONE $STATE $TRAN TPA$_DECIMAL,TPA$_EXIT,CLRTAB_ONE $STATE INTERVAL $TRAN 'INTERVAL' $STATE $TRAN ':' $TRAN TPA$_LAMBDA,TPA$_FAIL,TPA_PARSE_ERR,,,RETAB_INTVNUM $STATE $TRAN TPA$_DECIMAL,TPA$_EXIT,SETTAB_INTERVAL $TRAN TPA$_LAMBDA,TPA$_FAIL,CHK_ACTION_ERROR ; Abort if bad tab value $TRAN TPA$_LAMBDA,TPA$_FAIL,TPA_PARSE_ERR,,,RETAB_INTVNUM $STATE FILE_SPEC $TRAN TPA$_EOS,TPA$_FAIL $TRAN TPA$_LAMBDA,,TPA_SET_BLANKS $STATE NEXT_CHAR $TRAN TPA$_ANY,NEXT_CHAR,TPA_UNTIL_BLANK $TRAN TPA$_LAMBDA,TPA$_EXIT,TPA_CLR_BLANKS $END_STATE .PAGE .SBTTL Local parser action routines .PSECT CODE RD,NOWRT,EXE,SHR,LONG ; These routines are called by LIB$TPARSE as action routines. ; They are all called with TPARSE_BLOCK as their parameter list. .ENTRY SELECT_TAB_ARRAY,^M<> ; Routine to select which tab array is to be filled by subsequent ; SETTAB and CLRTAB routines. Clears default settings from the array. MOVL TPA$L_PARAM(AP),- CURRENT_TAB_ARRAY ; Store address of tab array CALL WIPTAB - @CURRENT_TAB_ARRAY, MAX_COL ; Zap default tabs MOVZWL #SS$_NORMAL,R0 ; Return success RET .ENTRY SETTAB_STD,^M<> ; Routine to set tabs in the current tab array to the standard interval. CALL REGTAB TAB_INC, @CURRENT_TAB_ARRAY,- MAX_COL ; Set standard interval MOVZWL #SS$_NORMAL,R0 ; Return success RET .ENTRY SETTAB_NONE,^M<> ; Routine to clear all tabs in the current tab array. CALL WIPTAB @CURRENT_TAB_ARRAY, MAX_COL MOVZWL #SS$_NORMAL,R0 ; Return success RET .ENTRY SETTAB_ONE,^M<> ; Routine to set a tab stop at a specified column. Column is passed in ; NUMBER field of tparse block IF AND - THEN CALL SETTAB TPA$L_NUMBER(AP), @CURRENT_TAB_ARRAY,- MAX_COL ; Set a tab MOVZWL #SS$_NORMAL,R0 ; Return success ELSE MOVL #RETAB_BADPOS,R0 ; Signal error SIGNAL - CODE1=R0,- F1= INCL PARSE_ACTION_ERROR ; Flag an error ENDIF RET .ENTRY CLRTAB_ONE,^M<> ; Routine to clear a tab stop at a specified column. Column number passed ; in the NUMBER field of TPARSE_BLOCK. IF AND - THEN CALL CLRTAB TPA$L_NUMBER(AP), @CURRENT_TAB_ARRAY,- MAX_COL ; Clear a tab MOVZWL #SS$_NORMAL,R0 ; Return success ELSE MOVL #RETAB_BADPOS,R0 ; Return error SIGNAL - CODE1=R0,- F1= INCL PARSE_ACTION_ERROR ; and flag it ENDIF RET .ENTRY SETTAB_INTERVAL,^M<> ; Routine to set tabs at a repeated interval. The interval is in the ; NUMBER field of the TPARSE block. IF THEN ; If non-zero increment CALL REGTAB TPA$L_NUMBER(AP), @CURRENT_TAB_ARRAY,- MAX_COL ; Set the tabs MOVZWL #SS$_NORMAL,R0 ; Return success ELSE MOVL #RETAB_BADPOS,R0 ; Return error SIGNAL - CODE1=R0,- F1=TPA$L_TOKENCNT(AP) INCL PARSE_ACTION_ERROR ; and flag it ENDIF RET .ENTRY CHK_ACTION_ERROR,^M<> ; Routine to allow errors detected by an action routine to abort the ; parse rather than continuing the search in the current state. This ; is needed if the last transition in each state is an inappropriate ; error message. This action routine should be called from a transition ; to TPA$_FAIL. If there have been any errors, we allow this transition ; to succeed. IF THEN CLRL R0 ; Fail this transition if no errors ENDIF RET .PAGE .SBTTL RETAB - Main program .PSECT CODE RD,NOWRT,EXE,SHR,LONG .ENTRY RETAB,^M<> ; Register usage: ; R0-R1 - Scratch MOVZWL #SS$_NORMAL,- FINAL_STATUS ; Assume we succeed with everything MOVAB HANDLER,(FP) ; Set up condition handler ; Setup for parsing command line CALL WIPTAB INTAB_ARRAY, MAX_COL ; Zap input tabs CALL REGTAB TAB_INC, INTAB_ARRAY, MAX_COL ; and set standard ones CALL WIPTAB OUTTAB_ARRAY, MAX_COL ; Zap output tabs. Don't set any. CALL TPA_INIT TPARSE_BLOCK, COMMAND_BUFFER ; Setup parser utility rtns CLRL PARSE_ACTION_ERROR ; No action routine errors yet CALL LIB$TPARSE TPARSE_BLOCK, STATE_TABLE, KEY_TABLE ; Get and parse ; Stop if no input received or if a syntax error. All messages have been ; issued BISL3 #STS$M_SEVERITY,R0,R1 ; Ignore severity bits IF THEN BISL2 #STS$M_INHIB_MSG,R0 ; Don't duplicate any messages ELSE ; Setup file specs in FAB's MOVL INPUT_FILE_DESC+DSC$A_POINTER,- IN_FAB+FAB$L_FNA ; Set input file spec CVTWB INPUT_FILE_DESC+DSC$W_LENGTH,- IN_FAB+FAB$B_FNS MOVL OUTPUT_FILE_DESC+DSC$A_POINTER,- OUT_FAB+FAB$L_FNA ; and output file spec CVTWB OUTPUT_FILE_DESC+DSC$W_LENGTH,- OUT_FAB+FAB$B_FNS ; Process all wildcards specified by input spec CALL WILDSCAN - IN_FAB,- DO_FILE,- DO_ERROR ; Do all the work ENDIF MOVL FINAL_STATUS,R0 ; Return any error status we ; have seen RET ; This is the condition handler for the entire program .ENTRY HANDLER,^M<> MOVL CHF$L_SIGARGLST(AP),R0 ; Get address of signal args MOVL CHF$L_SIG_NAME(R0),R0 ; Get signal name IF THEN ; If an error status MOVL R0,FINAL_STATUS ; Remember it ENDIF MOVL #SS$_RESIGNAL,R0 ; and resignal RET .PAGE .SBTTL DO_FILE - Do one file of wildcard group ;++ ; Functional Description: ; This routine is called as an action routine from WILDSCAN. It is ; called once for each file located as matching the wildcard input ; filespec. The FAB is ready to be opened when this routine is called. ; ; Calling Sequence: ; CALLS #3, DO_FILE ; ; Input Parameters: ; 4(AP) - Address of FAB ; 8(AP) - Address of success action routine ; 12(AP) - Address of error action routine ; ; Output Parameters: NONE ; ; Implicit Inputs: ; All RMS data structures ; ; Implicit Outputs: ; Ditto ; ; Procedures called: ; SYS$OPEN, SYS$CONNECT, SYS$CREATE, SYS$CLOSE ; ; Completion Status: ; Signals any errors encountered. Always returns SS$_NORMAL ; ; Side Effects: NONE ; ;-- .ENTRY DO_FILE,^M<> ; Register usage: ; R0-R1 - Scratch ; Open the next wild input file $OPEN FAB=IN_FAB ; Open the file we have located IF THEN MOVZBW IN_NAM+NAM$B_RSL,- IN_RS_DESC+DSC$W_LENGTH ; Finish descriptor to filespec SIGNAL - CODE1=#RETAB_OPNERR,- F1=IN_RS_DESC,- CODE2=R0 ; Signal the error BRW CLOSE_ALL ENDIF $CONNECT RAB=IN_RAB ; Connect the record stream IF THEN MOVZBW IN_NAM+NAM$B_RSL,- IN_RS_DESC+DSC$W_LENGTH ; Finish descriptor to filespec SIGNAL - CODE1=#RETAB_CONERR,- F1=IN_RS_DESC,- CODE2=R0 ; Signal the error BRW CLOSE_ALL ENDIF ; Propagate attributes from input file to output file MOVB IN_FAB+FAB$B_RAT,- OUT_FAB+FAB$B_RAT ; Propagate carriage control attrib MOVB IN_FAB+FAB$B_RFM,- OUT_FAB+FAB$B_RFM ; and record type $CREATE FAB=OUT_FAB ; Create output file IF THEN MOVZBW OUT_NAM+NAM$B_RSL,- OUT_RS_DESC+DSC$W_LENGTH ; Finish descriptor to filespec SIGNAL - CODE1=#RETAB_CREERR,- F1=OUT_RS_DESC,- CODE2=R0 ; Signal the error BRW CLOSE_ALL ENDIF $CONNECT RAB=OUT_RAB ; Connect record stream IF THEN MOVZBW OUT_NAM+NAM$B_RSL,- OUT_RS_DESC+DSC$W_LENGTH ; Finish descriptor to filespec SIGNAL - CODE1=#RETAB_CONERR,- F1=OUT_RS_DESC,- CODE2=R0 ; Signal the error BRW CLOSE_ALL ENDIF ; All files are ready. Go munge them. CALL MOVE_RECORDS CLOSE_ALL: $CLOSE FAB=IN_FAB ; Close any files which might be open $CLOSE FAB=OUT_FAB MOVZWL #SS$_NORMAL,R0 ; Return success RET .PAGE .SBTTL DO_ERROR - Report a Parse or Search error ;++ ; Functional Description: ; Action routine called from WILDSCAN if an error is encountered ; in the $PARSEing or $SEARCHing of the wildcard input spec. ; ; Calling Sequence: ; CALLS #3, DO_ERROR ; ; Input Parameters: ; 4(AP) - Address of FAB ; 8(AP) - Address of success action routine ; 12(AP) - Address of this routine ; ; Output Parameters: NONE ; ; Implicit Inputs: ; All RMS data structures ; ; Implicit Outputs: ; Ditto ; ; Procedures called: NONE ; ; Completion Status: ; Returns SS$_NORMAL always. ; ; Side Effects: NONE ; ;-- .ENTRY DO_ERROR,^M<> ; Register usage: ; R0-R1 - Scratch IF THEN ; We have a resultant file spec to use MOVZBW IN_NAM+NAM$B_RSL,- IN_RS_DESC+DSC$W_LENGTH ; Finish descriptor to filespec SIGNAL - CODE1=#RETAB_LOOKUP,- F1=IN_RS_DESC,- CODE2=IN_FAB+FAB$L_STS ELSE ; No resultant file spec. Use what was supplied on the command SIGNAL - CODE1=#RETAB_LOOKUP,- F1=INPUT_FILE_DESC,- CODE2=IN_FAB+FAB$L_STS ENDIF MOVZWL #SS$_NORMAL,R0 ; Return success RET .PAGE .SBTTL MOVE_RECORDS - Process the records in a file ;++ ; Functional Description: ; This routine is called for each input/output file pair successfully ; opened. This routine moves the contents of the first file to ; the second file performing the tab conversion. ; ; Calling Sequence: ; CALLS #0, MOVE_RECORDS ; ; Input Parameters: NONE ; ; Output Parameters: NONE ; ; Implicit Inputs: ; INTAB_ARRAY, OUTTAB_ARRAY - Tab column settings ; IN_RAB, OUT_RAB - RMS data structures ; ; Implicit Outputs: NONE ; ; Procedures called: ; LENTAB, LDETAB, SYS$GET, SYS$PUT ; ; Completion Status: ; Always returns SS$_NORMAL. Signals any RMS errors encounterd. ; ; Side Effects: NONE ; ;-- .ENTRY MOVE_RECORDS,^M<> ; Register usage: ; R0-R1 - Scratch REPEAT $GET RAB=IN_RAB ; Read a record IF THEN IF THEN ; IF a real error MOVZBW IN_NAM+NAM$B_RSL,- IN_RS_DESC+DSC$W_LENGTH ; Finish descriptor to filespec SIGNAL - CODE1=#RETAB_RDERR,- F1=IN_RS_DESC,- CODE2=R0 ; Signal the error ENDIF BRW ABORT_FILE ; Done with the file ENDIF MOVZWL IN_RAB+RAB$W_RSZ,- LINE_SIZE_IN ; Get length of record read CALL LDETAB - LINE_BUFFER_IN,- LINE_SIZE_IN,- LINE_BUFFER_OUT,- LINE_SIZE_OUT,- INTAB_ARRAY,- MAX_COL ; Remove the tabs from the line ; according to input spec CALL LENTAB - LINE_BUFFER_OUT,- LINE_SIZE_OUT,- LINE_BUFFER_IN,- LINE_SIZE_IN,- OUTTAB_ARRAY,- MAX_COL ; Restore tabs according to output ; spec CVTLW LINE_SIZE_IN,- OUT_RAB+RAB$W_RSZ ; Set record length in RAB $PUT RAB=OUT_RAB ; and write the record IF THEN MOVZBW OUT_NAM+NAM$B_RSL,- OUT_RS_DESC+DSC$W_LENGTH ; Finish descriptor to filespec SIGNAL - CODE1=#RETAB_WRTERR,- F1=OUT_RS_DESC,- CODE2=R0 ; Signal the error BRW ABORT_FILE ; Done with the file ENDIF UNTIL ABORT_FILE: RET .END RETAB