Varsig

Varsig is a variant by User:Zzo38 of SIG.

There are two data structures, a stack (initialized empty) and a tape (initialized to all zeros). The tape is infinite both ways. There are also 26 variables A to Z, all initialized to zero. You can't change the variable normally, but at the beginning of each run, if that variable has been read any number of times during the previous run, it is incremented at the beginning of the run. The program executes all the codes in order on each run, and won't stop until EXIT command is executed. Any "number" can be any non-negative integer, or a letter A to Z to use the current value of that variable.

Commands

 * SIG number ... TERM = Creates a signal block, it executes the commands inside the block if that signal with that number has been tripped during the previous run. You are allowed to nest the blocks.
 * MEASURE number = Changes the number of bits that a stored number in the stack or tape uses. Any values stored there will keep only that number of least significant bits. The initial measure is however many bits is used for the input/output. If it is set to more than the current measure, then the values are unchanged, but if changed to less than the current value, only the least significant bits are kept of the values on the stack and tape. If set to zero, everything is zero. Does not affect variables A to Z or numbers that are parameters to commands or signal numbers.
 * TRIP number = Trips the signal so it will execute during the next run. Does not affect subsequent runs unless it is tripped during that run also.
 * RESET number = Untrips a signal so it doesn't execute during the next run. It undoes TRIP command effect.
 * PRY = Input a byte/character, push to stack. If there is nothing to input, it will push nothing to the stack.
 * CRAM = If stack is not empty, pop 1 value and output that byte/character.
 * EXIT = Ends the execution of the program.
 * LESS command</tt> = Executes that command if value on tape is less than value at top of stack. Does not pop the stack. If stack is empty the condition is always false. The command cannot be SIG or TERM.
 * MORE command</tt> = Executes that command if value on tape is greater than value at top of stack. Does not pop the stack. If stack is empty the condition is always false. The command cannot be SIG or TERM.
 * GOOD command</tt> = Executes that command if value on tape is equal to value at top of stack. Does not pop the stack. If stack is empty the condition is always true. The command cannot be SIG or TERM.
 * EVIL command</tt> = Executes that command if value on tape is not equal to value at top of stack. Does not pop the stack. If stack is empty the condition is always true. The command cannot be SIG or TERM.
 * CLEAN command</tt> = Execute that command if stack is empty. The command cannot be SIG or TERM.
 * DIRTY command</tt> = Execute that command if stack is not empty. The command cannot be SIG or TERM.
 * GROW</tt> = Pop a number from stack, it is added to the value on the tape. Does nothing if stack is empty.
 * GROW number</tt> = That number is added to the value on the tape.
 * SHRINK</tt> = Pop a number from stack, it is subtracted from the value on the tape. Does nothing if stack is empty.
 * SHRINK number</tt> = That number is subtracted from the value on the tape.
 * PURGE</tt> = Sets value at tape to zero.
 * BURN</tt> = Discards the top value of stack if there is anything there.
 * SHOVE</tt> = Push value from tape to stack.
 * SHOVE number</tt> = Push that number to stack.
 * YANK</tt> = Pop a value from stack, sets the value on tape to that value. Does nothing if stack is empty.
 * CLONE</tt> = Duplicate top value of stack. Does nothing if the stack is empty.
 * <tt>PUSH</tt> = Advances the tape forward one space.
 * <tt>PULL</tt> = Advances the tape backward one space.
 * <tt>PUSH number</tt> = Advances the tape forward by that number of spaces.
 * <tt>PULL number</tt> = Advances the tape backward by that number of spaces.
 * <tt>FLIP</tt> = Flips the tape over so you can read/write on the other side. The pointer and measure and stuff is common to both sides. However, the direction is reversed, so forward on one side is backward on the other side, when using PUSH and PULL commands.

Comments can be done between /* and */

Shortcut symbols
{ SIG } TERM " MEASURE ^ TRIP . RESET ( PRY ) CRAM < LESS > MORE = GOOD ? EVIL _ CLEAN & DIRTY + GROW - SHRINK \ PURGE | BURN ! SHOVE ~ YANK : CLONE ] PUSH [ PULL % FLIP
 * 1) EXIT

Examples
Example of FLIP command: PUSH FLIP PUSH FLIP /* pointer is right where is was at the start */ PUSH FLIP PULL FLIP /* pointer is 2 spaces advanced */ PUSH 2 PUSH FLIP PUSH 4 PULL PUSH FLIP FLIP FLIP /* pointer is 1 space behind */

Copy input to output forever: PRY CRAM

Copy input to output until EOF: PRY CLEAN EXIT CRAM

Writes the input backwards to the output: /* Assumes 8-bit I/O */ CLEAN TRIP 0 SIG 0 MEASURE 9 SHOVE 321 CLONE YANK TRIP 1 TERM SIG 1 SHOVE 321 PRY GOOD TRIP 2 EVIL TRIP 1 TERM SIG 2 BURN CLEAN EXIT CRAM TRIP 2 TERM

Same as above but with shortcut symbols: _^0 {0"9!321:~^1} {1!321(=^2?^1} {2|_#)^2}