TEACL is a fork of TECOC created for the purpose of describing diffs in a document being collaboratively edited
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

1773 lines
63 KiB

!SQU.TEC V40.00!
! --------------------------------------------------------------------- !
! !
! TECO macro to squish other TECO macros. This macro will take a nice, !
! readable TECO macro and squish it so that it is as small and as fast !
! as possible (and is completely unreadable). !
! !
! Command line: !
! !
! MUNG SQU OUTFILE[.TEC]=INFILE[.TES]/SWITCHES !
! !
! For example: !
! !
! MUNG SQU SQU.TEC=SQU.TES/D:N/L:Y/B:Y/T:Y/C:Y/W:N/A:Y/E:N !
! !
! Switches: !
! !
! /D Delete lexical CR/LFs !
! /L Set line lengths !
! /B Delete blank lines !
! /T Delete lexical TAB/FFs !
! /C Delete comments !
! /W Watch progress !
! /A Automatic mode (ie: squish macros loaded w/^U) !
! /E Allow adjacent ESCapes !
! !
! Use of Q-registers: !
! !
! A.str = macro to run the squish macro in Z; then, if /L is set, !
! post-process the squished macro so each line is no longer the !
! length set by /L:nn. !
! !
! B.num = TRUE if any command line switches were present. !
! !
! C.num = the buffer pointer while squishing things for error !
! reporting purposes. !
! !
! C.str = the set of comment delimiter characters (/C:set, or !
! <SP><TAB> for /C:Y). !
! !
! E.str = macro telling when to break out of squish loop. either !
! on end of file or end of sub-squish loop !
! !
! F.str = SQU initialization and termination macro. !
! !
! H.num = TRUE (-1) if we are allowing adjacent escapes (/E:Y) !
! !
! K.str = the "non-squishable ^U command" character set (/A:set) !
! If we run into a @^Q<delim>text<delim>, and <delim> is *not* !
! in the "non-squishable ^U command" character set, we'll assume !
! that "text" is a macro that we have to recursively squish. !
! !
! O.num = the maximum line width (/L:nn, or 70 for /L) !
! !
! P.str = ???P is cleared if abort-on-error bit is set, and it is !
! executed as a macro during cleanup, but I don't see where it is !
! loaded anywhere. !
! !
! Q.str = used to contain responses from the user. !
! !
! R.str = "get-response-from-user" macro. !
! !
! S.num, T.num, U.num = used to store the start and end of text !
! arguments to TECO commands like FStext1$text2$. !
! !
! W.str = "-1W" scope refresh command if watching progress (/W:Y) !
! !
! Z.str = SQU macro proper !
! !
! 1.num = TRUE (-1) if the following command is @-sign modified !
! !
! 8.str = a string containing potential delimiting characters !
! in case we can't use ESC as a delimiter. this string will be !
! searched for a delimiting character which is not in the string !
! we are trying to delimit. !
! !
! 9.str = a mask containing labels we'll use in a goto. Each !
! character in the mask corresponds with a TECO command character !
! and controls some action the squisher takes when it runs into !
! that TECO command. For example, if the squisher runs into !
! <NUL>, the squisher uses the first character in the 9.str mask !
! as a label to goto which handles <NUL>'s. The mask characters !
! are: !
! !
! 1 command takes character argument !
! A ^A command !
! B delete if line is blank !
! D delete character from output !
! E E command !
! F F command !
! L lowercase char (convert to uppercase) !
! O optionally delete character from output !
! T TAB char !
! U ^U command !
! V ^^ command, leave next char as is !
! Z ^Z command, convert to <CARET>-Z !
! ^ (caret) next char is really CTRL-char !
! $ command takes string argument(s) !
! . (dot) pass character through w/o squishing !
! @ the next command is '@' modified !
! !
! Changes: !
! !
! Nov-89 !
! added comments !
! changed system specific "n,Stext$" to generic "m,nFBtext$" !
! --------------------------------------------------------------------- !
! --------------------------------------------------------------------- !
! Load Q-register F with SQU initialization macro. This macro loads !
! other macros into various Q-registers and handles the command line !
! switches: either taking them from the command line in the edit !
! buffer or prompting the user for them. When this macro is done, !
! SQU will be poised to run and the only thing left in the edit buffer !
! will be the input and output filenames. !
! --------------------------------------------------------------------- !
^UF ! F.str = initialization macro !
^D ! set radix to decimal !
0ED ! zero edit mode flag !
0^X ! zero search mode flag !
ET&128"N ! if abort-on-error bit is not zero !
0,0XP ! clear P.str !
' ! endif !
0,128ET ! turn on abort-on-error bit !
J ! jump to beginning of edit buffer !
< @FS%^ES%%; > ! zap multiple spaces and tabs in edit buffer !
J ! jump to beginning of edit buffer !
:@S%/% ! search for '/' command line switch delimiter !
UB ! put search success into B.num !
QB"T ! if there are switches !
ET&64"E ! if not detached !
@^A%
% ! display <CR><LF> !
' ! endif !
' ! endif !
! --------------------------------------------------------------------- !
! Load Q-register R with a "get-response-from-user" macro. !
! !
! Entry: !
! The last inserted string is the display prompt. !
! !
! The top of the stack is the Q-register name we will return !
! the response in. If the high bit of the Q-register name !
! is set, insist on ESC to terminate the response, otherwise !
! allow the response to be terminated with CR-LF . !
! !
! Returns: !
! Input string in the Q-register you specified on entry. !
! --------------------------------------------------------------------- !
@^UR\ ! R.str = response macro !
[0 [1 [2 [3 ! save Q-reg's 0 through 3 !
+0U3 ! 3.num = Q-reg name on top of stack !
^YX0 ! 0.str = display prompt (last inserted string) !
^YK ! kill display prompt from edit buffer !
.U1 ! 1.num = current buf ptr !
ZJ ! jump to buf end !
.U2 ! 2.num = current end of buffer !
Q3&127"R ! if Q-reg name in 3.num is alphanumeric !
! it's a valid Q-reg name !
| ! else (Q-reg name not alphanumeric) !
! it's not a valid Q-reg name !
@^A%?Invalid Q-register in INPLIN
% ! display error message !
@O!EXIT! ! go down to EXIT !
'
! --------------------------------------------------------------------- !
! build a mini-macro in Q-reg 1 which will put the user's response !
! into the Q-reg we are using to return the user's response in. !
! --------------------------------------------------------------------- !
@I%Q2,.X% ! insert "Q2,.X" into edit buffer !
Q3&127@I%% ! insert Q-reg name we're loading response in !
Q2,.X1 ! put this mini-macro into 1.str !
Q2,.K ! and kill it !
! --------------------------------------------------------------------- !
! display the prompt on a new, clean, line !
! --------------------------------------------------------------------- !
!PROMPT!
13^T ! display <CR> !
ET&512"N ! if scope, clear to end of screen !
0,1ET ! inhibit type-out conversions !
27^T ! display ESCAPE !
1,0ET ! enable type-out conversions !
0:W-4"E ! if VT100 in ANSI mode !
^^[^T ! display [ !
' ! endif !
^^J^T ! display J !
| ! else (not scope) !
10^T ! display <LF> !
' ! endif !
.-Q2+(0^Q)"G ! if anything on current line !
0T ! display it !
| ! else !
:G0 ! display prompt in 0.str !
Q2,ZT ! plus what we've entered so far !
' ! endif !
! --------------------------------------------------------------------- !
! Read characters from the console & insert them into the edit buffer. !
! !
! DEL delete last char entered !
! ^U delete everything entered !
! ^R redisplay prompt & what's been entered !
! ^Z delete everything entered and return !
! <CR>, <LF>, <ESC> terminate input !
! --------------------------------------------------------------------- !
!GETCH!
^TU0 ! get char from console & put in 0.num !
Q0-127"E ! if char is DEL !
Z-Q2"N ! if anything has been added to buffer !
-D ! delete last char !
' ! endif !
@O!PROMPT! ! go up to PROMPT !
' ! endif !
Q0-21"E ! if char is ^U !
Q2,ZK ! kill everything we've entered up to now !
@O!PROMPT! ! go up to PROMPT !
' ! endif !
Q0-18"E ! if char is ^R !
13^T ! display <CR> !
10^T ! display <LF> !
:G0 ! display prompt in 0.str !
Q2,ZT ! display everything we've entered up to now !
@O!GETCH! ! go up to GETCH !
' ! endif !
Q0-26"E ! if char is ^Z !
Q2,ZK ! kill everything we've entered up to now !
%0^[ ! convert ^Z (1Ah) to <ESC> (1Bh) !
' ! endif !
Q0-27"E ! if char is <ESC> !
13^T ! display <CR> !
10^T ! display <LF> !
@O!DONE! ! go down to DONE !
' ! endif !
Q3&128"E ! if hi-bit of return Q-reg name is zero !
Q0-10"E ! if char is <LF> !
13^T ! display <CR> !
@O!DONE! ! go down to DONE !
' ! endif !
Q0-13"E ! if char is <CR> !
^T^[ ! suck up <LF> of <CR>-<LF> pair? !
@O!DONE! ! go down to DONE !
' ! endif !
' ! endif !
Q0@I%% ! insert input char into edit buffer !
@O!GETCH! ! go up to GETCH to get next character !
!DONE!
M1 ! execute mini-macro to load Q-reg w/response !
Q2,.K ! kill everything we added to the input buffer !
!EXIT!
Q1J ! jump back to where we were before we started !
]3 ]2 ]1 ]0 ! restore Q-reg's 0 through 3 !
\ ! end of ^UR !
! --------------------------------------------------------------------- !
! Done loading response macro into Q-register R !
! --------------------------------------------------------------------- !
! --------------------------------------------------------------------- !
! Check for command line switches. Basically, each switch is searched !
! for in the edit buffer: !
! !
! If the switch is not found !
! If there were other switches on the command line !
! Set the switch to its default value !
! else !
! Prompt the user for the value of the switch !
! else !
! If switch followed by ":argument" !
! Set switch to "argument" !
! else !
! Set switch to the opposite of its default !
! !
! While we are checking for switches, we will be building the mask in !
! Q-register 9 !
! --------------------------------------------------------------------- !
! --------------------------------------------------------------------- !
! Check for /D "Delete CR/LF" switch. /D will delete all lexical CR's !
! and LF's. /D:N is the default. The format for the /D switch is: !
! /D:Y or /D:N. /D just by itself is the same as /D:Y. !
! !
! A problem with /D:Y is that the output will probably be all on one !
! line. If you want to delete all CR's and LF's, yet keep the output !
! width manageable, use /L:nn. !
! --------------------------------------------------------------------- !
0,0X9 ! clear mask in 9.str !
J ! jump to beginning of buffer !
:@FS%/D%%"S ! if "/D" found !
::@FS%:%%"S ! if ":arg" found !
0A@^UQ%% ! Q.str = arg !
D ! delete arg !
| ! else (":" not found) !
@^UQ%Y% ! Q.str = "Y" !
' ! endif !
| ! else ("/D" not found) !
QB"T ! if any other switches !
@^UQ%% ! Q.str = "" !
| ! else !
@I%Delete CR/LF (Y/N) <N>? %
^^QMR ! ask for /D value !
' ! endif !
' ! endif !
0QQ"A ! if /D val is alphabetic !
0QQ&95-^^Y"E ! if it's 'y' or 'Y' !
! load 9.str with labels for control chars, with <LF>, !
! <CR>, and <SP> marked as D. !
! !
! %@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ % !
@^U9%DA.......TD..D.......U....Z...V.D%
' ! endif !
' ! endif !
! --------------------------------------------------------------------- !
! Check for /L "Set line lengths" switch. If you're not explicitly !
! deleting all CR/LF's (ie: /D:N), you can still delete CR/LF's which !
! are unecessary yet still keep the width of the output line manageable.!
! The format of the /L switch is: /L, /L:Y, /L:N, or /L:nn where nn is !
! the line length. /L just by itself is the same as /L:Y, and /L:Y is !
! the same as /L:70. If /D is Y then any /L is ignored. !
! !
! Note: the /L switch does delete all lexical CR/LF's; but, after !
! everything is squished, goes back and inserts CR/LF wherever needed !
! so the maximum width of the output line doesn't exceed nn chars. !
! --------------------------------------------------------------------- !
!BADNUM! ! label to re-ask if :nn bad !
0UO ! clear O.num !
:Q9"N ! if we had /D:Y above !
J ! jump to beginning of buf !
:@FS%/L%%"S ! if "/L" found, delete it !
@^A"%/L specified with /D, /L ignored
" ! and warn the user !
::@FS%:%%"S ! if ":arg" found, kill ":" !
0A"D ! if arg is numeric !
< D .-Z; 0A"D > ' ! delete nn !
| ! else !
D ! delete arg !
' ! endif !
' ! endif !
' ! endif !
| ! else (no /D:Y above) !
J ! jump to beginning of buf !
:@FS%/L%%"S ! if "/L" found !
::@FS%:%%"S ! if ":arg" found !
0A@^UQ%% ! Q.str = arg !
0A"D ! if arg is numeric !
< D .-Z; 0A"D 0A:@^UQ%% > ' ! get nn !
| ! else !
D ! delete arg !
' ! endif !
| ! else, just /L !
@^UQ%Y% ! Q.str = "Y" !
' ! endif !
| ! else !
QB"T ! if any other switches !
@^UQ%% ! Q.str = "" !
| ! else !
@I%Set line lengths (Y for 70, N, or length) <N>? %
^^QMR ! ask for /L value !
' ! endif !
' ! endif !
0QQ"A ! if /L val is alphabetic !
0QQ&95-^^Y"E ! if it's 'y' or 'Y' !
! load 9.str with labels for control chars, !
! with <LF>, <CR>, and <SP> marked as O. !
! !
! %@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ % !
@^U9%DA.......TO..O.......U....Z...V.O%
70UO ! set line length to 70 !
' ! endif !
' ! endif !
0QQ"D ! if /L val is numeric !
.UQ ! save current buf ptr !
ZJ ! jump to buf end !
GQ ! put /L str in buffer !
^SC ! go back to /L str begin !
\UO ! put str value in O.num !
^SD ! and delete str !
.-Z"N ! if anything left over !
ZK ! kill chars \ skipped !
QQJ ! jump back to old cp !
@O!BADNUM! ! bad number !
' ! endif !
QQJ ! jump back to old cp !
QO"E ! if /L arg is 0 !
@O!BADNUM! ! bad number !
' ! endif !
! load 9.str with labels for control chars, with <LF>, !
! <CR>, and <SP> marked as O. !
! !
! %@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ % !
@^U9%DA.......TO..O.......U....Z...V.O%
' ! endif !
' ! endif !
! --------------------------------------------------------------------- !
! Check for /B "Delete blank lines" switch !
! --------------------------------------------------------------------- !
:Q9"N ! if we had /D:Y above !
J ! jump to beginning of buf !
:@FS%/B%%"S ! if "/B" found !
::@FS%:%%"S ! if ":arg" found !
0A-^^N"E ! if "/B:N", ignore it !
@^A"%/B:N specified with /D or /L, /B:N ignored
" ! warn user !
' ! endif !
D ! delete arg !
' ! endif !
' ! endif !
| ! else (no /D:Y above) !
J ! jump to beginning of buf !
:@FS%/B%%"S ! if "/B" found !
::@FS%:%%"S ! if ":arg" found !
0A@^UQ%% ! Q.str = arg !
D ! delete arg !
| ! else !
@^UQ%Y% ! Q.str = "Y" !
' ! endif !
| ! else !
QB"T ! if any other switches !
@^UQ%% ! Q.str = "" !
| ! else !
@I%Delete blank lines (Y/N) <N>? %
^^QMR ! ask for /B value !
' ! endif !
' ! endif !
0QQ"A ! if /B val is alphabetic !
0QQ&95-^^Y"E ! if it's 'y' or 'Y' !
! load 9.str with labels for control chars, !
! with <LF> marked as B and <SP> marked as D. !
! !
! %@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ % !
@^U9%DA.......TB..........U....Z...V.D%
' ! endif !
' ! endif !
' ! endif !
! --------------------------------------------------------------------- !
! at this point, if we've specified /D, /L, or /B above, 9.str should !
! hold the labels for the control characters, if it doesn't, we'll !
! supply the default labels which only deletes <NUL> and <SP>. !
! !
! Note: we only have entries for <NUL> to <SP> here. The entry for !
! exclamation point will be put in by the /C checking code below. All !
! other entries are appended to 9.str after switch parsing is finished. !
! --------------------------------------------------------------------- !
:Q9"E ! if 9.str is empty !
! %@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ % !
@^U9%DA.......T...........U....Z...V.D% ! load default mask !
' ! endif !
! --------------------------------------------------------------------- !
! Check for /T "Delete lexical TABs and FFs" switch. The format of !
! the /T switch is: /T, /T:Y, /T:N. /T by itself is the same as /T:Y. !
! If TABs are used to format the macro to be squished, instead of being !
! used to start an insert, you'll have to delete them using /T:Y !
! --------------------------------------------------------------------- !
J ! jump to beginning of buffer !
:@FS%/T%%"S ! if "/T" found !
::@FS%:%%"S ! if ":arg" found !
0A@^UQ%% ! Q.str = arg !
D ! delete arg !
| ! else !
@^UQ%Y% ! Q.str = "Y" !
' ! endif !
| ! else !
QB"T ! if any other switches !
@^UQ%% ! Q.str = "" !
| ! else !
@I%Delete lexical TABs and FORM FEEDs (Y/N) <N>? %
^^QMR ! ask for /T value !
' ! endif !
' ! endif !
0QQ"A ! if /T val is alphabetic !
0QQ&95@^UQ%% ! force it to uppercase !
' ! endif !
! --------------------------------------------------------------------- !
! if /T is "Y", the following code takes the existing control char !
! mask in Q-reg 9 and replaces the TAB and FF entries with "O". The !
! new control char mask is then put back in Q-reg 9. !
! --------------------------------------------------------------------- !
0QQ-^^Y"E ! if /T is 'Y' !
J ! jump to beginning of buffer !
G9 ! load mask into edit buffer !
9J ! jump to TAB entry !
D ! delete existing entry !
@I%O% ! insert "O" !
12J ! jump to FF entry !
D ! delete existing entry !
@I%O% ! insert "O" !
J ! jump to beginning of buffer !
0,33X9 ! put mask back in 9.str !
0,33K ! and clean up edit buffer !
' ! endif !
! --------------------------------------------------------------------- !
! Check for /C "Delete comments" switch. This switch deletes comments !
! as opposed to labels. It is easier if comments are distinguishable !
! from labels by having a special delimiting character immediately !
! following the initial exclamation point. The format of the /C !
! switch is: /C, /C:Y, /C:N, or /C:? where ? is the special comment !
! delimiting character. /C is the same as /C:Y, and /C:Y implies that !
! SPACE and TAB are the special comment delimiters. When done, Q-reg !
! C will contain the special comment delimiting characters. !
! --------------------------------------------------------------------- !
@^UC%% ! C.str = "" !
J ! jump to beginning of buffer !
:@FS%/C%%"S ! if "/C" found !
::@FS%:%%"S ! if ":arg" found !
0A@^UQ%% ! Q.str = arg !
D ! delete arg !
| ! else !
@^UQ%Y% ! Q.str = "Y" !
' ! endif !
| ! else !
QB"T ! if any other switches !
@^UQ%% ! Q.str = "" !
| ! else !
@I%Delete comments (Y for SP/TAB, N, or set) <N>? %
^^QMR ! ask for /C value !
' ! endif !
' ! endif !
:QQ"E ! if Q.str empty !
@^UQ%N% ! Q.str = "N" !
' ! endif !
0QQUQ ! Q.num = ASCII 1st Q.str char !
QQ"V ! if Q.num lowercase !
QQ-32UQ ! force it to uppercase !
' ! endif !
QQ-^^N"E ! if /C == "N" !
:@^U9%A% ! append "A" to 9.str mask !
| ! else !
:@^U9%C% ! append "C" to 9.str mask !
QQ-^^Y"E ! if /C == "Y" !
32@^UC%% ! C.str = <SP> !
9:@^UC%% ! append TAB to C.str !
| ! else (it's a set?) !
GQ ! put /C set in edit buf !
^YXC ! load it into Q-reg C !
^YK ! clean up edit buffer !
' ! endif !
' ! endif !
! --------------------------------------------------------------------- !
! append entries for all other TECO commands to the mask in Q-reg 9. !
! --------------------------------------------------------------------- !
! %"#$%&'()*+,-./0123456789:;<=>?% !
:@^U9%1..1..........................%
! %@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_% !
:@^U9%@....EF1.$...1$$.1.$.1..1..1.1^$%
! %`abcdefghijklmnopqrstuvwxyz{|}<tilde><sp>% !
:@^U9%.LLLLLLLLLLLLLLLLLLLLLLLLLL....D%
! --------------------------------------------------------------------- !
! Load Q-register 8 with potential <delim> characters in case ESC can't !
! be used. We initially load 8.str with the preferred delimiters: !
! !
! / # * & \ ? ( ) $ <exclamation pt> @ !
! !
! in case these can't be used either, we'll also append every ASCII !
! character to 8.str in the hope that something can be used. !
! --------------------------------------------------------------------- !
@^U8%/#*&\?()$!@% ! pre-load 8.str !
1U8 ! put 1 in 8.num !
126< ! this loop appends ASCII chars !
Q8:@^U8%% %8^[ ! CTRL-A to TILDE to 8.str !
>
! --------------------------------------------------------------------- !
! Check for /W "Watch progress" switch !
! --------------------------------------------------------------------- !
@^UW%% ! clear W.str !
ET&512"E ! if not scope, ignore /W !
J ! jump to beginning of buf !
:@FS%/W%%"S ! if "/W" found, delete it !
::@FS%:%%"S ! if ":" found !
D ! delete arg !
' ! endif !
' ! endif !
| ! else (it's a scope) !
J ! jump to beginning of buf !
:@FS%/W%%"S ! if "/W" found !
::@FS%:%%"S ! if ":arg" found !
0A@^UQ%% ! Q.str = arg !
D ! delete arg !
| ! else !
@^UQ%Y% ! Q.str = "Y" !
' ! endif !
| ! else !
QB"T ! if any other switches !
@^UQ%% ! Q.str = "" !
| ! else !
@I%Watch progress (Y/N) <N>? %
^^QMR ! ask for /W value !
' ! endif !
' ! endif !
0QQ"A ! if /W val is alphabetic !
0QQ&95-^^Y"E ! if it's 'y' or 'Y' !
0:W-2"E ! if VT100 in VT52 mode !
4,0:W^[ ! set VT100 in ANSI !
' ! endif !
@^UW/-1W/ ! Q.str = "-1W" (refresh) !
' ! endif !
' ! endif !
' ! endif !
! --------------------------------------------------------------------- !
! Check for /A "Automatic mode". If /A:Y, then if @^U%text% is found, !
! "text" is assumed to something which should *not* be sub-squished; !
! any other character used as a special <delim> *will* be sub-squished. !
! If /A:N, then go into "manual mode" where each time SQU runs into !
! ^Utext, it will ask if you want to sub-squish it. If /A:<char> is !
! a command line switch then use <char> as the "non-squishable" <delim> !
! char. If you're asked for the /A value, then you can enter a set of !
! "non-squishable" <delim> chars. !
! --------------------------------------------------------------------- !
@^UK%% ! clear K.str !
J ! jump to beginning of buffer !
:@FS%/A%%"S ! if "/A" found !
::@FS%:%%"S ! if ":arg" found !
0A@^UQ%% ! Q.str = arg !
D ! delete arg !
| ! else !
@^UQ%Y% ! Q.str = "Y" !
' ! endif !
| ! else !
QB"T ! if any other switches !
@^UQ%Y% ! Q.str = "Y" !
| ! else !
@I/Automatic mode (Y for %, N, or set) <N>? /
^^QMR ! ask for /A value !
' ! endif !
' ! endif !
:QQ"N ! if any /A val !
0QQUQ ! convert /A val to ASCII !
QQ"V ! if /A val lowercase !
QQ-32UQ ! force to uppercase !
' ! endif !
QQ-^^N"N ! if /A not "N" !
QQ-^^Y"E ! if /A == "Y" !
^^%@^UK%% ! K.str = "%" !
| ! else (it's a set?) !
GQ ! put /A set in edit buf !
^YXK ! load it into K.str !
^YK ! clean up edit buffer !
' ! endif !
' ! endif !
' ! endif !
! --------------------------------------------------------------------- !
! Check for /E "Allow adjacent ESCapes" switch. Sometimes squishing !
! will put two escapes together where there weren't two escapes before. !
! For example, @FS/abc// will be squished to @FSabc$$, the two adjacent !
! escapes could be a problem this is in a macro which is EI'd. The !
! format of the /E switch is: /E, /E:N, or /E:Y. /E is the same as !
! /E:Y. /E:N will direct SQU to never generate adjacent escapes where !
! there were none before. !
! --------------------------------------------------------------------- !
0UH ! H.num = 0 (FALSE) !
J ! jump to beginning of buffer !
:@FS%/E%%"S ! if "/E" found !
::@FS%:%%"S ! if ":" found !
0A@^UQ%% ! Q.str = arg !
D ! delete arg !
| ! else !
@^UQ%Y% ! Q.str = "Y" !
' ! endif !
| ! else !
QB"T ! if any other switches !
@^UQ%% ! Q.str = "" !
| ! else !
@I%Allow adjacent ESCapes (Y/N) <N>? %
^^QMR ! ask for /E value !
' ! endif !
' ! endif !
0QQ"A ! if /E val is alphabetic !
0QQ&95-^^Y"E ! if it's 'y' or 'Y' !
-1UH ! H.num = -1 (TRUE) !
' ! endif !
' ! endif !
! --------------------------------------------------------------------- !
! Load Q-register Z with the squisher macro !
! !
! Uses Q-register 1 for @-modified flag while processing and for !
! an error return when through. !
! --------------------------------------------------------------------- !
@^UZ* ! Z.str = squish macro !
[1 ! save Q-reg 1 !
0U1 ! clear @-modifed flag !
:QW"N ! if /W was TRUE !
-1,3:W^[ ! turn on SEEALL mode !
0,4:W^[ ! set no "mark" status !
0,5:W^[ ! turn hold mode off !
' ! endif !
! --------------------------------------------------------------------- !
! main loop start !
! --------------------------------------------------------------------- !
<
!..!
MW ! refresh scope !
!.!
ME; ! break if E macro returns 0 !
0AU0 ! 0.num = char in buffer !
Q0"L ! if char is less than zero !
@O!OFFEND! ! end of file err !
' ! endif !
C ! advance one character !
Q0&128"N ! if char's hi bit is set !
Q0&127U0 ! zero hi bit !
-D ! delete hi bit char !
Q0@I%% ! insert zero hi bit char !
' ! endif !
! --------------------------------------------------------------------- !
! Use the ASCII value of the current char in 0.num as an index into the !
! labels in 9.str, and goto that label. !
! --------------------------------------------------------------------- !
!DISP! ! dispatch !
Q0Q9@^U0%% ! 0.str = Q0th char of 9.str !
@O!^EQ0! ! and jump to it !
! --------------------------------------------------------------------- !
! handle a lowercase character. convert it to uppercase and process !
! it again. !
! --------------------------------------------------------------------- !
!L!
Q0-32U0 ! convert to uppercase !
-D ! delete lowercase char !
Q0@I%% ! insert uppercase char !
@O!DISP! ! try label for uppercase char !
! --------------------------------------------------------------------- !
! handle '^'. the next character is really CTRL-char. we'll delete !
! the "^char" construct, insert the "real" control char, and go back !
! and process it again. we'll watch out for inserting ^[ (<ESC>), we !
! have to be careful about creating adjacent <ESC>'s. !
! --------------------------------------------------------------------- !
!^!
0A&31U0 ! 0.num = ^char !
C ! skip past char !
-2D ! delete both ^ and char !
QH"F ! if no adjacent ESC's !
Q0-27"E ! if ^char is ESC !
0A-27"E ! if next char is ESC !
@I%^[% ! insert a single ESC !
C ! skip past next ESC !
@O!..! ! jump to main loop !
' ! endif !
! ----------------------------------------------------- !
! at this point we are trying to insert an ESC; but we !
! don't know if by doing so we will inadvertently form !
! two adjacent escapes. the following code searches !
! backwards for the last important character (skipping !
! CF/LF's) to see if that last important character was !
! also an ESC. if it was, we'll insert a <SP> to keep !
! the two ESC's lexically apart. !
! ----------------------------------------------------- !
.US ! S.num = cur buf ptr !
0UT ! T.num = 0 !
< ! ----loop begin--------------- !
-.; ! break if .==0 !
R ! back up one char !
0AUT ! T.num = previous char !
QT&128"E ! if hi bit of char zero !
QT-10"N ! if char is not <LF> !
0; ! break out of loop !
| ! else (it is <LF>) !
-.; ! break if .==0 !
-1A-128-13"N ! if not <CR><LF> !
0; ! break out of loop !
' ! endif !
' ! endif !
' ! endif !
> ! ----loop end----------------- !
QSJ ! jump to where we startd !
QT-27"E ! if last char == ESC !
@I% % ! insert <SP> !
' ! endif !
' ! endif !
' ! endif !
Q0@I%% ! insert ^char !
@O!DISP! ! try again !
! --------------------------------------------------------------------- !
! handle 'B'. we've run into the <LF> portion of CR/LF with the /B !
! switch (delete blank lines) set. if there are only two chars on the !
! current line, assume they are CR/LF and delete them. !
! --------------------------------------------------------------------- !
!B!
-1^Q+2"E ! if only 2 chars on this line !
-2D ! delete <CR><LF> !
' ! endif !
@O!..! ! jump to main loop !
! --------------------------------------------------------------------- !
! handle 'O'. we've run into <LF>, <CR>, or <LF> with the /L switch !
! set. !
! --------------------------------------------------------------------- !
!O!
-D ! delete last char !
."N ! if not at beginning of buffer !
-1A&128"N ! if last char hi bit set !
-D ! delete it !
' ! endif !
.-1"G ! if 2 chars past buf begin !
-1A-10"E ! if hi bi of last char set !
-2A-128-13"E ! if 2nd last char = <CR> !
Q0-13"E ! if curr char is <CR> !
-2D ! delete <CR><CR> !
| ! else !
@O!..! ! jump to main loop !
' ! endif !
' ! endif !
' ! endif !
' ! endif !
Q0#128@I%% ! insert char w/hi bit !
Q0-13"E ! if char is <CR> !
.-Z"E ! if at end of buffer !
10@I%% ! insert <LF> !
R ! back up one char !
' ! endif !
0A&127-10"E ! if curr char is <LF> !
D ! delete it !
' ! endif !
10@I%% ! insert <LF> !
' ! endif !
' ! endif !
@O!..! ! jump to main loop !
! --------------------------------------------------------------------- !
! handle 'U'. we've run into ^Uq. usually, the string ^Uq is loading !
! into Q-register q is *not* squished. the problem with ^Uq is that it !
! is sometimes used to load a macro into a Q-register. This macro code !
! should be squished too. What we do is if the ^U is @-modified, and !
! the <delim> is *not* in the "non-squishible ^U command" character set !
! in Q-register K, we assume it is a macro and should be sub-squished. !
! Otherwise, the ^U argument is assumed to be a simple string and is !
! not sub-squished. !
! --------------------------------------------------------------------- !
!U!
27@^U1%% ! 1.str = ESC (default delim) !
.UC ! C.num = current buf ptr !
0AU0 ! 0.num = ^U Q-reg name !
C ! advance past Q-reg name !
Q0-^^."E ! if it's .q (local Q-reg name) !
0AU0 ! 0.num = "real" Q-reg name !
C ! advance past "." !
' ! endif !
Q0"V ! if Q-reg name is lowercase !
Q0-32U0 ! convert it to uppercase !
-D ! delete lowercase char !
Q0@I%% ! insert uppercase char !
' ! endif !
Q1"T ! if @-modified !
0A-(1A)"E ! if @^Uq<delim>text<delim> !
@O!$$! ! goto $$ !
' ! endif !
| ! else !
0A-27"E ! if ^Uq<ESC> !
@O!$$! ! goto $$ !
' ! endif !
' ! endif !
.US ! S.num = current buf ptr !
Q1"T ! if @-modifed !
0A@^U1%% ! 1.str = <delim> !
D ! delete <delim> !
' ! endif !
:QW"N ! if /W was TRUE !
:@S%^EQ1%"U ! if search for <delim> fails !
@O!STRINGFAIL! ! unterminated string !
' ! endif !
.,4:W^[ ! set mark status !
QSJ ! jump back to where we were !
MW ! refresh scope !
' ! endif !
! --------------------------------------------------------------------- !
! if there are no "non-squishable ^U command" characters, you used the !
! /A:N switch. If this is the case, we'll have to drop into "manual" !
! mode: everytime we run into a ^U we'll ask if you want to squish it !
! or not, Y or N. !
! --------------------------------------------------------------------- !
:QK"E ! if no non-squishable ^U delim !
:QW"E ! if /W was FALSE !
0T ! display line up to now !
10^T ! display <LF> !
T ! display rest of line !
' ! endif !
7^T ! display <BEL> !
ETUQ ! save ET flags in Q.num !
ET#8#4-4ET ! turn on read w/o echo !
^TU0 ! read char into 0.num !
QQET ! restore ET flags !
| ! else (non-squishable delims) !
G1 ! put <delim> in buf !
R ! back up one char !
::@S%^EGK%"S ! if <delim> is non-squish !
-D ! delete <delim> !
^^NU0 ! 0.num = N !
| ! else !
D ! delete <delim> !
^^YU0 ! 0.num = Y !
' ! endif !
' ! endif !
:QW"N ! if /W was TRUE !
0,4:W^[ ! clear "mark" status !
32768W ! set huge # of display lines !
' ! endif !
! --------------------------------------------------------------------- !
! at this point, 0.num will be "Y" if we are to sub-squish the ^U text !
! --------------------------------------------------------------------- !
Q0-^^Y"E ! if 0.num is Y !
! ------------------------------------------------------------- !
! Q-register E originally holds ".-Z" (-number of chars until !
! end of the buffer, when zero we're at end of buf). The E !
! macro is executed at the top of the squish loop so we break !
! out of the squish loop when we reach the end of the buf. When !
! we recursively sub-squish a ^U string, we want the squish !
! loop to break out when it reaches the end of the ^U string. !
! Therefore, we'll now load Q-register E with a macro to do so. !
! !
! -1UE E.num == -1 (continue flag) !
! 0A-^^<delim>"E if we've run into <delim> !
! 0UE E.num == 0 (break flag) !
! ' endif !
! QE push -1 or 0 on stack !
! ------------------------------------------------------------- !
[E [C [S ! save Q-reg's E, C, & S !
@^UE%-1UE0A-^^% ! load Q-reg E w/macro start !
0Q1:@^UE%% ! append <delim> to Q-reg E !
:@^UE%"E0UE'QE% ! append macro end to Q-reg E !
MZ ! squish recursively !
]S ]C ]E ! restore Q-reg's C, S & E !
"N ! if recursive MZ failed !
@O!PRIORFAIL! ! announce it !
' ! endif !
C ! advance past end ^U delim !
@O!$$$$! ! goto $$$$ !
' ! endif !
@O!$$$! ! goto $$$ !
! --------------------------------------------------------------------- !
! handle 'T'. we've run into a TAB character, start an insert. !
! --------------------------------------------------------------------- !
!T!
0U1 ! clear @-modified flag !
! --------------------------------------------------------------------- !
! handle '$'. we've run into I, N, O, or S: commands which take a !
! single string argument (ie: commands which contain one <delim>). !
! --------------------------------------------------------------------- !
!$!
27@^U1%% ! 1.str = ESC (default delim) !
.UC ! C.num = current buf ptr !
! --------------------------------------------------------------------- !
! $$, entry point for commands which take two string arguments (ie: !
! commands which contain two <delim>'s). !
! --------------------------------------------------------------------- !
!$$!
.US ! S.num = start of text !
Q1"T ! if @-modified !
0A@^U1%% ! 1.str = <delim> !
D ! delete <delim> !
' ! endif !
! --------------------------------------------------------------------- !
! $$$, entry point for the ^U routine when we are not sub-squishing the !
! ^U argument, but we've already handled being @-modified. !
! --------------------------------------------------------------------- !
!$$$!
:@S%^EQ1%"U ! if search for <delim> fails !
@O!STRINGFAIL! ! unterminated string !
' ! endif !
! --------------------------------------------------------------------- !
! $$$$, entry point for the ^U routine after we've sub-squished a ^U !
! macro. !
! --------------------------------------------------------------------- !
!$$$$!
-D ! delete trailing <delim> !
.UT ! T.num = end of text !
27U0 ! 0.num = ESC (default <delim> !
! --------------------------------------------------------------------- !
! At this point, we have to output a delimited string. !
! !
! 0.num = <delim> !
! C.num = start of command !
! S.num = start of text !
! T.num = end of text !
! !
! --------------------------------------------------------------------- !
!AA!
Q0@^U0%% ! 0.str = <delim> char !
QT-QS"G ! if string is not-empty !
QSJ ! jump to start of string !
.,.+QT-QS:@FB%^EQ0%"S ! if <delim> is in string !
! ----------------------------------------------------- !
! find a <delim> we can use, one which is *not* already !
! in the string. !
! ----------------------------------------------------- !
G8 ! put 8.str into buf !
^Y:X1 ! put 8.str into 1.str !
^YK ! kill 8.str from buf !
0U0 ! clear 0.num !
< ! ----loop begin--------------- !
Q0Q1@^U0%% ! 0.str = Q0th char of Q1 !
QSJ ! jump to start of text !
.,.+QT-QS@FB%^EQ0%; ! break if search fails !
%0-:Q8"E ! if next char last char !
@O!NOQUOTE! ! can't find " char !
' ! endif !
> ! ----loop end----------------- !
Q0Q1U0 ! 0.num = <delim> to use !
QSJ ! jump to start of string !
Q0@I%% ! insert <delim> !
QC-1J ! jump before command !
@I%@% ! insert @ !
2%T^[ ! T.num (end of text) += 2 !
! ----------------------------------------------------- !
' ! endif !
' ! endif !
QTJ ! jump to end of string !
Q0@I%% ! insert <delim> !
0U1 ! clear @-modified flag !
@O!..! ! jump to main loop !
! --------------------------------------------------------------------- !
! handle '1'. we've run into ", %, G, M, Q, U, X, [, or ]. For ", the !
! next character is a conditional execution command. For everything !
! else, the next character is a Q-register name. In either case, if !
! the next char is lowercase, we uppercase it; otherwise, we fall !
! through to the 'V' code below which simply advances past the char. !
! --------------------------------------------------------------------- !
!1!
0A-^^."E ! if it's .q (local Q-reg name) !
C ! advance past "." !
' ! endif !
0A"V ! if lowercase !
0A-32U0 ! convert to uppercase !
D ! delete lowercase char !
Q0@I%% ! insert uppercase char !
@O!.! ! goto . !
' ! endif !
! ... fall through ...!
! --------------------------------------------------------------------- !
! handle 'V'. we've run into <CTRL>-^, simply skip it !
! --------------------------------------------------------------------- !
!V!
C ! simply advance past it !
@O!.! ! goto . !
! --------------------------------------------------------------------- !
! handle '@'. the following command is @ modified, set a flag in 1.num !
! so we know to look for the alternate delimiter characters. !
! !
! even though <delim> characters will be specified along with the '@' !
! command, we'll try to use ESC whenever possible and convert the @ !
! modified command back into a "normally" delimited command. !
! --------------------------------------------------------------------- !
!@!
-1U1 ! set @-modified flag !
! ...fall through ... !
! --------------------------------------------------------------------- !
! handle 'D'. delete the character from the output file !
! --------------------------------------------------------------------- !
!D!
-D ! delete last character !
@O!.!
! --------------------------------------------------------------------- !
! handle 'F'. we've run into a F', F<. F>, F|, FB, FC, FD, FK, FN, FR, !
! FS, or F_ command. !
! --------------------------------------------------------------------- !
!F!
27@^U1%% ! 1.str = ESC (default delim) !
.UC ! C.num = current buf ptr !
0AU0 ! 0.num = 2nd command char !
C ! advance past 2nd cmd char !
Q0"V ! if 2nd cmd char is lowercase !
Q0-32U0 ! convert it to uppercase !
-D ! delete lowercase char !
Q0@I%% ! insert uppercase char !
' ! endif !
! --------------------------------------------------------------------- !
! the FB and FR commands take a single string argument, goto $$ !
! the FC, FS, FN, and F_ commands take two string arguments, goto F$$ !
! !
! ???What about FD and FK taking 1 string argument !
! --------------------------------------------------------------------- !
Q0-^^B"E ! if it's FB !
@O!$$! ! goto $$ !
' ! endif !
Q0-^^C"E ! if it's FC !
@O!F$$! ! goto F$$ !
' ! endif !
Q0-^^R"E ! if it's FR !
@O!$$! ! goto $$ !
' ! endif !
Q0-^^S"E ! if it's FS !
@O!F$$! ! goto F$$ !
' ! endif !
Q0-^^N"E ! if it's FN !
@O!F$$! ! goto F$$ !
' ! endif !
Q0-^^_"E ! if it's F_ !
@O!F$$! ! goto F$$ !
' ! endif !
@O!.!
! --------------------------------------------------------------------- !
! handle FC, FS, FN, and F_ commands which take two string arguments, !
! there are three possible formats for these commands: !
! !
! Fx <delim> <delim> !
! Fx text <delim> <delim> !
! Fx text1 <delim> text2 <delim> !
! !
! we first have to find the starting and ending points of the text !
! arguments. we set S.num to be the start of text1, we look for the !
! 1st <delim>, delete it, and set T.num to be the start of text2. we !
! then look for the 2nd <delim>, delete it, and set U.num to be the !
! end of text2. !
! !
! if S.num == T.num & T.num == U.num, then we have: FS$$ !
! if S.num <> T.num & T.num == U.num, then we have: FStext$$ !
! if S.num <> T.num & T.num <> U.num, then we have: FStext1$text2 !
! --------------------------------------------------------------------- !
!F$$!
.US ! S.num = start of text1 !
27@^U1%% ! 1.str = ESC (default delim) !
Q1"T ! if @-modified !
0A@^U1%% ! 1.str = <delim> !
D ! delete <delim> !
' ! endif !
:@S%^EQ1%"U ! if search for 1st delim fails !
@O!STRINGFAIL! ! unterminated string !
' ! endif !
-D ! delete 1st <delim> !
.UT ! T.num = start of text2 !
:@S%^EQ1%"U ! if search for 2nd delim fails !
@O!STRINGFAIL! ! unterminated string !
' ! endif !
-D ! delete 2nd <delim> !
.UU ! U.num = end of text2 !
QH"T ! if allow adjacent escapes !
27U0 ! 0.num = ESC !
Q0@^U0%% ! 0.str = ESC !
QU-QS"G ! if we have text1 & text2 !
QSJ ! jump to start of text1 !
.,.+QU-QS:@FB%^EQ0%"U ! if search for ESC fails !
@O!F0! ! use ESC as <delim> !
' ! endif !
| ! else (no text arguments) !
@O!F0! ! use ESC as DELIM !
' ! endif !
| ! else (don't allow adjacent $) !
QU-QT"G ! if we have text2 !
27U0 ! 0.num = ESC !
Q0@^U0%% ! 0.str = ESC !
QSJ ! jump to start of text1 !
.,.+QU-QS:@FB%^EQ0%"U ! if search for ESC fails !
@O!F0! ! done w/F !
' ! endif !
' ! endif !
' ! endif !
! --------------------------------------------------------------------- !
! if we reach this point, there is a danger of putting adjacent ESC's !
! in the output. we will try to find a character that's not in the !
! string we're delimiting and use that as a <delim> character instead !
! of ESC. basically, we search "text1text2" looking for each character !
! in G8, trying to find a delimiter char that's not already in the !
! string. !
! --------------------------------------------------------------------- !
G8 ! put 8.str into buf !
^Y:X1 ! put 8.str into 1.str !
^YK ! kill 8.str from buf !
0U0 ! 0.num = 0 !
< ! loop begin------------------- !
Q0Q1@^U0%% ! 0.str = 0.num'th char of Q1 !
QSJ ! jump to start of text1 !
.,.+QU-QS@FB%^EQ0%; ! break if 0.str search fails !
%0-:Q8"E ! inc 0.num, if end of 8.str !
@O!NOQUOTE! ! can't find " char !
' ! endif !
> ! loop end--------------------- !
! --------------------------------------------------------------------- !
! at this point, we've found our <delim> char, it's index is in 0.num !
! --------------------------------------------------------------------- !
Q0Q1U0 ! 0.num = Q0th char of Q1 !
QSJ ! jump to start of text1 !
Q0@I%% ! insert <delim> !
QC-1J ! jump 1 char before F command !
@I%@% ! insert @ !
2%T^[ ! T.num (end of text1) += 2 !
2%U^[ ! U.num (end of text2) += 2 !
!F0!
QTJ ! jump to end of text1 !
Q0@I%% ! insert <delim> !
QU-QTC ! advance to end of text2 !
Q0@I%% ! insert <delim> !
0U1 ! clear @-modified flag !
@O!..! ! jump to main loop !
! --------------------------------------------------------------------- !
! handle 'A'. we've run into ^Atext^A or @^A/text/. This is also the !
! entry point for the 'C' routine: if we're not deleting the comment !
! we handle <exclamation-point>comment<exclamation-point> just like !
! ^Atest^A. !
! --------------------------------------------------------------------- !
!A!
Q0@^U1%% ! 1.str = ^A or exclamation pt. !
.UC ! C.num = start of text !
.US ! S.num = start of text !
Q1"T ! if @-modified !
0A@^U1%% ! 1.str = <delim> !
D ! delete <delim> !
' ! endif !
:@S%^EQ1%"U ! if search for <delim> fails !
@O!STRINGFAIL! ! unterminated string !
' ! endif !
-D ! delete second <delim> !
.UT ! T.num = end of text !
@O!AA! ! goto AA !
! --------------------------------------------------------------------- !
! handle 'C'. we've run into an exclamation point with the /C switch !
! set. Q-register C contains the special comment delimiter characters. !
! --------------------------------------------------------------------- !
!C!
::@S%^EGC%"U ! if not special comment delim !
@O!A! ! handle like ^Astring^A !
' ! endif !
R ! back up past special <delim> !
.UC ! C.num = current buf ptr !
Q0@^U1%% ! 1.str = exclamation point !
Q1"T ! if @-modified !
0A@^U1%% ! 1.str = <delim> !
D ! delete <delim> !
' ! endif !
:@S%^EQ1%"U ! if search for <delim> failed !
@O!STRINGFAIL! ! unterminated string !
' ! endif !
QC-1,.K ! kill entire comment !
0U1 ! clear @-modified flag !
@O!..! ! jump to main loop !
! --------------------------------------------------------------------- !
! handle 'E'. we've run into an E command. !
! --------------------------------------------------------------------- !
!E!
27@^U1%% ! 1.str = ESC (default delim) !
.UC ! C.num = current buf ptr !
0AU0 ! 0.num = 2nd command char !
C ! advance past 2nd cmd char !
Q0"V ! if 2nd cmd char is lowercase !
Q0-32U0 ! convert to uppercase !
-D ! delete lowercase char !
Q0@I%% ! insert uppercase char !
' ! endif !
! --------------------------------------------------------------------- !
! the EB, EG, EI, EN, ER, EW, E_ commands take a string argument, they !
! have to be passed to the $$ routine. !
! ???What about EL, EQq, EZ, and E%q taking a string argument !
! --------------------------------------------------------------------- !
Q0-^^B"E ! if it's EB !
@O!$$! ! goto $$ !
' ! endif !
Q0-^^G"E ! if it's EG !
@O!$$! ! goto $$ !
' ! endif !
Q0-^^I"E ! if it's EI !
@O!$$! ! goto $$ !
' ! endif !
Q0-^^N"E ! if it's EN !
@O!$$! ! goto $$ !
' ! endif !
Q0-^^R"E ! if it's ER !
@O!$$! ! goto $$ !
' ! endif !
Q0-^^W"E ! if it's EW !
@O!$$! ! goto $$ !
' ! endif !
Q0-^^_"E ! if it's E_ !
@O!$$! ! goto $$ !
' ! endif !
@O!.!
! --------------------------------------------------------------------- !
! handle 'Z'. we've run into a ^Z, replace it with <CARET>-Z !
! --------------------------------------------------------------------- !
!Z!
-D ! delete <CTRL>-Z !
@I%^Z% ! insert <CARET>-Z !
@O!..! ! jump to main loop !
> ! main loop end---------------- !
! --------------------------------------------------------------------- !
! At this point, everything should be squished and Q1 will be -1 if !
! an error occurred, or 0 if everything is OK. !
! --------------------------------------------------------------------- !
Q1"T ! if error flag !
@^U1%Trailing, pending @% ! !
@O!ERROR! ! goto error display !
' ! endif !
0U1 ! clear Z-macro return value !
! --------------------------------------------------------------------- !
! the only way the following error reporting code is executed is if we !
! jump to a label inside of it. if we arrive here by any other means !
! then things are OK, skip down to the "endif". !
! --------------------------------------------------------------------- !
0"N ! skip the following code !
!OFFEND!
@^U1%End of buffer while sub-squishing%
@O!ERROR!
!NOQUOTE!
@^U1%Can't find a quote character%
@O!SETPOS!
!PRIORFAIL!
@^U1%Prior recursion level failed%
@O!SETPOS!
!STRINGFAIL!
@^U1%Unterminated string%
! --------------------------------------------------------------------- !
! the following code finishes building an error string in Q-register 1. !
! 1.str already contains the type of error, this code appends the !
! position where the error occurred and the line before and after the !
! error, like so: !
! !
! <error message> from squished .=<error position> !
! <line up to error>| !
! |<line after error> !
! !
! --------------------------------------------------------------------- !
!SETPOS!
:@^U1% from squished .=% ! append msg to 1.str !
QC\ ! position in C.num to buf !
^Y:X1 ! append position in buf !
^YK ! delete position from buf !
13:@^U1%% ! append <CR> !
10:@^U1%% ! append <LF> !
QCJ ! jump to where error starts !
0^Q+.,.:X1 ! append line up to error !
^^|:@^U1%% ! append | !
10:@^U1%% ! append <LF> !
^^|:@^U1%% ! append | !
.,^Q+.:X1 ! append rest of line !
!ERROR!
ZJ ! jump to buf end !
MW ! refresh scope !
0,0XW ! clear W.str (/W switch) !
7^T ! sound bell !
^^?^T ! display "?" !
:G1 ! display 1.str !
7^T ! sound bell !
13^T ! display <CR> !
10^T ! display <LF> !
-1U1 ! set Z-macro return to -1 !
' ! endif !
Q1 ! push Z-macro return val !
]1 ! restore Q-reg 1 !
* ! end of ^UZ !
! --------------------------------------------------------------------- !
! Done loading squisher macro into Q-register Z !
! --------------------------------------------------------------------- !
! --------------------------------------------------------------------- !
! Load squish driver macro into Q-register A !
! --------------------------------------------------------------------- !
@^UA* ! A.str = squish driver macro !
-1^X ! search flag = exact matches !
@^UE%.-Z% ! E.str = -# chars to buf end !
QO"N ! if max line length not 0 !
ZJ ! jump buf end !
@I% % ! insert <SP>, insure we halt !
' ! endif !
J ! jump to beginning of buffer !
MZ"E ! if squish macro returns OK !
! ------------------------------------------------------------- !
! at this point, everything is squished; but, if the /L switch !
! was set, we've deleted all lexical CR/LF's and have to go !
! back and insert CR/LF wherever needed so the line is no !
! longer than the width specified with /L:nn. !
! ------------------------------------------------------------- !
QO"N ! if max line length not 0 !
:QW"N ! if /W was TRUE !
-1,3:W^[ ! turn on SEEALL mode !
0,4:W^[ ! clear "mark" status !
0,5:W^[ ! turn off hold mode !
' ! endif !
J ! jump to beginning of buf !
< ! ----loop begin--------------- !
MW ! refresh scope !
! --------------------------------------------- !
! the following loop advances through the edit !
! buffer, looking for a character with the high !
! bit set. !
! --------------------------------------------- !
< ! ------loop begin------------- !
0A&128"N ! if high bit is set !
0; ! break out of loop !
' ! endif !
C ! advance 1 char !
> ! ------loop end--------------- !
0A&127-13"E ! if char is <CR> !
D ! delete it !
' ! endif !
D ! delete <LF> !
.-Z; ! break if at end of buf !
.U0 ! 0.num = current buf ptr !
! --------------------------------------------- !
! --------------------------------------------- !
< ! ------loop begin------------- !
0A&128"N ! if hi bit clear !
0; ! break out of loop !
' ! endif !
C ! advance 1 char !
> ! ------loop end--------------- !
! --------------------------------------------- !
! --------------------------------------------- !
< ! ------loop begin------------- !
.U1 ! 1.num = cur buf ptr !
0L ! go to begin of line !
.-Q0-1"L ! if !
0; ! break out of loop !
' ! endif !
R ! back up one char !
> ! ------loop end--------------- !
Q1J
-(0^Q)-QO"G ! if !
Q0J ! !
-1A-27"E ! if last char was ESC !
@I% % ! insert <SP> !
' ! endif !
@I%
% ! insert <CR><LF> !
' ! endif !
> ! ----loop end----------------- !
! ----------------------------------------------------- !
! the following loop deletes trailing CR's, LF's, and !
! <SP>'s from the end of the buffer !
! ----------------------------------------------------- !
< ! ----loop begin--------------- !
ZJ ! jump to buf end !
-Z; ! break if buf empty !
-1A-10"N ! is it LF? !
-1A-13"N ! is it CR? !
-1A-32"N ! is it <SP>? !
0; ! break !
' ! endif !
' ! endif !
' ! endif !
-D ! delete it !
> ! ----loop end----------------- !
MW ! refresh scope !
' ! endif !
! ------------------------------------------------------------- !
! make sure the edit buffer ends in a CR/LF. !
! ------------------------------------------------------------- !
QH"F ! if no adjacent escapes !
ZJ ! jump to buf end !
."E ! if at beginning of buf !
10@I%% ! insert <LF> !
' ! endif !
-1A-10"N ! if prev char is not <LF> !
10@I%% ! insert <LF> !
' ! endif !
R ! back up one char !
."E ! if at beginning of buf !
13@I%% ! insert <CR> !
' ! endif !
-1A-13"N ! if prev char is not <CR> !
13@I%% ! insert <CR> !
' ! endif !
' ! endif !
ZJ ! jump to buf end !
! ------------------------------------------------------------- !
! clean up the scope !
! ------------------------------------------------------------- !
:QW"N ! if /W was TRUE !
0:W-4"E ! if VT100 in ANSI mode !
2,0:W^[ ! set VT100 in VT52 mode !
' ! endif !
-1,3:W^[ ! turn on SEEALL mode !
0,4:W^[ ! clear "mark" status !
MW ! refresh scope !
' ! endif !
| ! else (Z macro returned err) !
@^A/?Squish run failed; aborting any output
/ ! warn user !
0,0XF ! clear F.str !
' ! endif !
0^X ! reset search mode flag !
* ! end of ^UA !
! --------------------------------------------------------------------- !
! Done loading squish driver macro into Q-register A !
! --------------------------------------------------------------------- !
! --------------------------------------------------------------------- !
! If nothing is in the edit buffer, as them to input the name of the !
! input file and insert it into the buffer. !
! --------------------------------------------------------------------- !
Z"E ! if edit buffer is empty !
@I%File <.TES or .TEC>? % ! ask for input file !
^^QMR ! get response in Q.str !
GQ ! and put it into the buffer !
' ! endif !
0,0XR ! clear R.str (response macro) !
0,0XQ ! clear Q.str (user responses) !
 ! end of ^UF !
! --------------------------------------------------------------------- !
! Done loading initialization macro into Q-register F !
! --------------------------------------------------------------------- !
 ! execute everything up until this point !
! --------------------------------------------------------------------- !
! S t a r t H e r e !
! --------------------------------------------------------------------- !
@EI%% ! close current EI command !
MF ! execute initialization macro in F.str !
0,0XF ! clear F.str !
Z"E ! if no command line in buffer !
@^A%Enter your macro then type MA$$
% ! ask them to input a macro to squeeze !
| ! else (the buffer isn't empty) !
! ------------------------------------------------------------- !
! If the edit buffer isn't empty, it must contain the input !
! filename, and it might contain the output filename like so: !
! !
! [OUTFILE[.TEC]=]INFILE[.TES] !
! !
! Executing the F macro above has stripped all the switches !
! from the command line in the edit buffer. !
! !
! First, deal with an output filename. If an output filename !
! exists on the command line, we might append a .TEC filetype !
! to it if a filetype wasn't specified. Then we'll load Q-reg !
! F with "EWfilename$" to open it for output and remove the !
! output filename from the buffer. !
! ------------------------------------------------------------- !
J ! jump to start of buffer !
:@FS%=%%"S ! if "=" found, have output fn !
@^UF%EW% ! put "EW" in F.str !
0,.:XF ! append fn to F.str !
.UF ! put cp in F.num !
-:@S%.%"U ! if no ".", no file type !
:@^UF%.TEC% ! append ".TEC" !
' ! endif !
QFJ ! jump to end of filename !
27:@^UF%% ! append ESC to F.str !
QB"T ! if any switches !
ET&64"E ! if not detached !
:@^UF/ ! append create msg to F !
@^A%Creating "%
:G* ! append last filespec !
@^A%"
% ! append "<CR><LF> !
/ ! done loading F.str !
' ! endif !
' ! endif !
0,.K ! kill output fn in buffer !
' ! endif !
! ------------------------------------------------------------- !
! Now, deal with an input filename. If the filename doesn't !
! have a filetype, first we'll try .TES; and, if there is no !
! .TES file, we'll try .TEC. Once we have an input filename, !
! we'll ER it. !
! ------------------------------------------------------------- !
J ! jump to start of buf !
:@S%.%"U ! if no ".", no filetype !
ZJ ! jump to buf end !
@I%.TES% ! insert ".TES" !
HXQ ! put input fn in Q.str !
:@ER%^EQQ%"U ! if ".TES" doesn't exist !
-@FS%.TES%.TEC% ! try ".TEC" !
' ! endif !
' ! endif !
HXQ ! Q.str = input filename !
HK ! kill buffer !
@ER%^EQQ% ! open input file !
QB"T ! if any switches !
ET&64"E ! if not detached !
@^A%Squishing "%! display squish message" !
:G* ! display filespec buffer !
@^A%"
% ! display "<CR><LF> !
' ! endif !
' ! endif !
! ------------------------------------------------------------- !
! If there's no output filename, we'll stay in TECO after !
! squishing the input file. If there is an output file, we'll !
! exit TECO after squishing. !
! ------------------------------------------------------------- !
:QF"E ! if no output filename !
Y ! yank 1st page !
128,0ET ! turn off abort-on-error !
< ! ----loop begin--------------- !
^E"T ! if formfeed flag !
ZJ ! jump to buf end !
12@I%% ! insert <FF> !
' ! endif !
:A; ! break if append fails !
> ! ----loop end----------------- !
MA ! squeeze page !
MP ! ??? what's in Q-reg P ??? !
| ! else (we have an output fn) !
Y ! yank 1st page !
QB"F ! if no switches !
128,0ET ! turn off abort-on-error !
' ! endif !
! ----------------------------------------------------- !
! if we're at end-of-file after yanking in the first !
! page, then squeeze what we've read in and write it !
! out. If we're not at end-of-file, then we'll have !
! to go into a loop: squeezing the page we have, and !
! then reading in the next page. !
! ----------------------------------------------------- !
^N"T ! if at end-of-file !
^E"T ! if formfeed flag !
ZJ ! jump to buf end !
12@I%% ! insert <FF> !
' ! endif !
MA ! squeeze page !
MF ! open output file !
HPW ! write page !
HK ! kill page !
| ! else !
MF ! open output file !
< ! ------loop begin------------- !
^E"T ! if formfeed flag !
ZJ ! jump to buf end !
12@I%% ! insert <FF> !
' ! endif !
MA ! squeeze current page !
HPW ! write current page !
HK ! kill current page !
:Y; ! break if yank fails !
> ! ------loop end--------------- !
' ! endif !
EF ! close output file !
EX ! exit !
' ! endif !
' ! endif !