/* PP.C - Pretty Printer Incorporating Print Directives And Variable Formatting Copyright (C) 1986, 1987 T.A. Daneliuk Last Modified: 02/19/87 */ #include <stdio.h> #include <system.h> #include <filefind.h> /* Global Defaults, Counters, Buffers, And State Flags */ #define HDRDEFALT 3 /* Default Header Length */ static struct DataArea mydta; /* Working DTA For Wildcards */ static int pwidth=132; /* Page Width */ static int plen=56; /* Page Length */ static int tabsz=4; /* Tab Expansion Size */ static char line[6]; /* Current Source Line Number */ static row=1; /* Current Physical Line Number */ static int col=1; /* Horizontal Position Being Printed */ static char page[4]; /* Page Counter */ static char nest[3]; /* Curly Brace Nesting Level */ static int linenums=TRUE; /* If TRUE, prints line numbers */ static int header=TRUE; /* If TRUE, prints header */ static int hdrlen=HDRDEFALT+1; /* Number Of Lines In Header */ static int squote; /* Single Quote Flag */ static int dquote; /* Double Quote Flag */ static int comment; /* Comment Flag */ static int prtstdin=FALSE; /* Means stdin In Input File List */ static int messages=TRUE; /* Means Display Error Messages */ static int start=1; /* Beginning Position Of Text */ /* Global Constants And Print Formatting Offsets */ #define CR 0x0d /* Carriage Return */ #define LF 0x0a /* Line Feed */ #define EOL 0x0d0a /* End-Of-Line */ #define TOF 0x0c /* Top-Of-Form Character */ #define OUTSZ (pwidth+3) /* Size Of Output Buffer */ #define HDRSZ ((pwidth+2)*HDRDEFALT)+1 /* Size Of Header Buffer */ #define PAGEPOS 8 /* Page Number Posn From Rt. Margin */ #define DATEPOS 21 /* Date Position From Rt. Margin */ #define TIMEPOS 8 /* Time Position From Rt. Margin */ #define NESTPOS 0 /* Offset Of Nesting String */ #define LINOPOS 3 /* Offset Of Line Number String */ #define TEXTPOS 10 /* Offset Of Beginning Of Text */ /*********************** Main Body Of PP.C Logic *****************************/ main(argc,argv) int argc; char *argv[]; { int c; /* Read Character */ int f; /* argv Offset For Filenames */ int g,h; /* Temporary */ int fp; /* Working File Pointer */ int first; /* Working Flag */ char *fn; /* Filename Pointer */ char name[129]; /* Name w/ Path For fopen() */ banner(); /* Display Logon Banner */ f=parse_args(argc,argv); /* Parse Command Line Args. */ if ((f == argc) || (prtstdin)) /* No Filename Passed */ { if (messages) fputs("Now Printing: <stdin> ",stderr); /* So Use stdin Data */ pp(stdin,"<stdin>"); if (messages) { fputs(line,stderr); fputs(" Line(s) Printed !\n",stderr); } } if (f != argc) while(f < argc) /* Process Passed Filenames */ { for (h=0;*(argv[f]+h) != '\0';h++) *(argv[f]+h)=toupper(*(argv[f]+h)); /* Make all UC */ strcpy(name,argv[f]); /* Copy Full Name For The fopen() */ h=strlen(name)-1; /* Strip Off Everything But Path */ while((name[h]) != ':' && (name[h] != '\\') && (h > -1)) h--; first=TRUE; while (wildcard(argv[f],&mydta,first) != 0) { first=FALSE; /* Made it thru 1st time */ fn=mydta.dta_name; name[h+1]='\0'; /* Append Filename To Path */ strcat(name,fn); fp=fopen(name,"r"); if (fp != NULL) /* Successful Open */ { if (messages) { fputs("Now Printing: ",stderr); fputs(name,stderr); g=43-strlen(name); /* Pad So Line Display Aligns */ while (--g) fputc(' ',stderr); } pp(fp,fn); fclose(fp); if (messages) { fputs(line,stderr); fputs(" Line(s) Printed !\n",stderr); } } else if (messages) /* Open Failed */ { fputs("Cannot Open: ",stderr); fputs(argv[f],stderr); fputs("\n",stderr); } } if (first && messages) /* Failed on 1st try, bad wc spec */ { fputs("Cannot Open: ",stderr); fputs(argv[f],stderr); fputs("\n",stderr); } f++; } } /*************************** Display Logon Banner ****************************/ void banner() { scr_setup(); scr_clr(); scr_rowcol(0,0); fputs("PP - Pretty Printer Version 1.2.1\n",stderr); fputs("Copyright (C) 1986, 1987 By T&R Communications Associates, Chicago, IL, 60625\n",stderr); fputs("Permission Granted For Unlimited * NON-COMMERCIAL * Distribution !!!\n\n",stderr); } /*********************** Parse Command Line Arguments ************************/ parse_args(argc,argv) int argc; char *argv[]; { int x,c,tmp; FILE *fp; x = 1; fp = NULL; while ( ((*argv[x]) == '-') && (x < argc) ) { switch(*(argv[x]+1)) { case 0: /* Just passed a - */ prtstdin=TRUE; /* Treat stdin as a passed filename */ break; case 'h': if (*(argv[x]+2)) /* Should be NULL */ error(NULL); else { header=FALSE; hdrlen=0; } break; case 'i': if (*(argv[x]+2)) /* Is an init file named? */ { fp=fopen(argv[x]+2,"r"); if (fp == NULL) /* Couldn't open init file */ error(NULL); while ((c=fgetc(fp)) != EOF) fputc(c,stdout); fclose(fp); } else error(NULL); break; case 'l': tmp=atoi((argv[x]+2)); if ((tmp < 10) || (tmp > 128)) error(NULL); else plen=tmp; break; case 'm': if (*(argv[x]+2)) /* Should be NULL */ error(NULL); else messages=FALSE; break; case 'n': if (*(argv[x]+2)) /* Should be NULL */ error(NULL); else linenums=FALSE; break; case 't': tmp=atoi((argv[x]+2)); if ((tmp < 2) || (tmp > 32)) error(NULL); else tabsz=tmp; break; case 'w': tmp=atoi((argv[x]+2)); if ((tmp < 50) || (tmp > 512)) error(NULL); else pwidth=tmp; break; default: error(NULL); } x++; } return(x); } /*********************** Error Abort Handling Routine ************************/ void error(msg) char *msg; { if (messages) { if (msg) { fputs("PP Error: ",stderr); fputs(msg,stderr); fputs(" !!!\n\n",stderr); } else fputs("Usage: pp [-h -i -l -m -n -t -w -] filename(s) [>output device]\n\n",stderr); } exit(1); } /***************** Initialize Header Buffer And Globals **********************/ void init(hdrptr,filnam,fp) char *hdrptr,*filnam; int fp; { int tmp; char t[9],d[9],ft[9],fd[9],*offset; times(t); dates(d); for (tmp=0;tmp < 8;tmp++) /* Stuff DeSmet's spaces */ { if (t[tmp] == ' ') t[tmp] = '0'; if (d[tmp] == ' ') d[tmp] = '0'; } if (fp != stdin) fstamp(fp,fd,ft); /* Get File Date/Time Stamp */ else { strcpy(fd,d); /* Use today for stdin stamp */ strcpy(ft,t); } tmp=0; /* First Do The Header */ while (tmp < HDRSZ) { *(hdrptr+tmp)=' '; /* Initialize With Blanks */ tmp++; } tmp=1; while (tmp <= HDRDEFALT) /* Stuff CR/LF Characters */ { offset=(hdrptr+(pwidth*tmp)+(2*(tmp-1))); *offset=CR; *(offset+1)=LF; tmp++; } *(hdrptr+HDRSZ-1)='\0'; /* Stuff Strings */ strdup(hdrptr,filnam); strdup((hdrptr+pwidth-PAGEPOS-8)," Page:"); strdup((hdrptr+(pwidth*2)+2-DATEPOS-9),"Printed: At:"); strdup((hdrptr+(pwidth*2)+2-DATEPOS),d); strdup((hdrptr+(pwidth*2)+2-TIMEPOS),t); strdup((hdrptr+(pwidth*3)+4-DATEPOS-15),"Last Modified: At:"); strdup((hdrptr+(pwidth*3)+4-DATEPOS),fd); strdup((hdrptr+(pwidth*3)+4-TIMEPOS),ft); strcpy(line,"00001"); /* Now Do All The Globals */ col=1; strcpy(page,"001"); strcpy(nest,"01"); squote=FALSE; dquote=FALSE; comment=FALSE; if (linenums) start=(sizeof(line)+2); /* Default is 1 - No line nums */ } /***************************** Force New Page ********************************/ void newpage(hdrptr) char *hdrptr; { fputc(TOF,stdout); if (header) { strdup(hdrptr+pwidth-PAGEPOS,page); fputs(hdrptr,stdout); fputc('\n',stdout); bump(page,sizeof(page)); } newline(); row=hdrlen+1; } /***************************** Begin New Line ********************************/ void newline() { if (linenums) { fputs(line,stdout); fputs(" ",stdout); } col=start; } /******************************* Wrap A Line *********************************/ void wrap(hdrptr,fp) char *hdrptr; int fp; { int x; x=fgetc(fp); /* Throw away whitespace */ while ((x == ' ') || (x == TAB) || (x == '\r')) x=fgetc(fp); ungetc(x,fp); fputc('\n',stdout); row++; if (row > plen) newpage(hdrptr); else { x=start; while (x) { fputc(' ',stdout); x--; } col=start+1; } } /**************************** Bump ASCII Count *******************************/ void bump(ptr,sz) char *ptr; int sz; { int carry,tmp; carry=1; sz=sz-2; while (sz >= 0) { tmp=(*(ptr+sz))-'0'; tmp=tmp+carry; if (tmp < 10) carry=0; else { tmp=tmp-10; carry=1; } *(ptr+sz)=('0'+tmp); sz--; } } /***************************** Print Routine *********************************/ void pp(fp,filnam) int fp; char *filnam; { int c,e,x; /* Working Character */ char *hdrptr; /* Buffer Pointers */ c = e = x = 0; /* Get Buffer Space And Initialize Buffer Pointers */ hdrptr = calloc(HDRSZ,sizeof(char)); if (hdrptr == NULL) error("Couldn't Allocate Header Buffer - Insufficient Memory"); init(hdrptr,filnam,fp); /* Initialize Header/Globals */ /* Actual Print Logic */ c=fgetc(fp); if (c != EOF) newpage(hdrptr); ungetc(c,fp); while ((c=fgetc(fp)) != EOF) { if (col > pwidth) /* Start next line */ { ungetc(c,fp); /* Save for next time around */ c=-1; } switch(c) { case -1: /* Gotta start a new line */ wrap(hdrptr,fp); e=' '; /* Last char really printed */ break; case TOF: /* Allow embedded formfeeds */ if (e != '\n') /* Terminate partial line */ fputc('\n',stdout); newpage(hdrptr); if (linenums) /* Save last char printed */ e=' '; else e='\n'; break; case '\r': /* Ignore CR because of fputc() */ break; /* Translates LF to CR-LF ! */ case '\n': /* Process end of line */ fputc(c,stdout); if ((c=fgetc(fp)) != EOF) /* Count up if not a file end */ { bump(line,sizeof(line)); /* Bump source line number */ row++; /* Bump physical line number */ if (row > plen) newpage(hdrptr); else newline(); } ungetc(c,fp); c='\n'; break; case TAB: /* Expand TABs to spaces */ x = ((col-start+1) % tabsz); x = (x == 0 ? tabsz : x); x = (tabsz+1) - x; while (x) { if (col > pwidth) { c=wrap(hdrptr,fp); x=0; } else { fputc(' ',stdout); x--; col++; } } e=' '; /* Last char really printed */ break; default: fputc(c,stdout); col++; e=c; break; } } if (e != '\n') /* For printers like laser */ fputs("\n",stdout); /* That maintain column after FF */ /* Release Buffer Space */ free(hdrptr); }