Newer
Older
Microsoft / pp / PP.C
@tundra tundra on 24 May 2012 11 KB Initial revision
/*	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);

}