EMIT: filter pages to LPT.
The main difference between 'emit' for DOS and Linux is that the DOS port only accepts the printer as output
port. You simply cannot emit pages to a file.
The options 'odd', 'even' and the range specifiers can be mixed at will. This can produce silly looking
command lines such as 'emit odd even [1..99]' for a 3 page document, but emit does not care. Remember, we're
programming in Modula-2. Not in one of the curly-braces-languages.
Emit will filter out the printer-setup and -reset sequences from the source streams. It does not need a
configuration file. It only expects a stream of data whereby each page is terminated by a Formfeed token
(ASCII 12 or ^L). If, right after an ASCII 12 (FF, ^L) comes an ASCII.ESC token, the printer reset string is
expected.
In the following source code, the Mocka/Linux and the FST/DOS versions are printed right above eachother for
easy comparison.
Emit source.
MODULE emit03; (* FST/DOS *)
(* This software is released under the rules of the GNU GPL.
Please feel free to improve this software, if needed. You may even
port this source to a lesser language like C.
This software comes without any warranty of any kind. *)
(* Emit is meant to filter out data from piped streams with the options
odd, even or [range]. This program will be most efficent when it is
combined with soup (qv). *)
(* 01 : get it working for 'odd', 'even' and 'range' May 28, 2003 *)
(* 02 : add -h, -v, -a and -e options May 29, 2003 *)
(* 03 : port it to FST Modula-2 for DOS Oct 9, 2003 *)
IMPORT ASCII; (* FST/DOS *)
FROM InOut IMPORT Read, Write, WriteLn, WriteLine, WriteString,
RedirectOutput, CloseOutput;
FROM Strings IMPORT CompareStr;
FROM System IMPORT GetArg, Terminate;
FROM Xchar IMPORT UpperString;
TYPE pageMODE = (Odd, Even, Range);
VAR ch : CHAR;
page, low, high : CARDINAL;
PageMode : SET OF pageMODE;
PageOK : BOOLEAN;
PROCEDURE UserMessage (nr : CARDINAL); (* FST/DOS *)
BEGIN
WriteLn;
CASE nr OF
1 : WriteString ('Illegal character in range digits: ') |
2 : WriteLine ('Program aborted. Check syntax with emit -h.'); |
3 : WriteString ('Range identifier syntax error.') |
4 : WriteString ('Illegal commandline parameter: ') |
5 : WriteLine ('This is version 0.3 (DOS) of emit.') |
6 : WriteLine ('Syntax : emit {odd} {even} {[low..high]} -{E|A|V|H|?}');
WriteLn;
WriteString ('emit will let through all the specified pages ');
WriteLine ("as defined by 'odd', 'even'");
WriteLine ('and/or the range specifier.');
WriteLn;
WriteString ('The range MUST comply to the format [first..last] ');
WriteLine ('INCLUDING the TWO dots');
WriteLine ('and both square brackets.');
WriteLn;
WriteLine ('emit odd relay all odd pages');
WriteLine ('emit odd [4..6] relay only page 5');
WriteLine ('emit even [2..7] relay pages 2, 4 and 6');
WriteLine ('emit odd even [1..20] output pages 1 thru 20');
WriteLine ('emit [1..20] the same');
WriteLn;
WriteLine ('emit accepts options prefixed by a hyphen "-". They are:');
Write (ASCII.HT);
WriteLine ('emit -Email -Author -Help -Version');
WriteLine ('although only one option may be present at a time.') |
7 : WriteLine ('E-mail address of owner: fruttenboel@tomaatnet.nl'); |
8 : WriteLine ('This software was made by a member of the WISclub.');
WriteLine ('Check http://wisclub.fol.nl.')
ELSE
WriteString ('Strange error encountered. Inform fruttenboel@tomaatnet.nl.');
WriteLn
END
END UserMessage;
PROCEDURE GetRange (str : ARRAY OF CHAR; VAR lo, hi : CARDINAL); (* FST/DOS *)
VAR i, digit : CARDINAL;
BEGIN
INCL (PageMode, Range);
i := 1; lo := 0; hi := 0;
REPEAT
IF (i > HIGH (str)) OR (str [i] < '0') OR (str [i] > '9') THEN
UserMessage (1); WriteString (str); UserMessage (2);
Terminate (1)
END;
lo := lo * 10;
lo := lo + ORD (str [i]) - ORD ('0');
INC (i)
UNTIL str [i] = '.';
INC (i);
IF str [i] # '.' THEN
UserMessage (3);
Terminate (3)
END;
INC (i);
REPEAT
IF (i > HIGH (str)) OR (str [i] < '0') OR (str [i] > '9') THEN
UserMessage (1); WriteString (str); UserMessage (2);
Terminate (1)
END;
hi := hi * 10;
hi := hi + ORD (str [i]) - ORD ('0');
INC (i)
UNTIL str [i] = ']';
IF lo > hi THEN
i := lo;
lo := hi;
hi := i
END;
IF NOT (Even IN PageMode) AND NOT (Odd IN PageMode) THEN
INCL (PageMode, Odd);
INCL (PageMode, Even)
END
END GetRange;
PROCEDURE Init; (* FST/DOS *)
VAR count, i : CARDINAL;
option : ARRAY [0..15] OF CHAR;
BEGIN
LOOP
GetArg (option, count);
IF count > 0 THEN
UpperString (option);
IF CompareStr (option, 'ODD') = 0 THEN INCL (PageMode, Odd)
ELSIF CompareStr (option, 'EVEN') = 0 THEN INCL (PageMode, Even)
ELSIF option [0] = '[' THEN GetRange (option, low, high)
ELSIF option [0] = '-' THEN
CASE option [1] OF
'H', '?' : UserMessage (6) |
'V' : UserMessage (5) |
'E' : UserMessage (7) |
'A' : UserMessage (8)
END;
Terminate (0)
ELSE
UserMessage (4); WriteString (option); UserMessage (2);
Terminate (4)
END
ELSE
EXIT
END
END;
IF NOT (Odd IN PageMode) AND NOT (Even IN PageMode) THEN
INCL (PageMode, Odd);
INCL (PageMode, Even)
END;
page := 1
END Init;
PROCEDURE CheckPage;
BEGIN
IF ((Odd IN PageMode) AND (ODD (page))) OR ((Even IN PageMode) AND (NOT ODD (page))) THEN
IF Range IN PageMode THEN
IF (page >= low) AND (page <= high) THEN
PageOK := TRUE
ELSE
PageOK := FALSE
END
ELSE
PageOK := TRUE
END
ELSE
PageOK := FALSE
END
END CheckPage;
BEGIN
Init;
RedirectOutput ("PRN");
REPEAT (* Make sure Printer Setup string is sent *)
Read (ch);
Write (ch)
UNTIL ch = ASCII.EOL;
LOOP (* The main printing loop *)
CheckPage;
IF PageOK THEN
REPEAT
Read (ch);
IF ch = ASCII.ESC THEN EXIT END;
IF ch # ASCII.LF THEN Write (ch) END;
UNTIL ch = ASCII.FF;
ELSE
REPEAT
Read (ch);
IF ch = ASCII.ESC THEN EXIT END
UNTIL ch = ASCII.FF
END;
INC (page)
END;
LOOP
Write (ch);
Read (ch);
IF ch = ASCII.EOF THEN EXIT END
END;
CloseOutput;
END emit03.
About the SET constructs.
In this source code I used Modula-2 SET concepts to make the program interact with the user. All options can
be used simultaneously, so I either had to fall back on many discrete BOOLEAN variables or one SET construct.
I chose for the latter.
Remember math in secondary school? With the sets, Venn diagrams and conjunction? Well, that's all implemented
in Modula-2. SET's are an integral part of the language and so there are specific SET operators. Look at the
following snippet:
IF StrEq (option, 'ODD') THEN INCL (PageMode, Odd) ELSIF StrEq (option, 'EVEN') THEN INCL (PageMode, Even)in which the SET variable 'PageMode' is loaded with SET elements. If the command line dictates so, the elements 'Odd', 'Even' or 'Range' are INCLuded in the SET PageMode.
IF Odd IN PageMode THEN WriteString ('Odd'); WriteLn END;
IF Even IN PageMode THEN WriteString ('Even'); WriteLn END;
IF Range IN PageMode THEN WriteString ('Range');
Can one do it more elegant and easier? No, it cannot. If you like mathematics, you *LOVE* Modula-2 (or one of
it's successors). It's all IN the language itself.
Page created March 2005,
Page equipped with GoogleBuster technology