home *** CD-ROM | disk | FTP | other *** search
- /*
- * ------------------------------------
- * 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);
- }
- }
-