home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 200-299 / ff270.lzh / ColumnSet / column_set.MOD < prev    next >
Text File  |  1989-11-06  |  16KB  |  655 lines

  1. MODULE column_set;
  2.  
  3. (* Copyright 1989 by Kent Paul Dolan, USENet: xanthian@well.sf.ca.us          *)
  4. (* Use it as you wish, but leave me a little credit somewhere in the result!  *)
  5.  
  6. (* Developed with BENCHMARK Modula-2 from Avante-Garde Software               *)
  7.  
  8. (* Purpose: to lay out "words" from a file of one word per line in as many    *)
  9. (* columns as will fit across the page with at least one space between        *)
  10. (* columns.  Command usage is described further down in the code.  This code  *)
  11. (* was written to provide a filter in a script for making the output of the   *)
  12. (* AmigaDOS "list lformat="%S" command look like the Unix "ls" output, but    *)
  13. (* looks useful as an independent command, as well.                           *)
  14.  
  15. (* It is a modest attempt at mixing a Unix and an AmigaDOS command format in  *)
  16. (* a small utility, while reasonably bullet-proofing the routine from command *)
  17. (* line errors or i/o problems.  The working guts of the program, without     *)
  18. (* the frills, takes up 1/3 the source and 1/2 the runtime space; this is an  *)
  19. (* exercise in doing the job "right", for the fun of it.   Kent.              *)
  20.  
  21. FROM System IMPORT argc, argv, StdInput, StdOutput;
  22.  
  23. FROM InOut IMPORT WriteString, WriteInt, WriteLn, Write, Read, OpenInputFile,
  24.                   OpenOutputFile, Done, CloseInput, CloseOutput, EOL;
  25.  
  26. IMPORT Terminal;
  27.  
  28. FROM Terminal IMPORT eof;
  29.  
  30. FROM FileSystem IMPORT Response, File, Lookup, Close, Delete, ReadChar,
  31.                        WriteChar;
  32.  
  33. FROM Strings IMPORT CompareStringCAP, LocateChar, CopyString, Relation;
  34.  
  35. CONST
  36.   DefaultWindowWidth = 77;
  37.   TempFileName = "T:column_set.temp";
  38.  
  39. TYPE
  40.   CommandLineParam = ARRAY [0..255] OF CHAR;
  41.   
  42. VAR
  43.   Ch:             CHAR;
  44.  
  45.   InFile,
  46.   OutFile:        CommandLineParam;
  47.  
  48.   MaxLength, 
  49.   WindowWidth,
  50.   ThisLength,
  51.   MaxColumns,
  52.   NumColumns,
  53.   ThisColumn,
  54.   NumSpaces,
  55.   I:              INTEGER;
  56.  
  57.   TempFile:       File;
  58.  
  59.   UsingStdInput,
  60.   UsingStdOutput,
  61.   WentOK:         BOOLEAN;
  62.  
  63. (*
  64. ** Usage: column_set [[FROM | -i] infile] [[TO | -o] outfile] [[WIDTH | -w] nn]
  65. **        [[MAXCOL | -m] mm]
  66. **
  67. ** infile is the input file, one "word" per line;
  68. ** outfile is the output file, with the same words in the same order laid out
  69. ** in columns evenly across the page or screen;
  70. ** width is the number of character positions across the screen or page;
  71. ** default is 77 to fit a standard AmigaDOS window;
  72. ** maxcol limits the number of columns of words which will be set across the
  73. ** page to less than the maximum possible; default is (width+1)/2;
  74. **
  75. ** where infile, outfile, width and maxcol are positional parameters unless the
  76. ** keywords are present.  If no infile is given, standard input is used, and
  77. ** a temporary file "column_set.temp" is created and deleted to allow a second
  78. ** pass over the input data.  If an infile is given, it is closed and reopened
  79. ** for the second pass over the data.  If no outfile is given, standard output
  80. ** is used.
  81. *)
  82.  
  83. PROCEDURE usage;
  84. BEGIN
  85.   WriteLn;
  86.   WriteString
  87.   ("Usage: column_set [FROM | -i] infile [TO | -o] outfile [WIDTH | -w] ww");
  88.   WriteLn;
  89.   WriteString
  90.   ("       [MAXCOL | -m] mm]");
  91.   WriteLn;
  92.   WriteString
  93.   ("   or: column_set < infile > outfile [{WIDTH | -w} ww] [{MAXCOL | -m} mm]");
  94.   WriteLn;
  95.   WriteString
  96.   ("   or: column_set [(WIDTH | -w} ww] [{MAXCOL | -m} mm] infile outfile");
  97.   WriteLn;
  98.   WriteString
  99.   ("or other likely combinations; infile, outfile, ww, and mm are positional");
  100.   WriteLn;
  101.   WriteString
  102.   ("without keywords, position independent with keywords, and mixes are read");
  103.   WriteLn;
  104.   WriteString
  105.   ("by trying to pick off first the keyword parmameters, then the missing");
  106.   WriteLn;
  107.   WriteString
  108.   ("positional parameters in order from what is left over.");
  109.   WriteLn;
  110.   WriteString
  111.   ("'Infile' is the input file, expected to contain one 'word' per line;");
  112.   WriteLn;
  113.   WriteString
  114.   ("'outfile' is the output file, which will contain the same 'words' in the");
  115.   WriteLn;
  116.   WriteString
  117.   ("same order laid out in as many even columns as will fit across the");
  118.   WriteLn;
  119.   WriteString
  120.   ("page or screen; 'ww' is the width of the screen or page in character");
  121.   WriteLn;
  122.   WriteString
  123.   ("positions; 'mm' is the most 'words' the user wants per line, to limit");
  124.   WriteLn;
  125.   WriteString
  126.   ("them below the most possible in case a sparser layout is desired.");
  127.   WriteLn;
  128.   WriteString
  129.   ("If infile and/or outfile are not specified, they default to standard");
  130.   WriteLn;
  131.   WriteString
  132.   ("input and output; width (ww) defaults to 77 columns to match the");
  133.   WriteLn;
  134.   WriteString
  135.   ("AmigaShell window, and maxcol (mm) defaults to (width+1)/2.");
  136.   WriteLn;
  137.   WriteString
  138.   ("                     /s/  Kent Paul Dolan, USENet: xanthian@well.sf.ca.us");
  139.   WriteLn;
  140.   WriteLn;
  141.   RETURN;
  142. END usage;
  143.  
  144. PROCEDURE getcmdline
  145.           (VAR infile, outfile: ARRAY OF CHAR;
  146.            VAR width: INTEGER; VAR maxcol: INTEGER): BOOLEAN;
  147. VAR
  148.   J, MyArgc, UnusedArgs: INTEGER;
  149.   Unused: ARRAY [0..15] OF INTEGER;
  150.  
  151. PROCEDURE getwidth(VAR width: INTEGER; token: ARRAY OF CHAR): BOOLEAN; 
  152. VAR
  153.   CharIndex, DigitValue: INTEGER;
  154.  
  155. BEGIN
  156.   CharIndex := 0;
  157. (*
  158.   WriteString(argv^[J+1]^); WriteLn;
  159. *)
  160.   WHILE (ORD(token[CharIndex]) <> 0) DO
  161.     DigitValue := LocateChar("0123456789",token[CharIndex],0,9);
  162.     IF ( DigitValue = -1 ) THEN
  163.       WriteString("column_set: Error -- non-digit in width parameter");
  164.       WriteLn;
  165.       RETURN FALSE;
  166.     ELSE
  167.       width := 10 * width + DigitValue;
  168.     END;
  169.     CharIndex := CharIndex + 1;
  170.   END;
  171.   RETURN TRUE;
  172. END getwidth;
  173.  
  174. PROCEDURE getmaxcol(VAR maxcol: INTEGER; token: ARRAY OF CHAR): BOOLEAN; 
  175. VAR
  176.   CharIndex, DigitValue: INTEGER;
  177.  
  178. BEGIN
  179.   CharIndex := 0;
  180. (*
  181.   WriteString(argv^[J+1]^); WriteLn;
  182. *)
  183.   WHILE (ORD(token[CharIndex]) <> 0) DO
  184.     DigitValue := LocateChar("0123456789",token[CharIndex],0,9);
  185.     IF ( DigitValue = -1 ) THEN
  186.       WriteString("column_set: Error -- non-digit in maxcol parameter");
  187.       WriteLn;
  188.       RETURN FALSE;
  189.     ELSE
  190.       maxcol := 10 * maxcol + DigitValue;
  191.     END;
  192.     CharIndex := CharIndex + 1;
  193.   END;
  194.   RETURN TRUE;
  195. END getmaxcol;
  196.  
  197. BEGIN (* getcmdline *)
  198.   
  199.   CopyString(infile,"");
  200.   CopyString(outfile,"");
  201.   width := 0;
  202.   UnusedArgs := 0;
  203.   
  204.   FOR J := 0 TO 15 BY 1 DO
  205.     Unused[J] := 0;
  206.   END;
  207.  
  208.   MyArgc := argc;
  209. (*
  210.   WriteString("MyArgc"); WriteInt(MyArgc,4); WriteLn;
  211. *)
  212.   (* Pull out any keyword arguments from the command line: *)
  213.   J := 1;
  214.   WHILE (J < MyArgc) DO
  215. (*
  216.     WriteString(argv^[J]^);
  217. *)
  218.     IF 
  219.     (
  220.       ( CompareStringCAP( argv^[J]^ , "-i" ) = equal )
  221.       OR
  222.       ( CompareStringCAP( argv^[J]^ , "FROM" ) = equal )
  223.     ) THEN
  224.       IF ( J + 1 >= MyArgc ) THEN
  225.         WriteString
  226. ("column_set: Error -- '-i' or 'FROM' was last argument on command line");
  227.         WriteLn;
  228.     RETURN FALSE;
  229.       ELSE
  230.         CopyString(infile,argv^[J+1]^);
  231. (*
  232.         WriteString(argv^[J+1]^); WriteLn;
  233. *)
  234.         J := J + 2;
  235.       END;
  236.     ELSIF
  237.     (
  238.       ( CompareStringCAP( argv^[J]^ , "-o" ) = equal )
  239.       OR
  240.       ( CompareStringCAP( argv^[J]^ , "TO" ) = equal )
  241.     ) THEN
  242.       IF ( J + 1 >= MyArgc ) THEN
  243.         WriteString
  244. ("column_set: Error -- '-o' or 'TO' was last argument on command line");
  245.         WriteLn;
  246.     RETURN FALSE;
  247.       ELSE
  248.         CopyString(outfile,argv^[J+1]^);
  249. (*
  250.         WriteString(argv^[J+1]^); WriteLn;
  251. *)
  252.         J := J + 2;
  253.       END;
  254.     ELSIF
  255.     (
  256.       ( CompareStringCAP( argv^[J]^ , "-w" ) = equal )
  257.       OR
  258.       ( CompareStringCAP( argv^[J]^ , "WIDTH" ) = equal )
  259.     ) THEN
  260.       IF ( J + 1 >= MyArgc ) THEN
  261.         WriteString
  262. ("column_set: Error -- '-w' or 'WIDTH' was last argument on command line");
  263.         WriteLn;
  264.     RETURN FALSE;
  265.       ELSE
  266.         width := 0;
  267.         IF ( NOT getwidth(width,argv^[J + 1]^) ) THEN
  268.           RETURN FALSE;
  269.         END;
  270.     J := J + 2;
  271.       END;
  272.     ELSIF
  273.     (
  274.       ( CompareStringCAP( argv^[J]^ , "-m" ) = equal )
  275.       OR
  276.       ( CompareStringCAP( argv^[J]^ , "MAXCOL" ) = equal )
  277.     ) THEN
  278.       IF ( J + 1 >= MyArgc ) THEN
  279.         WriteString
  280. ("column_set: Error -- '-m' or 'MAXCOL' was last argument on command line");
  281.         WriteLn;
  282.     RETURN FALSE;
  283.       ELSE
  284.         maxcol := 0;
  285.         IF ( NOT getmaxcol(maxcol,argv^[J + 1]^) ) THEN
  286.           RETURN FALSE;
  287.         END;
  288.     J := J + 2;
  289.       END;
  290.     ELSE
  291.       Unused[UnusedArgs] := J;
  292.       UnusedArgs := UnusedArgs + 1;
  293.       J := J + 1;
  294.     END;
  295.   END;
  296.  
  297.   (* Pull out any remaining positional arguments from the command line: *)
  298.   J := 0;
  299.   IF ( ( CompareStringCAP(infile,"") = equal ) AND (J < UnusedArgs) ) THEN
  300.     CopyString(infile,argv^[Unused[J]]^);
  301.     J := J + 1;
  302.   END;
  303.   IF ( ( CompareStringCAP(outfile,"") = equal ) AND (J < UnusedArgs) ) THEN
  304.     CopyString(outfile,argv^[Unused[J]]^);
  305.     J := J + 1;
  306.   END;
  307.   IF ( width = 0 ) AND (J < UnusedArgs) THEN
  308.     IF ( NOT getwidth(width,argv^[Unused[J]]^) ) THEN
  309.       RETURN FALSE;
  310.     END;
  311.     J := J + 1;
  312.   END;
  313.   IF ( width = 0) THEN
  314.     width := DefaultWindowWidth;
  315.   END;
  316.   IF ( maxcol = 0 ) AND (J < UnusedArgs) THEN
  317.     IF ( NOT getmaxcol(maxcol,argv^[Unused[J]]^) ) THEN
  318.       RETURN FALSE;
  319.     END;
  320.     J := J + 1;
  321.   END;
  322.   IF ( maxcol = 0 ) THEN
  323.     maxcol := (width + 1) DIV 2;
  324.   END;
  325. (*
  326.   WriteLn;
  327. *)
  328.   RETURN TRUE;
  329. END getcmdline;
  330.  
  331. PROCEDURE writebitch;
  332. BEGIN
  333.   WriteString("column_set: Error -- problem writing OutFile = ");
  334.   WriteString(OutFile);
  335.   WriteLn;
  336.   IF (UsingStdInput) THEN
  337.     Close(TempFile);
  338.     Delete(TempFileName);
  339.   END;
  340.   IF (NOT UsingStdOutput) THEN
  341.     CloseOutput;
  342.   END;
  343.   RETURN;
  344. END writebitch;
  345.  
  346. BEGIN (* column_set *)
  347.  
  348. IF ( argc > 1 ) THEN
  349.   IF ( CompareStringCAP(argv^[1]^,"?") = equal ) THEN
  350.     usage;
  351.     RETURN;
  352.   END;
  353. END;
  354.  
  355. IF ( NOT getcmdline(InFile,OutFile,WindowWidth,MaxColumns) ) THEN
  356.   WriteString("column_set: Error -- unable to correctly parse command line!");
  357.   WriteLn;
  358.   usage;
  359.   RETURN;
  360. (*
  361. ELSE
  362.   WriteString("InFile      = "); WriteString(InFile); WriteLn;
  363.   WriteString("OutFile     = "); WriteString(OutFile); WriteLn;
  364.   WriteString("WindowWidth = "); WriteInt(WindowWidth,1); WriteLn;
  365.   WriteString("MaxColumns  = "); WriteInt(MaxColumns,1); WriteLn;
  366. *)
  367. END;
  368.  
  369. IF (CompareStringCAP(InFile,"") = equal) THEN
  370.   UsingStdInput := TRUE;
  371. ELSE
  372.   UsingStdInput := FALSE;
  373. END;
  374.  
  375. IF (CompareStringCAP(OutFile,"") = equal) THEN
  376.   UsingStdOutput := TRUE;
  377. ELSE
  378.   UsingStdOutput := FALSE;
  379. END;
  380.  
  381. IF ( UsingStdInput) THEN
  382.   Lookup(TempFile,TempFileName,TRUE);
  383.   IF (TempFile.res <> done) THEN
  384.     WriteString
  385.       ("column_set: Error -- unable to open new work file T:column_set.temp");
  386.     WriteLn;
  387.     RETURN;
  388.   END;
  389. (*
  390.   WriteString("column_set: taking data from standard input"); WriteLn;
  391. *)
  392. ELSE
  393.   OpenInputFile(InFile);
  394.   IF (NOT Done) THEN
  395.     WriteString("column_set: Error -- file open failed for InFile = ");
  396.     WriteString(InFile); WriteLn;
  397.     RETURN;
  398.   END;
  399. (*
  400.   WriteString("column_set: taking data from a named file"); WriteLn;
  401. *)
  402. END;
  403.  
  404. MaxLength := 0;
  405. ThisLength := 0;
  406. WentOK := TRUE;
  407.  
  408. IF ( UsingStdInput ) THEN
  409.   Terminal.Read(Ch);
  410.   IF (eof) THEN
  411.     WriteString
  412.       ("column_set: Error -- standard input looks empty in counting pass");
  413.     WentOK := FALSE;
  414.   END;
  415. ELSE
  416.   Read(Ch);
  417.   IF (NOT Done) THEN
  418.     WriteString("column_set: Error -- input file looks empty in counting pass");
  419.     WentOK := FALSE;
  420.   END;
  421. END;
  422.  
  423. IF (NOT WentOK) THEN
  424.   WriteLn;
  425.   Close(TempFile);
  426.   Delete(TempFileName);
  427.   IF (NOT UsingStdInput) THEN
  428.     CloseInput;
  429.   END;
  430.   RETURN;
  431. END;
  432.  
  433. LOOP
  434.   IF ( UsingStdInput ) THEN
  435.     WriteChar(TempFile,Ch);
  436.     IF (TempFile.res = notdone) THEN
  437.       WriteString
  438.         ("column_set: Error -- problem writing to file T:column_set.temp");
  439.       WriteLn;
  440.       Close(TempFile);
  441.       Delete(TempFileName);
  442.       RETURN;
  443.     END;
  444.   END;
  445.   IF (Ch <> EOL) THEN
  446.     ThisLength := ThisLength + 1;
  447.   ELSE
  448.     IF (ThisLength > MaxLength) THEN
  449.       MaxLength := ThisLength;
  450.     END;
  451.     ThisLength := 0;
  452.   END;
  453.   IF (UsingStdInput) THEN
  454.     Terminal.Read(Ch);
  455.     IF (eof) THEN
  456.       EXIT;
  457.     END;
  458.   ELSE
  459.     Read(Ch);
  460.     IF (NOT Done) THEN
  461.       EXIT;
  462.     END;
  463.   END;
  464. END;
  465.  
  466. IF ( UsingStdInput ) THEN
  467.   Close(TempFile);
  468.   IF (TempFile.res = notdone) THEN
  469.     WriteString
  470.       ("column_set: Error -- unable to close file T:column_set.temp after");
  471.     WriteString(" counting pass"); WriteLn;
  472.     RETURN;
  473.   END;
  474.   Lookup(TempFile,TempFileName,FALSE);
  475.   IF (TempFile.res <> done) THEN
  476.     WriteString
  477.       ("column_set: Error -- unable to open file T:column_set.temp before");
  478.     WriteString(" writing pass"); WriteLn;
  479.     Delete(TempFileName);
  480.     RETURN;
  481.   END;
  482. ELSE
  483.   CloseInput;
  484.   OpenInputFile(InFile);
  485.   IF (NOT Done) THEN
  486.     WriteString("column_set: Error -- File reopen failed for InFile = ");
  487.     WriteString(InFile); WriteLn;
  488.     RETURN;
  489.   END;
  490. END;
  491.  
  492. IF (NOT UsingStdOutput) THEN
  493.   OpenOutputFile(OutFile);
  494.   IF (NOT Done) THEN
  495.     WriteString("column_set: Error -- file open failed for OutFile = ");
  496.     WriteString(OutFile); WriteLn;
  497.     Close(TempFile);
  498.     Delete(TempFileName);
  499.     RETURN;
  500.   END;
  501. END;
  502.  
  503. NumColumns := (WindowWidth + 1) DIV (MaxLength + 1);
  504. IF (NumColumns > MaxColumns) THEN
  505.   NumColumns := MaxColumns;
  506. END;
  507. IF (NumColumns > 1) THEN
  508.   NumSpaces := (WindowWidth - (NumColumns * MaxLength)) DIV (NumColumns - 1);
  509. ELSE
  510.   NumSpaces := 0;
  511. END;
  512.  
  513. ThisLength := 0;
  514. ThisColumn := 0;
  515. IF ( UsingStdInput ) THEN
  516.   ReadChar(TempFile,Ch);
  517.   IF (TempFile.res <> done) THEN
  518.     IF (TempFile.eof) THEN
  519.       WriteString
  520. ("column_set: Error -- Temporary Input File Looks Empty In Writing Pass");
  521.       WriteLn;
  522.     ELSE
  523.       WriteString
  524.         ("column_set: Error -- problem reading from T:column_set.temp");
  525.     END;
  526.     Close(TempFile);
  527.     Delete(TempFileName);
  528.     IF (NOT UsingStdOutput) THEN
  529.       CloseOutput;
  530.     END;
  531.     RETURN;
  532.   END;
  533. ELSE
  534.   Read(Ch);
  535.   IF (NOT Done) THEN
  536.     WriteString("column_set: Error -- Input File Looks Empty In Writing Pass");
  537.     WriteLn;
  538.     IF (NOT UsingStdOutput) THEN
  539.       CloseOutput;
  540.     END;
  541.     CloseInput;
  542.     RETURN;
  543.   END;
  544. END;
  545.  
  546. LOOP
  547.   IF (Ch <> EOL) THEN
  548.     ThisLength := ThisLength + 1;
  549.     IF ( UsingStdOutput ) THEN
  550.       Terminal.Write(Ch);
  551. (*
  552.       Module InOut "Done" documentation is buggy; omit checks after write;
  553.       Wirth didn't specify them, and BENCHMARK doesn't support them.
  554.       No way to check "Terminal" output result - not good when redirected
  555.       to a disk file that might overflow!
  556.  
  557.       WriteString("column_set: Error -- problem writing standard output");
  558. *)
  559.     ELSE
  560.       Write(Ch);
  561. (*
  562.     Module InOut "Done" documentation is buggy; omit checks after write;
  563.     Wirth didn't specify them, and BENCHMARK doesn't support them.
  564.       IF (NOT Done) THEN
  565.         writebitch;
  566.         RETURN;
  567.       END;
  568. *)
  569.     END;
  570.   ELSE
  571.     ThisColumn := ThisColumn + 1;
  572.     IF (ThisColumn < NumColumns) THEN
  573.       FOR I := ThisLength + 1 TO MaxLength + NumSpaces BY 1 DO
  574.         IF (UsingStdOutput) THEN
  575.           Terminal.Write(" ");
  576.         ELSE
  577.           Write(" ");
  578.           IF (NOT Done) THEN
  579.             writebitch;
  580.             RETURN;
  581.           END;
  582.         END;
  583.       END;
  584.     ELSE
  585.       IF (UsingStdOutput) THEN
  586.         Terminal.WriteLn;
  587.       ELSE
  588.         Write(EOL);
  589. (*
  590.     Module InOut "Done" documentation is buggy; omit checks after write;
  591.     Wirth didn't specify them, and BENCHMARK doesn't support them.
  592.  
  593.         IF (NOT Done) THEN
  594.           writebitch;
  595.           RETURN;
  596.         END;
  597. *)
  598.       END;
  599.       ThisColumn := 0;
  600.     END;
  601.     ThisLength := 0;
  602.   END;
  603.   IF ( UsingStdInput ) THEN
  604.     ReadChar(TempFile,Ch);
  605.     IF (TempFile.res <> done) THEN
  606.       IF (TempFile.eof) THEN
  607.         EXIT;
  608.       ELSE
  609.         WriteString
  610.           ("column_set: Error -- problem reading from T:column_set.temp");
  611.         Close(TempFile);
  612.         Delete(TempFileName);
  613.         IF (NOT UsingStdOutput) THEN
  614.           CloseOutput;
  615.         END;
  616.         RETURN;
  617.       END;
  618.     END;
  619.   ELSE
  620.     Read(Ch);
  621.     IF (NOT Done) THEN (* Unable to differentiate read error from eof *)
  622.       EXIT;
  623.     END;
  624.   END;
  625. END;
  626.  
  627. IF (ThisColumn <> 0) THEN
  628.   IF (UsingStdOutput) THEN
  629.     Terminal.WriteLn;
  630.   ELSE
  631.     Write(EOL);
  632. (*
  633.     Module InOut "Done" documentation is buggy; omit checks after write;
  634.     Wirth didn't specify them, and BENCHMARK doesn't support them.
  635.     IF (NOT Done) THEN
  636.       writebitch;
  637.       RETURN;
  638.     END;
  639. *)
  640.   END;
  641. END;
  642.  
  643. IF ( UsingStdInput ) THEN
  644.   Close(TempFile);
  645.   Delete(TempFileName);
  646. ELSE
  647.   CloseInput;
  648. END;
  649.  
  650. IF (NOT UsingStdOutput) THEN
  651.   CloseOutput;
  652. END;
  653.  
  654. END column_set.
  655.