home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
World of Shareware - Software Farm 2
/
wosw_2.zip
/
wosw_2
/
PRINTING
/
CRAM_V21.ZIP
/
CRAM.C
next >
Wrap
C/C++ Source or Header
|
1990-12-31
|
15KB
|
440 lines
/*
* ------------------------------------
* C R A M - the ASCII file reducer
* ------------------------------------
*
* CRAM - ASCII File Reducer - V2.1
* Copyright (c) 1988-90 - Dean Tutterow - All Rights Reserved
*
* What does it do? It crams as much text as possible onto a page
* in reduced format. Using subscript characters as the font on an
* Epson printer, you can print up to 79 characters wide and 154 rows
* long in 2 columns. That works out to 5-6 pages of text on each
* printed page. In normal use with files with embedded formfeeds
* respected, you get 4 pages of text on each printed page.
*
* CRAM was written after I had printed another of those LONG
* documentation files. I was tired of those STACKS of listings, etc.,
* that gathered dust simply because they were too much trouble to
* handle once I printed them. Now the printed listings are small
* enough to keep in notebooks. As a bonus, CRAM is especially useful
* for printing program listings. The reduced format is just the thing
* to show program structure and the BIG picture!
*
* While not limited to Epson printers, it is hardcoded for my FX-86e.
* Of course you can provide your own setup and un-setup codes for your
* printer, and include them in a printer setup file for CRAM to use.
*
* USAGE:
*
* CRAM srcfile crammedfile [/options]
*
* where [/options] are:
* /COLUMN=n with 1 ≤ n ≥ 10
* /FF if <FF> encountered, align to next logical page
* /LARGE use PICA format to get 137 characters/line
* /PAGELENGTH=n may vary printed page length from 1-154 lines
* /SKIP=n number of columns to ignore in srcfile
* /WHITE=n number of characters of whitespace on left of page
*
* The srcfile should be a valid DOS filename; wildcards are not
* accepted. You need only supply enough to the option name to
* distinguish it from the other options, for example /C=1 and /R.
*
* As a daily VAX user, I have tried to implement the straightforward
* command-line interface that VMS affords the user. While the srcfile
* and crammedfile must be in that order, the options may be spread at
* will along the command line.
*
* The options are much easier understood after a few practice sessions.
* '/COLUMN=n' is used whenever you want more or less than the standard
* two columns on each page. While normally defaulted to two-column
* operation, only the first 79 characters on each line (unless some are
* /SKIP-ped) are visible. '/FF' respects embedded formfeeds in the
* text. Normally off, this option moves to the next logical page when
* encountered. The pagelength is adjustable through '/PAGELENGTH=n'
* The default is 132 rows, which allows two pages in each column since
* most formatters place 66 lines per page. If you want your one-column
* printing shifted right on the page so that you have whitespace on the
* left side of the page, then '/WHITE' is just the ticket. Finally,
* '/SKIP=n' ignores the first 'n' characters on each line. This allows
* you to print 79 useful characters in each column when printing
* formatted files with spaces or tabs in the first 'n' columns.
*/
#include <stdio.h>
#include <string.h>
/* G L O B A L D E F I N E S */
#define byte unsigned char
#define MAX_CHAR 161
#define MAX_ROWS 154
#define MAX_ELEMENTS 8
#define PICA 137
#define ELITE 160
/* E R R O R C O D E S */
#define FILENAME_TROUBLE 0x101
#define INVALID_OPTION 0x102
#define MISSING_FILE 0x103
#define INVLD_NUM_COLUMNS 0x104
/* S E V E R I T Y C O D E S */
#define FATAL "F"
#define SEVERE "S"
#define WARNING "W"
#define INFORMATIONAL "I"
/* G L O B A L D A T A */
char BUFFER[MAX_ROWS][MAX_CHAR];
char PRINTER_INIT[200];
char PRINTER_TERM[200];
int SKIP_PT = 0;
int NUM_COLS = 2;
int NUM_CHAR = MAX_CHAR - 1;
int NUM_ROWS = MAX_ROWS;
byte NUM_FILES = 0;
byte WHITE = 0;
byte FF = 0;
byte DISPLAYABLE;
byte LEFT_EDGE;
char *INFILE, *OUTFILE;
FILE *INPUT, *OUTPUT;
main (argc,argv)
int argc;
char *argv[];
{
int i, j, carryover, value, lr, lc, current_col;
char equivalence[100], parsed[120], *elements[MAX_ELEMENTS];
char *option, *parse_option(), *status, *file_status, line[161];
/* Tell them who I am. */
print_copyright ();
/* Parse the command line for files and switches. */
memset (equivalence, '\0', sizeof (equivalence));
memset (parsed, '\0', sizeof (parsed));
for (i = 0; i < argc; i++) {
strcat (equivalence, argv[i]);
strcat (equivalence, " ");
};
value = MAX_ELEMENTS;
parse_command_line (equivalence, parsed, elements, &value);
get_filenames_and_options (elements, &value, &INFILE, &OUTFILE);
get_printer_defaults ();
if (NUM_FILES != 2) err_exit (MISSING_FILE, FATAL);
if (NUM_ROWS > MAX_ROWS) NUM_ROWS = MAX_ROWS;
/* Open the proper files for reading/writing. */
INPUT = fopen (INFILE, "rt");
OUTPUT = fopen (OUTFILE, "wt");
if (!INPUT || !OUTPUT) err_exit (FILENAME_TROUBLE, FATAL);
/* Send the printer setup string. */
fputs (PRINTER_INIT, OUTPUT);
/* Compute the maximum displayable portion of the input line. */
DISPLAYABLE = ( NUM_CHAR - NUM_COLS + 1 - WHITE ) / NUM_COLS;
/* Read from the input file and build the output file in memory. */
carryover = 0;
do {
LEFT_EDGE = WHITE;
memset (BUFFER, ' ', NUM_ROWS * MAX_CHAR);
for ( i=0; i < NUM_ROWS; i++ ) BUFFER[i][NUM_CHAR] = 0;
for ( current_col=1,lc=lr=0; current_col<=NUM_COLS; current_col++ ) {
if ( carryover ) {
filter_input(&line[0]);
line[DISPLAYABLE] = '\0';
if ( current_col != NUM_COLS )
strncpy (&BUFFER[0][LEFT_EDGE], &line[0], strlen(line));
else
strcpy (&BUFFER[0][LEFT_EDGE], &line[0]);
};
for ( i=carryover; i < NUM_ROWS; i++ ) {
carryover = 0;
file_status = fgets (line, 159, INPUT);
if (file_status == NULL) break;
if ( FF && (line[0] == '\f') )
if (i <= (NUM_ROWS+1)/2) i = carryover = (NUM_ROWS+1)/2;
else {carryover = 1; break; }
filter_input(&line[0]);
line[DISPLAYABLE] = '\0';
if ( current_col != NUM_COLS )
strncpy (&BUFFER[i][LEFT_EDGE], &line[0], strlen(line));
else
strcpy (&BUFFER[i][LEFT_EDGE], &line[0]);
};
if ( i > lr ) lr = i;
if (file_status == NULL) break;
LEFT_EDGE = LEFT_EDGE + DISPLAYABLE + 1;
if ( carryover > 1 ) carryover = 0;
};
/* Write out a page buffer and get ready for next page. */
for (i=0; i < lr; i++) {
j = strlen(&BUFFER[i][0]);
if (j)
if (BUFFER[i][j-1] == '\n') j--;
if ( j > (NUM_CHAR - 1) ) j = NUM_CHAR - 1;
BUFFER[i][j] = '\n';
BUFFER[i][j+1] = '\0';
fputs (&BUFFER[i][0], OUTPUT);
};
if (file_status != NULL) fputs ("\xc\0", OUTPUT);
} while (file_status);
/* Send the printer termination string and close all files. */
fputs (PRINTER_TERM, OUTPUT);
fclose(INPUT);
fclose(OUTPUT);
}
int _nullcheck () {};
int _setenvp () {};
int print_copyright ()
{
fprintf (stderr, "CRAM - ASCII File Reducer - V2.1\n");
fprintf (stderr, "Copyright (c) 1988-90 - Dean Tutterow - All Rights Reserved\n");
}
int filter_input (line)
char *line;
{
int i, n;
char newline[161], *oldline;
/* Clean all tabs and formfeeds from the input line. */
oldline = line;
memset (newline, '\0', sizeof (newline));
for ( i = 0; i < sizeof(newline); ) {
if (*line == '\0') { newline[i] = '\0'; break; }
if (*line == '\n') *line = ' ';
if (*line == '\f') {
*line = ' '; strcpy (&newline[i], "<FF>"); i += 4; }
if (*line == '\t') {
n = i;
while (n >= 0)
n -= 8;
n = -n;
strncpy (&newline[i], " ", n);
i += (n - 1); }
else
newline[i] = *line;
i++;
line++;
};
if (newline[0] != 0x0D)
strcpy (oldline, &newline[SKIP_PT]);
else
strcpy (oldline, &newline[0]);
}
int get_printer_defaults ()
{
char *file_status;
INPUT = fopen ("CRAM.DAT", "rt");
if ( !INPUT ) {
if ( NUM_CHAR == PICA )
strcpy ( PRINTER_INIT, "\x1b\x33\xf\x1b\x53\x30\xf\0" );
else
strcpy ( PRINTER_INIT, "\x1b\x33\xf\x1b\x53\x30\x1b\x4d\xf\0" );
strcpy ( PRINTER_TERM, "\x1b\x32\x1b\x54\x1b\x50\x12\x1a\0" );
return;
}
file_status = fgets (PRINTER_INIT, sizeof (PRINTER_INIT), INPUT);
if ( file_status == NULL ) goto file_error;
file_status = fgets (PRINTER_TERM, sizeof (PRINTER_TERM), INPUT);
if ( file_status == NULL ) goto file_error;
file_error:
fclose (INPUT);
return;
}
int parse_command_line (input, output, arrayed, number)
char *input, *output, *arrayed[];
int *number;
{
int i, j, k, paren;
/* Convert input line to upper case */
for (i=0; i < strlen(input); i++)
(input)[i] = toupper ( (input)[i] );
(output)[0] = ' ';
for (i=k=paren=0, j=1; (i < strlen (input) && k <= *number); i++) {
switch ( (input)[i] ) {
case ',' : if (paren) { (output)[j] = (input)[i]; break; }
case ' ' :
case '\t' : (output)[j] = ' '; break;
case '/' : (output)[j] = ' '; j++; paren--;
case '(' : paren += 2;
case ')' : paren--;
default : (output)[j] = (input)[i];
}
j++;
/*
* If this is the start of an argument, then place its address
* in the argument list & null-terminate the previous argument.
*/
if ( (output)[j-1] != ' ' && (output)[j-2] == ' ' ) {
if (k != *number) {
(arrayed)[k] = (&(output)[j-1]);
k++;
}
(output)[j-2] = '\0';
}
};
(output)[j] = '\0';
*number = k;
};
char *parse_option (option, output)
char *option, **output;
{
int length_to_option;
if (*option != '/') return (0);
if (!(length_to_option = strcspn (option, "=:"))) return (0);
if (length_to_option == strlen (option)) return (0);
*output = option + length_to_option + 1;
return ((char *)output);
}
int get_filenames_and_options (elements, value, INFILE, OUTFILE)
char **INFILE, **OUTFILE, *elements[];
int *value;
{
int first, i;
char *status, *option, *parse_option(), first_char;
for (i = first = 1; i < *value; i++) {
if (*elements[i] != '/') {
if (first) { *INFILE = elements[i]; first = 0; }
else *OUTFILE = elements[i];
NUM_FILES++; }
else {
first_char = *(elements[i] + 1);
switch (first_char) {
case 'C' : /* # OF COLUMNS PARAMETER */
status = parse_option (elements[i], &option);
if (status) sscanf (option, "%d", &NUM_COLS);
else NUM_COLS = 2;
if ( NUM_COLS > 10 || NUM_COLS < 1 )
err_exit (INVLD_NUM_COLUMNS, FATAL);
break;
case 'F' : /* RECOGNIZE FORMFEEDS */
FF = 1;
break;
case 'L' : /* LARGE-SMALL PRINT (CHARS/LINE = 137) */
NUM_CHAR = PICA;
break;
case 'P' : /* LINES-PER-PAGE PARAMETER */
status = parse_option (elements[i], &option);
if (status) sscanf (option, "%d", &NUM_ROWS);
else NUM_ROWS = MAX_ROWS;
break;
case 'S' : /* START INPUT PROCESSING AT THIS POSITON */
status = parse_option (elements[i], &option);
if (status) sscanf (option, "%d", &SKIP_PT);
else SKIP_PT = 0;
break;
case 'W' : /* WHITE SPACE ON LEFT */
status = parse_option (elements[i], &option);
if (status) sscanf (option, "%d", &WHITE);
else WHITE = 35;
if ( WHITE > MAX_CHAR/2 ) WHITE = 35;
break;
default :
err_exit (INVALID_OPTION, WARNING);
}
}
};
}
int err_exit (code, severity)
int code;
char *severity;
{
char err_code[20], msg[50];
/* Display an error message, delete output file, exit. */
switch (code) {
case FILENAME_TROUBLE :
strcpy (msg, "Trouble opening files, please check filenames.");
strcpy (err_code, "FILEOPEN");
break;
case MISSING_FILE :
strcpy (msg, "You must specify an input and output file.");
strcpy (err_code, "MISSFILE");
break;
case INVALID_OPTION :
strcpy (msg, "You have specified an invalid option.");
strcpy (err_code, "INVLDOPT");
break;
case INVLD_NUM_COLUMNS :
strcpy (msg, "You have specified an invalid number of columns.");
strcpy (err_code, "IVLDCOLS");
break;
default :
strcpy (msg, "Unknown error!");
strcpy (err_code, "UNKNOWN");
}
fprintf (stderr, "\nCRAM-%c-%s, %s\n", *severity, err_code, msg);
if ( (*severity == 'F') || (*severity == 'S') ) {
fprintf (stderr, "\n usage: CRAM infile outfile [options]\n\n");
fprintf (stderr, " where [options] are:\n\t[/column=N]\n\t[/ff]\n\t");
fprintf (stderr, "[/large]\n\t[/pagelength=N]\n\t");
fprintf (stderr, "[/skip=N]\n\t[/white=N]\n");
/* Close two files and delete partial output */
fclose (INPUT);
fclose (OUTPUT);
unlink (OUTFILE);
/* Exit with errorlevel 1 */
exit (1);
}
}