home *** CD-ROM | disk | FTP | other *** search
- MODULE ModPrint;
-
- (*
- * This program is a utility to print Modula-2 programs with
- * pagination, expanded tabs, and emboldened keywords. It should be
- * easy to modify the keyword list to search for other keywords if desired.
- *
- * The keyword emboldening works with Epson compatible printers. It
- * should be fairly simple to change it to work with other types
- * of printers.
- *
- * USAGE :
- * modprint [-noh][-nok][-nop][-p #][-l][-?][-x #][-w #][<filenames>]
- * -noh : disables header printing.
- * -nok : disables keyword emboldening.
- * -nop : disables pagination.
- * -p : Sets pagelength. Default is 66.
- * -l : use Near Letter Quality printing
- * -? : prints usage line
- * -x : Sets tab expansion size. Default is 8.
- * -w : Sets line width. Default is 80 characters.
- *
- * The follwing are the defaults:
- * Use draft print mode.
- * Tab stops are set every 8 spaces.
- * Page length is 66.
- * Line width is 80 chars.
- * Stdin is the input.
- *
- * Copyright 1987, Barry Locklear
- *
- * The author grants the privilege of distributing this
- * software free, or for a nominal charge to cover the media
- * costs, or for connect time.
- *
- * Distribution for commercial gain is prohibited.
- * The only exception is that Jefferson Software may
- * distribute it with their Modula-2 package if they so
- * desire.
- *
- * If improvements are made, please send them to me.
- * Compuserve: 76327,2102
- * Genie: BLOCKLEAR
- * The Jefferson Software BBS (602)276-6102
- *
- * This version of ModPrint is written in Jefferson Software Modula-2
- *)
-
- (*
- * Author: Barry Locklear 12/07/87
- * Version # 1.0
- *)
-
- (* IMPORTED CONSTs *)
- FROM FileSystem IMPORT MAXPATHLEN;
- FROM ASCII IMPORT HT, LF;
-
- (* IMPORTED TYPEs *)
- FROM FileSystem IMPORT File, Response;
- FROM String IMPORT CompareResults;
- FROM DateTime IMPORT DateType, TimeType, DateFormat, TimeFormat;
-
- (* IMPORTED VARs *)
- FROM InOut IMPORT in, out, Done;
-
- (* IMPORTED PROCEDUREs *)
- FROM BasePage IMPORT NumberOfArguments, GetArgument;
- FROM GEMDOSTimeDate IMPORT Tgetdate, Tgettime;
- FROM DateTime IMPORT GetDate, GetTime;
- FROM HashTable IMPORT InsertElem, LookupElem;
- FROM FileSystem IMPORT Lookup, Again;
- FROM InOut IMPORT CloseInput, CloseOutput, Read, Write, WriteString,
- WriteLn, WriteCard;
- FROM SYSTEM IMPORT ADDRESS, TSIZE, SHIFT;
- FROM Heap IMPORT CreateHeap;
- FROM String IMPORT InitStringModule, Assign, Compare, GetTerminator;
- FROM System IMPORT UserDebug;
-
- IMPORT Terminal;
-
- CONST
- HEAPSIZE = 5000; (* Size of heap that program uses *)
-
- VAR
- HeaderFlag, (* TRUE -> Print headers *)
- KeyWordFlag, (* TRUE -> Embolden keywords *)
- PageFlag, (* TRUE -> Paginate the output *)
- DraftFlag, (* TRUE -> Print draft output *)
- FinishedFile, (* TRUE -> Finished printing file *)
- InComment, (* TRUE -> We are inside of a comment *)
- InString : BOOLEAN; (* TRUE -> We are inside of a string constant *)
-
- DateString : DateType;(* Contains date string - updated for each file *)
- TimeString : TimeType;(* Contains time string - updated for each file *)
-
- NumArgs, (* Number of arguments passed in *)
- ArgIndex, (* Current index into argument array *)
- CharCount, (* Number of characters on this line *)
- LineCount, (* Number of lines printed this page *)
- PageCount, (* Number of pages printed *)
- TabSize, (* Tab expansion size *)
- MaxLineSize, (* Maximum characters on a line *)
- PageSize, (* Lines per page *)
- FooterSize : CARDINAL;(* Blank size at bottom of page *)
-
- StringTerminator : CHAR;
-
- ArgString : ARRAY [0..MAXPATHLEN] OF CHAR; (* Current Argument *)
-
- (* --------------------------------------------------------------------*)
-
- (*
- * Initialize the hash table with the lookup values
- *)
- PROCEDURE InitHashTable() : BOOLEAN;
- BEGIN
- (* fill the table up *)
- InsertElem("AND"); InsertElem("ARRAY"); InsertElem("BEGIN");
- InsertElem("BY"); InsertElem("CASE"); InsertElem("CONST");
- InsertElem("DEFINITION"); InsertElem("DIV"); InsertElem("DO");
- InsertElem("ELSE"); InsertElem("ELSIF"); InsertElem("END");
- InsertElem("FROM"); InsertElem("FOR"); InsertElem("IF");
- InsertElem("IMPLEMENTATION"); InsertElem("IMPORT"); InsertElem("IN");
- InsertElem("LOOP"); InsertElem("MOD"); InsertElem("MODULE");
- InsertElem("NOT"); InsertElem("OF"); InsertElem("OR");
- InsertElem("POINTER"); InsertElem("PROCEDURE");InsertElem("QUALIFIED");
- InsertElem("RECORD"); InsertElem("REPEAT"); InsertElem("RETURN");
- InsertElem("SET"); InsertElem("THEN"); InsertElem("TO");
- InsertElem("TYPE"); InsertElem("UNTIL"); InsertElem("VAR");
- InsertElem("WHILE"); InsertElem("WITH"); InsertElem("CARDINAL");
- InsertElem("LONGCARD");InsertElem("INTEGER"); InsertElem("LONGINT");
- InsertElem("BYTE"); InsertElem("WORD"); InsertElem("LONGWORD");
- InsertElem("ADDRESS"); InsertElem("BOOLEAN"); InsertElem("CHAR");
-
- RETURN TRUE;
- END InitHashTable;
-
- (* --------------------------------------------------------------------*)
-
- (*
- * This is some code for a String to Cardinal routine.
- * It takes a string in decimal format and converts it to a Cardinal.
- * It returns FALSE if the routine fails, TRUE if it works.
- *)
- PROCEDURE StrToCard( NumString: ARRAY OF CHAR; VAR Card: CARDINAL ): BOOLEAN;
- VAR
- index,
- limit : CARDINAL;
- BEGIN
- limit := HIGH( NumString );
- Card := 0;
-
- FOR index := 0 TO limit DO
-
- IF NumString[index] = StringTerminator THEN RETURN TRUE; END; (* IF *)
-
- IF (NumString[index] >= '0') AND (NumString[index] <= '9') THEN
- Card := ( Card * 10 ) + VAL( CARDINAL, ORD( NumString[index] ))
- - VAL( CARDINAL, ORD( '0' ));
- ELSE RETURN FALSE;
- END; (* IF *)
- END; (* FOR *)
-
- RETURN TRUE;
-
- END StrToCard;
-
- (* --------------------------------------------------------------------*)
-
- (*
- * Global initializations take place here
- *)
- PROCEDURE GlobalInit() : BOOLEAN;
- BEGIN
- (*
- * Open the printer for use later
- *)
-
- IF out.res = done THEN
- Assign( out.name, "PRN:");
- Lookup( out, out.name, TRUE);
- END; (* IF *)
-
- IF out.res # done THEN
- Done := FALSE;
- Terminal.WriteString("Could not open printer for writing!");
- Terminal.WriteLn;
- RETURN FALSE;
- ELSE
- Done := TRUE;
- END; (* IF *)
-
- (*
- * Make sure we have some space to ALLOCATE from later
- *)
- IF NOT CreateHeap( HEAPSIZE, TRUE ) THEN RETURN FALSE; END; (* IF *)
-
- (*
- * Initialize the string handling module
- *)
- InitStringModule;
-
- (*
- * Initialize the globals.
- *)
- HeaderFlag := TRUE; (* Print Headers *)
- KeyWordFlag := TRUE; (* Print Keywords *)
- PageFlag := TRUE; (* Paginate Output *)
- DraftFlag := TRUE; (* Print draft quality *)
-
- TabSize := 8; (* Set default tabsize *)
- PageSize := 66; (* Set default pagesize *)
- MaxLineSize := 80; (* Default to 80 chars/line *)
- FooterSize := 4; (* blank lines after pagenumber *)
-
- NumArgs := NumberOfArguments();
- ArgIndex := 1;
-
- StringTerminator := GetTerminator();
-
- RETURN InitHashTable();
-
- END GlobalInit;
-
- (* --------------------------------------------------------------------*)
-
- PROCEDURE PrintUsage();
- BEGIN
- CloseOutput(); (* make sure that output goes to terminal *)
- WriteString("USAGE: modprint [options][<filenames>]"); WriteLn;
- WriteString("Options are:"); WriteLn;
- WriteString(" -noh: disables header printing"); WriteLn;
- WriteString(" -nok: disables keyword emboldening"); WriteLn;
- WriteString(" -nop: disables pagination"); WriteLn;
- WriteString(" -p #: set page length to # lines. Default is 66"); WriteLn;
- WriteString(" -l : use Near Letter Quality print"); WriteLn;
- WriteString(" -? : prints usage line and exits"); WriteLn;
- WriteString(" -x #: Sets tab expansion size to #. Default is 8"); WriteLn;
- WriteString(" -w #: Sets line width. Default is 80 characters"); WriteLn;
- WriteString("NOTE: standard input (stdin) is used if no filenames are given");
- WriteLn;
- END PrintUsage;
-
- (* --------------------------------------------------------------------*)
-
- PROCEDURE GetArgs() : BOOLEAN;
- BEGIN
- ArgIndex := 0;
-
- LOOP
- INC( ArgIndex );
- GetArgument( ArgIndex, ArgString );
- IF ArgString[0] # '-' THEN EXIT END;
-
- (* Take action on the argument *)
- CASE ArgString[1] OF
- 'n' : IF Compare( ArgString, "-noh" ) = Equal THEN
- HeaderFlag := FALSE;
- ELSIF Compare( ArgString, "-nok" ) = Equal THEN
- KeyWordFlag := FALSE;
- ELSIF Compare( ArgString, "-nop" ) = Equal THEN
- PageFlag := FALSE;
- ELSE PrintUsage();
- RETURN FALSE;
- END;
-
- | 'l' : DraftFlag := FALSE;
-
- | 'p' : INC( ArgIndex );
- GetArgument( ArgIndex, ArgString );
- IF NOT StrToCard( ArgString, PageSize ) THEN
- PrintUsage();
- RETURN FALSE;
- END; (* IF *)
-
- | 'x' : INC( ArgIndex );
- GetArgument( ArgIndex, ArgString );
- IF NOT StrToCard( ArgString, TabSize ) THEN
- PrintUsage();
- RETURN FALSE;
- END; (* IF *)
-
- | 'w' : INC( ArgIndex );
- GetArgument( ArgIndex, ArgString );
- IF NOT StrToCard( ArgString, MaxLineSize ) THEN
- PrintUsage();
- RETURN FALSE;
- END; (* IF *)
-
- ELSE PrintUsage();
- RETURN FALSE;
- END; (* CASE *)
- END; (* END LOOP *)
-
- IF ArgIndex > NumArgs THEN
- Terminal.WriteString("Error in argument list!"); WriteLn;
- RETURN FALSE;
- ELSE RETURN TRUE;
- END; (* IF *)
-
- END GetArgs;
-
- (* --------------------------------------------------------------------*)
-
- PROCEDURE PerFileInit();
- BEGIN
-
- GetDate( DateString, MoDayYear );
- GetTime( TimeString, Hour24 );
-
- IF DraftFlag THEN
- (* Set printer in draft mode *)
- Write( CHR(27) );
- Write( CHR(120) );
- Write( CHR(0) );
- ELSE (* Set printer to Near Letter Quality Mode *)
- Write( CHR(27) );
- Write( CHR(120) );
- Write( CHR(1) );
- END; (* IF *)
-
- InString := FALSE; (* We don't start out in a string *)
- InComment := FALSE; (* We don't start out in a comment *)
-
- CharCount := 0; (* No chars printed yet *)
- LineCount := 1; (* Start on line 1 *)
- PageCount := 0; (* No pages printed yet *)
- FinishedFile := FALSE; (* We're just starting! *)
- END PerFileInit;
-
- (* --------------------------------------------------------------------*)
-
- PROCEDURE PrintHeader( PageNo: CARDINAL ): CARDINAL;
-
- BEGIN
- WriteLn;
- WriteLn;
-
- IF NOT HeaderFlag THEN
- RETURN 2;
- ELSE
- (*
- * Print Date and Time
- *)
- WriteString( " " );
- WriteString( DateString );
- WriteString(" ");
- WriteString( TimeString );
-
- (*
- * Print file name if there is one
- *)
- IF in.handle # 0 THEN
- (* We have a file *)
- WriteString(" ");
- WriteString(ArgString);
- ELSE
- (* We have stdin *)
- WriteString(" ");
- END; (* IF *)
-
- (*
- * Print Page Number
- *)
- WriteString(" Page:");
- WriteCard( PageNo, 2 );
- WriteLn;
- WriteLn;
- WriteLn;
- RETURN 5;
- END; (* IF *)
- END PrintHeader;
-
- (* --------------------------------------------------------------------*)
-
- PROCEDURE NewPage();
- BEGIN
- INC( PageCount );
- LineCount := PrintHeader( PageCount ) + 1;
- END NewPage;
-
- (* --------------------------------------------------------------------*)
-
- PROCEDURE NewLine();
- VAR
- i : CARDINAL;
-
- BEGIN
- Write( LF );
- CharCount := 0;
- INC( LineCount );
-
- IF PageFlag THEN
- IF LineCount >= (PageSize - FooterSize) THEN
-
- FOR i := LineCount TO PageSize DO
- Write( LF );
- END; (* FOR *)
-
- IF ~FinishedFile THEN
- NewPage();
- END; (* IF *)
- END; (* IF *)
- END; (* IF *)
- END NewLine;
-
- (* --------------------------------------------------------------------*)
-
- PROCEDURE PrintChar( InChar: CHAR );
- BEGIN
- IF( InChar = LF ) THEN
- NewLine();
- ELSE
- IF CharCount >= MaxLineSize THEN NewLine(); END; (* IF *)
-
- Write( InChar );
- INC( CharCount );
- END; (* IF *)
- END PrintChar;
-
- (* --------------------------------------------------------------------*)
-
- (*
- * PrintToken
- * Prints tokens, emboldening if necessary. This works for EPSON
- * compatible printers. Should be easy to change for others.
- *)
- PROCEDURE PrintToken( Token: ARRAY OF CHAR; TokenLen: CARDINAL );
- VAR
- i : CARDINAL;
- emBolden : BOOLEAN;
-
- BEGIN
- emBolden := FALSE;
- (*
- * See if the token would be split up at the end of a line.
- * If so, then start a new line.
- *)
- IF ( CharCount + TokenLen ) > MaxLineSize THEN NewLine(); END; (* IF *)
-
- (*
- * If not in a comment or a string and we are to embolden keywords,
- * check to see if we should embolden the token.
- *)
- IF NOT( InComment OR InString ) AND KeyWordFlag THEN
- emBolden := LookupElem( Token );
- IF emBolden THEN
- (* Put printer in BOLD font *)
- Write( CHR(27) ); (* ESC *)
- Write( 'E' ); (* BOLD *)
- END; (* IF *)
- END; (* IF *)
-
- FOR i := 0 TO TokenLen-1 DO PrintChar( Token[i] ); END; (* FOR *)
-
- IF emBolden THEN
- (* Take printer out of bold mode *)
- Write( CHR(27) ); (* ESC *)
- Write( 'F' ); (* NO BOLD *)
- END; (* IF *)
-
- END PrintToken;
-
- (* --------------------------------------------------------------------*)
-
- PROCEDURE PrintAFile();
- VAR
- tokenIndex,
- i : CARDINAL;
-
- commentLevel : CARDINAL; (* Level of nesting in comments *)
-
- inChar,
- stringChar: CHAR;
-
- token : ARRAY [0..127] OF CHAR;
-
- BEGIN
- tokenIndex := 0;
- commentLevel := 0; (* We don't start out in a comment *)
-
- PerFileInit();
-
- NewPage();
-
- WHILE NOT in.eof DO
- Read( inChar );
-
- (*
- * take action based on value of inChar
- *)
- IF inChar = HT THEN
- (* Got a TAB character *)
- PrintChar(' ');
- WHILE (CharCount MOD TabSize) # 0 DO
- (*
- * The correct working of this loop depends on
- * CharCount being modified by PrintChar.
- *)
- PrintChar(' ');
- END; (* WHILE *)
- ELSIF (inChar = '"') OR (inChar = "'") THEN
- IF InString THEN
- IF stringChar = inChar THEN
- InString := FALSE;
- END; (* IF *)
- ELSIF NOT InComment THEN
- stringChar := inChar;
- InString := TRUE;
- END; (* IF *)
- PrintChar( inChar );
-
- ELSIF inChar = '(' THEN
- PrintChar( inChar );
- Read( inChar );
- IF inChar = '*' THEN
- INC( commentLevel );
- InComment := TRUE;
- PrintChar( inChar );
- ELSE Again( in );
- END; (* IF *)
-
- ELSIF inChar = '*' THEN
- PrintChar( inChar );
- IF InComment THEN
- Read( inChar );
- IF inChar = ')' THEN
- IF commentLevel > 0 THEN
- DEC( commentLevel );
- END;
-
- IF commentLevel = 0 THEN
- InComment := FALSE;
- END; (* IF *)
- PrintChar( inChar );
- ELSE Again( in );
- END; (* IF *)
- END; (* IF *)
-
- ELSE
- (*
- * Might be a token, check it and print it.
- *)
-
- IF (inChar >= 'A') AND (inChar <= 'Z') THEN
- (* check for reserved words *)
- tokenIndex := 0;
- token[ tokenIndex ] := inChar;
- INC( tokenIndex );
-
- IF NOT in.eof THEN
- LOOP
- Read( inChar );
- IF in.eof THEN EXIT; END; (* IF *)
- IF ((inChar < 'A') OR (inChar > 'Z' )) AND
- ((inChar < 'a') OR (inChar > 'z' )) AND
- ((inChar < '0') OR (inChar > '9' ))
- THEN
- Again( in );
- token[ tokenIndex ] := StringTerminator;
- PrintToken( token, tokenIndex );
- tokenIndex := 0;
- EXIT;
- ELSE
- token[ tokenIndex ] := inChar;
- INC( tokenIndex );
- END; (* IF *)
- END; (* LOOP *)
- END; (* IF *)
- ELSE
- PrintChar( inChar );
- END; (* IF *)
-
- END; (* IF *)
-
- END; (* WHILE *)
-
- (* Form Feed *)
- FinishedFile := TRUE;
-
- FOR i := LineCount TO PageSize DO Write( LF ); END; (* FOR *)
-
- END PrintAFile;
-
- (* --------------------------------------------------------------------*)
-
- PROCEDURE PrintFiles();
- BEGIN
- IF ArgIndex <= NumArgs THEN
- WHILE ArgIndex <= NumArgs DO
- GetArgument( ArgIndex, ArgString );
- Lookup( in, ArgString, FALSE );
- in.eof := FALSE; (* this is to get around a 'bug' in lookup -
- * if you use the same handle when opening
- * and closing several files, eof does not get
- * reset by lookup. If this bug is fixed in your
- * library, you can remove this line.
- *)
- IF in.res # done THEN
- Terminal.WriteString("Cannot open file ");
- Terminal.WriteString( ArgString );
- Terminal.WriteLn;
- ELSE
- Terminal.WriteString("Printing ");
- Terminal.WriteString( ArgString );
- Terminal.WriteLn;
- PrintAFile();
- END; (* IF *)
-
- CloseInput();
-
- INC( ArgIndex );
- END; (* WHILE *)
- ELSE (* Use standard input *)
- PrintAFile();
- END; (* IF *)
- END PrintFiles;
-
- (* --------------------------------------------------------------------*)
-
- PROCEDURE CloseUp();
- BEGIN
-
- IF NOT DraftFlag THEN
- (* Set printer in draft mode *)
- Write( CHR(27) );
- Write( CHR(120) );
- Write( CHR(0) );
- END; (* IF *)
-
- CloseOutput(); (* close printer file *)
- END CloseUp;
-
- (* --------------------------------------------------------------------*)
-
- BEGIN (* ModPrint *)
-
- IF GlobalInit() THEN
- IF GetArgs() THEN
- PrintFiles();
- END; (* IF *)
- END; (* IF *)
-
- CloseUp();
- END ModPrint.
-