home *** CD-ROM | disk | FTP | other *** search
- MODULE column_set;
-
- (* Copyright 1989 by Kent Paul Dolan, USENet: xanthian@well.sf.ca.us *
-
- (* Use it as you wish, but leave me a little credit somewhere in the result! *
-
-
- (* Developed with BENCHMARK Modula-2 from Avante-Garde Software *
-
-
- (* Purpose: to lay out "words" from a file of one word per line in as many *
-
- (* columns as will fit across the page with at least one space between *
-
- (* columns. Command usage is described further down in the code. This code *
-
- (* was written to provide a filter in a script for making the output of the *
-
- (* AmigaDOS "list lformat="%S" command look like the Unix "ls" output, but *
-
- (* looks useful as an independent command, as well. *
-
-
- (* It is a modest attempt at mixing a Unix and an AmigaDOS command format in *
-
- (* a small utility, while reasonably bullet-proofing the routine from command *
-
- (* line errors or i/o problems. The working guts of the program, without *
-
- (* the frills, takes up 1/3 the source and 1/2 the runtime space; this is an *
-
- (* exercise in doing the job "right", for the fun of it. Kent. *
-
-
- FROM System IMPORT argc, argv, StdInput, StdOutput;
-
- FROM InOut IMPORT WriteString, WriteInt, WriteLn, Write, Read, OpenInputFile,
- OpenOutputFile, Done, CloseInput, CloseOutput, EOL;
-
- IMPORT Terminal;
-
- FROM Terminal IMPORT eof;
-
- FROM FileSystem IMPORT Response, File, Lookup, Close, Delete, ReadChar,
- WriteChar;
-
- FROM Strings IMPORT CompareStringCAP, LocateChar, CopyString, Relation;
-
- CONST
- DefaultWindowWidth = 77;
- TempFileName = "T:column_set.temp";
-
- TYPE
- CommandLineParam = ARRAY [0..255] OF CHAR;
-
- VAR
- Ch: CHAR;
-
- InFile,
- OutFile: CommandLineParam;
-
- MaxLength,
- WindowWidth,
- ThisLength,
- MaxColumns,
- NumColumns,
- ThisColumn,
- NumSpaces,
- I: INTEGER;
-
- TempFile: File;
-
- UsingStdInput,
- UsingStdOutput,
- WentOK: BOOLEAN;
-
- (*
- ** Usage: column_set [[FROM | -i] infile] [[TO | -o] outfile] [[WIDTH | -w] nn]
- ** [[MAXCOL | -m] mm]
- **
- ** infile is the input file, one "word" per line;
- ** outfile is the output file, with the same words in the same order laid out
- ** in columns evenly across the page or screen;
- ** width is the number of character positions across the screen or page;
- ** default is 77 to fit a standard AmigaDOS window;
- ** maxcol limits the number of columns of words which will be set across the
- ** page to less than the maximum possible; default is (width+1)/2;
- **
- ** where infile, outfile, width and maxcol are positional parameters unless the
- ** keywords are present. If no infile is given, standard input is used, and
- ** a temporary file "column_set.temp" is created and deleted to allow a second
- ** pass over the input data. If an infile is given, it is closed and reopened
- ** for the second pass over the data. If no outfile is given, standard output
- ** is used.
- *)
-
- PROCEDURE usage;
- BEGIN
- WriteLn;
- WriteString
- ("Usage: column_set [FROM | -i] infile [TO | -o] outfile [WIDTH | -w] ww");
- WriteLn;
- WriteString
- (" [MAXCOL | -m] mm]");
- WriteLn;
- WriteString
- (" or: column_set < infile > outfile [{WIDTH | -w} ww] [{MAXCOL | -m} mm]")
-
- WriteLn;
- WriteString
- (" or: column_set [(WIDTH | -w} ww] [{MAXCOL | -m} mm] infile outfile");
- WriteLn;
- WriteString
- ("or other likely combinations; infile, outfile, ww, and mm are positional");
- WriteLn;
- WriteString
- ("without keywords, position independent with keywords, and mixes are read");
- WriteLn;
- WriteString
- ("by trying to pick off first the keyword parmameters, then the missing");
- WriteLn;
- WriteString
- ("positional parameters in order from what is left over.");
- WriteLn;
- WriteString
- ("'Infile' is the input file, expected to contain one 'word' per line;");
- WriteLn;
- WriteString
- ("'outfile' is the output file, which will contain the same 'words' in the");
- WriteLn;
- WriteString
- ("same order laid out in as many even columns as will fit across the");
- WriteLn;
- WriteString
- ("page or screen; 'ww' is the width of the screen or page in character");
- WriteLn;
- WriteString
- ("positions; 'mm' is the most 'words' the user wants per line, to limit");
- WriteLn;
- WriteString
- ("them below the most possible in case a sparser layout is desired.");
- WriteLn;
- WriteString
- ("If infile and/or outfile are not specified, they default to standard");
- WriteLn;
- WriteString
- ("input and output; width (ww) defaults to 77 columns to match the");
- WriteLn;
- WriteString
- ("AmigaShell window, and maxcol (mm) defaults to (width+1)/2.");
- WriteLn;
- WriteString
- (" /s/ Kent Paul Dolan, USENet: xanthian@well.sf.ca.us")
-
- WriteLn;
- WriteLn;
- RETURN;
- END usage;
-
- PROCEDURE getcmdline
- (VAR infile, outfile: ARRAY OF CHAR;
- VAR width: INTEGER; VAR maxcol: INTEGER): BOOLEAN;
- VAR
- J, MyArgc, UnusedArgs: INTEGER;
- Unused: ARRAY [0..15] OF INTEGER;
-
- PROCEDURE getwidth(VAR width: INTEGER; token: ARRAY OF CHAR): BOOLEAN;
- VAR
- CharIndex, DigitValue: INTEGER;
-
- BEGIN
- CharIndex := 0;
- (*
- WriteString(argv^[J+1]^); WriteLn;
- *)
- WHILE (ORD(token[CharIndex]) <> 0) DO
- DigitValue := LocateChar("0123456789",token[CharIndex],0,9);
- IF ( DigitValue = -1 ) THEN
- WriteString("column_set: Error -- non-digit in width parameter");
- WriteLn;
- RETURN FALSE;
- ELSE
- width := 10 * width + DigitValue;
- END;
- CharIndex := CharIndex + 1;
- END;
- RETURN TRUE;
- END getwidth;
-
- PROCEDURE getmaxcol(VAR maxcol: INTEGER; token: ARRAY OF CHAR): BOOLEAN;
- VAR
- CharIndex, DigitValue: INTEGER;
-
- BEGIN
- CharIndex := 0;
- (*
- WriteString(argv^[J+1]^); WriteLn;
- *)
- WHILE (ORD(token[CharIndex]) <> 0) DO
- DigitValue := LocateChar("0123456789",token[CharIndex],0,9);
- IF ( DigitValue = -1 ) THEN
- WriteString("column_set: Error -- non-digit in maxcol parameter");
- WriteLn;
- RETURN FALSE;
- ELSE
- maxcol := 10 * maxcol + DigitValue;
- END;
- CharIndex := CharIndex + 1;
- END;
- RETURN TRUE;
- END getmaxcol;
-
- BEGIN (* getcmdline *)
-
- CopyString(infile,"");
- CopyString(outfile,"");
- width := 0;
- UnusedArgs := 0;
-
- FOR J := 0 TO 15 BY 1 DO
- Unused[J] := 0;
- END;
-
- MyArgc := argc;
- (*
- WriteString("MyArgc"); WriteInt(MyArgc,4); WriteLn;
- *)
- (* Pull out any keyword arguments from the command line: *)
- J := 1;
- WHILE (J < MyArgc) DO
- (*
- WriteString(argv^[J]^);
- *)
- IF
- (
- ( CompareStringCAP( argv^[J]^ , "-i" ) = equal )
- OR
- ( CompareStringCAP( argv^[J]^ , "FROM" ) = equal )
- ) THEN
- IF ( J + 1 >= MyArgc ) THEN
- WriteString
- ("column_set: Error -- '-i' or 'FROM' was last argument on command line");
- WriteLn;
- RETURN FALSE;
- ELSE
- CopyString(infile,argv^[J+1]^);
- (*
- WriteString(argv^[J+1]^); WriteLn;
- *)
- J := J + 2;
- END;
- ELSIF
- (
- ( CompareStringCAP( argv^[J]^ , "-o" ) = equal )
- OR
- ( CompareStringCAP( argv^[J]^ , "TO" ) = equal )
- ) THEN
- IF ( J + 1 >= MyArgc ) THEN
- WriteString
- ("column_set: Error -- '-o' or 'TO' was last argument on command line");
- WriteLn;
- RETURN FALSE;
- ELSE
- CopyString(outfile,argv^[J+1]^);
- (*
- WriteString(argv^[J+1]^); WriteLn;
- *)
- J := J + 2;
- END;
- ELSIF
- (
- ( CompareStringCAP( argv^[J]^ , "-w" ) = equal )
- OR
- ( CompareStringCAP( argv^[J]^ , "WIDTH" ) = equal )
- ) THEN
- IF ( J + 1 >= MyArgc ) THEN
- WriteString
- ("column_set: Error -- '-w' or 'WIDTH' was last argument on command line");
- WriteLn;
- RETURN FALSE;
- ELSE
- width := 0;
- IF ( NOT getwidth(width,argv^[J + 1]^) ) THEN
- RETURN FALSE;
- END;
- J := J + 2;
- END;
- ELSIF
- (
- ( CompareStringCAP( argv^[J]^ , "-m" ) = equal )
- OR
- ( CompareStringCAP( argv^[J]^ , "MAXCOL" ) = equal )
- ) THEN
- IF ( J + 1 >= MyArgc ) THEN
- WriteString
- ("column_set: Error -- '-m' or 'MAXCOL' was last argument on command line");
- WriteLn;
- RETURN FALSE;
- ELSE
- maxcol := 0;
- IF ( NOT getmaxcol(maxcol,argv^[J + 1]^) ) THEN
- RETURN FALSE;
- END;
- J := J + 2;
- END;
- ELSE
- Unused[UnusedArgs] := J;
- UnusedArgs := UnusedArgs + 1;
- J := J + 1;
- END;
- END;
-
- (* Pull out any remaining positional arguments from the command line: *)
- J := 0;
- IF ( ( CompareStringCAP(infile,"") = equal ) AND (J < UnusedArgs) ) THEN
- CopyString(infile,argv^[Unused[J]]^);
- J := J + 1;
- END;
- IF ( ( CompareStringCAP(outfile,"") = equal ) AND (J < UnusedArgs) ) THEN
- CopyString(outfile,argv^[Unused[J]]^);
- J := J + 1;
- END;
- IF ( width = 0 ) AND (J < UnusedArgs) THEN
- IF ( NOT getwidth(width,argv^[Unused[J]]^) ) THEN
- RETURN FALSE;
- END;
- J := J + 1;
- END;
- IF ( width = 0) THEN
- width := DefaultWindowWidth;
- END;
- IF ( maxcol = 0 ) AND (J < UnusedArgs) THEN
- IF ( NOT getmaxcol(maxcol,argv^[Unused[J]]^) ) THEN
- RETURN FALSE;
- END;
- J := J + 1;
- END;
- IF ( maxcol = 0 ) THEN
- maxcol := (width + 1) DIV 2;
- END;
- (*
- WriteLn;
- *)
- RETURN TRUE;
- END getcmdline;
-
- PROCEDURE writebitch;
- BEGIN
- WriteString("column_set: Error -- problem writing OutFile = ");
- WriteString(OutFile);
- WriteLn;
- IF (UsingStdInput) THEN
- Close(TempFile);
- Delete(TempFileName);
- END;
- IF (NOT UsingStdOutput) THEN
- CloseOutput;
- END;
- RETURN;
- END writebitch;
-
- BEGIN (* column_set *)
-
- IF ( argc > 1 ) THEN
- IF ( CompareStringCAP(argv^[1]^,"?") = equal ) THEN
- usage;
- RETURN;
- END;
- END;
-
- IF ( NOT getcmdline(InFile,OutFile,WindowWidth,MaxColumns) ) THEN
- WriteString("column_set: Error -- unable to correctly parse command line!");
- WriteLn;
- usage;
- RETURN;
- (*
- ELSE
- WriteString("InFile = "); WriteString(InFile); WriteLn;
- WriteString("OutFile = "); WriteString(OutFile); WriteLn;
- WriteString("WindowWidth = "); WriteInt(WindowWidth,1); WriteLn;
- WriteString("MaxColumns = "); WriteInt(MaxColumns,1); WriteLn;
- *)
- END;
-
- IF (CompareStringCAP(InFile,"") = equal) THEN
- UsingStdInput := TRUE;
- ELSE
- UsingStdInput := FALSE;
- END;
-
- IF (CompareStringCAP(OutFile,"") = equal) THEN
- UsingStdOutput := TRUE;
- ELSE
- UsingStdOutput := FALSE;
- END;
-
- IF ( UsingStdInput) THEN
- Lookup(TempFile,TempFileName,TRUE);
- IF (TempFile.res <> done) THEN
- WriteString
- ("column_set: Error -- unable to open new work file T:column_set.temp");
- WriteLn;
- RETURN;
- END;
- (*
- WriteString("column_set: taking data from standard input"); WriteLn;
- *)
- ELSE
- OpenInputFile(InFile);
- IF (NOT Done) THEN
- WriteString("column_set: Error -- file open failed for InFile = ");
- WriteString(InFile); WriteLn;
- RETURN;
- END;
- (*
- WriteString("column_set: taking data from a named file"); WriteLn;
- *)
- END;
-
- MaxLength := 0;
- ThisLength := 0;
- WentOK := TRUE;
-
- IF ( UsingStdInput ) THEN
- Terminal.Read(Ch);
- IF (eof) THEN
- WriteString
- ("column_set: Error -- standard input looks empty in counting pass");
- WentOK := FALSE;
- END;
- ELSE
- Read(Ch);
- IF (NOT Done) THEN
- WriteString("column_set: Error -- input file looks empty in counting pass")
-
- WentOK := FALSE;
- END;
- END;
-
- IF (NOT WentOK) THEN
- WriteLn;
- Close(TempFile);
- Delete(TempFileName);
- IF (NOT UsingStdInput) THEN
- CloseInput;
- END;
- RETURN;
- END;
-
- LOOP
- IF ( UsingStdInput ) THEN
- WriteChar(TempFile,Ch);
- IF (TempFile.res = notdone) THEN
- WriteString
- ("column_set: Error -- problem writing to file T:column_set.temp");
- WriteLn;
- Close(TempFile);
- Delete(TempFileName);
- RETURN;
- END;
- END;
- IF (Ch <> EOL) THEN
- ThisLength := ThisLength + 1;
- ELSE
- IF (ThisLength > MaxLength) THEN
- MaxLength := ThisLength;
- END;
- ThisLength := 0;
- END;
- IF (UsingStdInput) THEN
- Terminal.Read(Ch);
- IF (eof) THEN
- EXIT;
- END;
- ELSE
- Read(Ch);
- IF (NOT Done) THEN
- EXIT;
- END;
- END;
- END;
-
- IF ( UsingStdInput ) THEN
- Close(TempFile);
- IF (TempFile.res = notdone) THEN
- WriteString
- ("column_set: Error -- unable to close file T:column_set.temp after");
- WriteString(" counting pass"); WriteLn;
- RETURN;
- END;
- Lookup(TempFile,TempFileName,FALSE);
- IF (TempFile.res <> done) THEN
- WriteString
- ("column_set: Error -- unable to open file T:column_set.temp before");
- WriteString(" writing pass"); WriteLn;
- Delete(TempFileName);
- RETURN;
- END;
- ELSE
- CloseInput;
- OpenInputFile(InFile);
- IF (NOT Done) THEN
- WriteString("column_set: Error -- File reopen failed for InFile = ");
- WriteString(InFile); WriteLn;
- RETURN;
- END;
- END;
-
- IF (NOT UsingStdOutput) THEN
- OpenOutputFile(OutFile);
- IF (NOT Done) THEN
- WriteString("column_set: Error -- file open failed for OutFile = ");
- WriteString(OutFile); WriteLn;
- Close(TempFile);
- Delete(TempFileName);
- RETURN;
- END;
- END;
-
- NumColumns := (WindowWidth + 1) DIV (MaxLength + 1);
- IF (NumColumns > MaxColumns) THEN
- NumColumns := MaxColumns;
- END;
- IF (NumColumns > 1) THEN
- NumSpaces := (WindowWidth - (NumColumns * MaxLength)) DIV (NumColumns - 1);
- ELSE
- NumSpaces := 0;
- END;
-
- ThisLength := 0;
- ThisColumn := 0;
- IF ( UsingStdInput ) THEN
- ReadChar(TempFile,Ch);
- IF (TempFile.res <> done) THEN
- IF (TempFile.eof) THEN
- WriteString
- ("column_set: Error -- Temporary Input File Looks Empty In Writing Pass");
- WriteLn;
- ELSE
- WriteString
- ("column_set: Error -- problem reading from T:column_set.temp");
- END;
- Close(TempFile);
- Delete(TempFileName);
- IF (NOT UsingStdOutput) THEN
- CloseOutput;
- END;
- RETURN;
- END;
- ELSE
- Read(Ch);
- IF (NOT Done) THEN
- WriteString("column_set: Error -- Input File Looks Empty In Writing Pass");
- WriteLn;
- IF (NOT UsingStdOutput) THEN
- CloseOutput;
- END;
- CloseInput;
- RETURN;
- END;
- END;
-
- LOOP
- IF (Ch <> EOL) THEN
- ThisLength := ThisLength + 1;
- IF ( UsingStdOutput ) THEN
- Terminal.Write(Ch);
- (*
- Module InOut "Done" documentation is buggy; omit checks after write;
- Wirth didn't specify them, and BENCHMARK doesn't support them.
- No way to check "Terminal" output result - not good when redirected
- to a disk file that might overflow!
-
- WriteString("column_set: Error -- problem writing standard output");
- *)
- ELSE
- Write(Ch);
- (*
- Module InOut "Done" documentation is buggy; omit checks after write;
- Wirth didn't specify them, and BENCHMARK doesn't support them.
- IF (NOT Done) THEN
- writebitch;
- RETURN;
- END;
- *)
- END;
- ELSE
- ThisColumn := ThisColumn + 1;
- IF (ThisColumn < NumColumns) THEN
- FOR I := ThisLength + 1 TO MaxLength + NumSpaces BY 1 DO
- IF (UsingStdOutput) THEN
- Terminal.Write(" ");
- ELSE
- Write(" ");
- IF (NOT Done) THEN
- writebitch;
- RETURN;
- END;
- END;
- END;
- ELSE
- IF (UsingStdOutput) THEN
- Terminal.WriteLn;
- ELSE
- Write(EOL);
- (*
- Module InOut "Done" documentation is buggy; omit checks after write;
- Wirth didn't specify them, and BENCHMARK doesn't support them.
-
- IF (NOT Done) THEN
- writebitch;
- RETURN;
- END;
- *)
- END;
- ThisColumn := 0;
- END;
- ThisLength := 0;
- END;
- IF ( UsingStdInput ) THEN
- ReadChar(TempFile,Ch);
- IF (TempFile.res <> done) THEN
- IF (TempFile.eof) THEN
- EXIT;
- ELSE
- WriteString
- ("column_set: Error -- problem reading from T:column_set.temp");
- Close(TempFile);
- Delete(TempFileName);
- IF (NOT UsingStdOutput) THEN
- CloseOutput;
- END;
- RETURN;
- END;
- END;
- ELSE
- Read(Ch);
- IF (NOT Done) THEN (* Unable to differentiate read error from eof *)
- EXIT;
- END;
- END;
- END;
-
- IF (ThisColumn <> 0) THEN
- IF (UsingStdOutput) THEN
- Terminal.WriteLn;
- ELSE
- Write(EOL);
- (*
- Module InOut "Done" documentation is buggy; omit checks after write;
- Wirth didn't specify them, and BENCHMARK doesn't support them.
- IF (NOT Done) THEN
- writebitch;
- RETURN;
- END;
- *)
- END;
- END;
-
- IF ( UsingStdInput ) THEN
- Close(TempFile);
- Delete(TempFileName);
- ELSE
- CloseInput;
- END;
-
- IF (NOT UsingStdOutput) THEN
- CloseOutput;
- END;
-
- END column_set.
-