xref: /csrg-svn/usr.bin/indent/io.c (revision 21969)
1*21969Sdist /*
2*21969Sdist  * Copyright (c) 1980 Regents of the University of California.
3*21969Sdist  * All rights reserved.  The Berkeley software License Agreement
4*21969Sdist  * specifies the terms and conditions for redistribution.
5*21969Sdist  */
68803Smckusick 
7*21969Sdist #ifndef lint
8*21969Sdist static char sccsid[] = "@(#)io.c	5.1 (Berkeley) 06/04/85";
9*21969Sdist #endif not lint
10*21969Sdist 
118803Smckusick /*
128803Smckusick 
138803Smckusick 			  Copyright (C) 1976
148803Smckusick 				by the
158803Smckusick 			  Board of Trustees
168803Smckusick 				of the
178803Smckusick 			University of Illinois
188803Smckusick 
198803Smckusick 			 All rights reserved
208803Smckusick 
218803Smckusick 
228803Smckusick FILE NAME:
238803Smckusick 	io.c
248803Smckusick 
258803Smckusick PURPOSE:
268803Smckusick 	Contains routines to handle i/o related stuff for indent.
278803Smckusick 
288803Smckusick GLOBALS:
298803Smckusick 	None
308803Smckusick 
318803Smckusick FUNCTIONS:
328803Smckusick 	dump_line
338803Smckusick 	fill_buffer
348803Smckusick 	pad_output
358803Smckusick 	count_spaces
368803Smckusick 	eqin
378803Smckusick 	cmp
388803Smckusick 
398803Smckusick */
408803Smckusick /*
418803Smckusick 
428803Smckusick 			  Copyright (C) 1976
438803Smckusick 				by the
448803Smckusick 			  Board of Trustees
458803Smckusick 				of the
468803Smckusick 			University of Illinois
478803Smckusick 
488803Smckusick 			 All rights reserved
498803Smckusick 
508803Smckusick 
518803Smckusick NAME:
528803Smckusick 	dump_line
538803Smckusick 
548803Smckusick FUNCTION:
558803Smckusick 	Does the actual printing of the stored up line
568803Smckusick 
578803Smckusick ALGORITHM:
588803Smckusick 	For each of the label, code, and comment sections which are used on
598803Smckusick 	this line:
608803Smckusick 
618803Smckusick 	1) Use pad_output to get the section aligned properly.
628803Smckusick 	2) write the section
638803Smckusick 
648803Smckusick 	The indentation level used for the code is set by ind_level.  After
658803Smckusick 	printing, ind_level is set to i_l_follow.
668803Smckusick 
678803Smckusick 	An extra level of indentation is added if ind_stmt is 1.  After
688803Smckusick 	printing, ind_stmt is set to 1 iff the line just printed has an
698803Smckusick 	unterminated, non-declaration statement.
708803Smckusick 
718803Smckusick PARAMETERS:
728803Smckusick 	None
738803Smckusick 
748803Smckusick RETURNS:
758803Smckusick 	Nothing
768803Smckusick 
778803Smckusick GLOBALS:
788803Smckusick 	labbuf
798803Smckusick 	s_lab
808803Smckusick 	e_lab =		Reset to s_lab
818803Smckusick 
828803Smckusick 	codebuf
838803Smckusick 	s_code
848803Smckusick 	e_code =	Reset to s_code
858803Smckusick 
868803Smckusick 	combuf
878803Smckusick 	s_com
888803Smckusick 	e_com =		Reset to s_com
898803Smckusick 
908803Smckusick 	bl_line =	Set to true iff the line was blank
918803Smckusick 	case_ind
928803Smckusick 	code_lines =	Count lines with code
938803Smckusick 	com_col
948803Smckusick 	com_lines =	Keep track of lines with comments
958803Smckusick 	decl_on_line =	Set to in_decl after line is printed
968803Smckusick 	i_l_follow
978803Smckusick 	in_decl
988803Smckusick 	in_stmt
998803Smckusick 	ind_level =	Set to i_l_follow at completion
1008803Smckusick 	ind_size
1018803Smckusick 	ind_stmt =	Set to in_stmt at completion if not in declaration
1028803Smckusick 	out_lines =	Count output lines
1038803Smckusick 	p_l_follow
1048803Smckusick 	paren_level =	Set to p_l_follow at completion
1058803Smckusick 	pcase
1068803Smckusick 	use_ff =	Reset to false
1078803Smckusick 
1088803Smckusick CALLS:
1098803Smckusick 	pad_output
1108803Smckusick 	printf (lib)
1118803Smckusick 	write (lib)
1128803Smckusick 
1138803Smckusick CALLED BY:
1148803Smckusick 	main
1158803Smckusick 	pr_comment
1168803Smckusick 
1178803Smckusick HISTORY:
1188803Smckusick 	initial coding 	November 1976	D A Willcox of CAC
1198803Smckusick 
1208803Smckusick */
1218803Smckusick #include "indent_globs.h";
1228803Smckusick 
1238803Smckusick 
1248803Smckusick 
1258803Smckusick int     ff = 014;	       /* used to write a form feed */
1268803Smckusick 
1278803Smckusick 
1288803Smckusick dump_line () {		       /* dump_line is the routine that actually
1298803Smckusick 			          effects the printing of the new source.
1308803Smckusick 			          It prints the label section, followed by
1318803Smckusick 			          the code section with the appropriate
1328803Smckusick 			          nesting level, followed by any comments
1338803Smckusick 			       */
1348803Smckusick     register int    cur_col,
1358803Smckusick                     temp_col,
1368803Smckusick                     target_col;
1378803Smckusick 
1388803Smckusick     bl_line = true;	       /* if we don't find otherwise, assume a
1398803Smckusick 			          blank line */
1408803Smckusick 
1418803Smckusick     if (ind_level == 0)
1428803Smckusick 	ind_stmt = 0;	       /* this is a class A kludge. don't do
1438803Smckusick 			          additional statement indentation if we
1448803Smckusick 			          are at bracket level 0 */
1458803Smckusick 
1468803Smckusick     if (e_lab != s_lab || e_code != s_code)
1478803Smckusick 	++code_lines;	       /* keep count of lines with code */
1488803Smckusick 
1498803Smckusick     if (e_lab != s_lab) {      /* print lab, if any */
1508803Smckusick 	if (pcase)	       /* if the label is really a case, we must
1518803Smckusick 			          indent */
1528803Smckusick 	    cur_col = pad_output (1, case_ind * ind_size + 1);
1538803Smckusick 	else {
1548803Smckusick 	    if (*s_lab == '#') /* check for #define, etc */
1558803Smckusick 		cur_col = 1;
1568803Smckusick 	    else
1578803Smckusick 		cur_col = pad_output (1, ind_size * (ind_level - label_offset) + 1);
1588803Smckusick 	}
1598803Smckusick 
1608803Smckusick 	write (output, s_lab, e_lab - s_lab);
1618803Smckusick 	cur_col = count_spaces (cur_col, s_lab);
1628803Smckusick     /* count_spaces gives number of characters, considering tabs */
1638803Smckusick 	bl_line = false;       /* line not blank after all */
1648803Smckusick     }
1658803Smckusick     else
1668803Smckusick 	cur_col = 1;	       /* there is no label section */
1678803Smckusick 
1688803Smckusick     pcase = false;
1698803Smckusick 
1708803Smckusick     if (s_code != e_code) {    /* print code section, if any */
1718803Smckusick 	target_col = ind_size * (ind_level + paren_level + ind_stmt) + 1;
1728803Smckusick 
1738803Smckusick 	cur_col = pad_output (cur_col, target_col);
1748803Smckusick     /* pad_output writes enough tabs and spaces to get the current char
1758803Smckusick        position up to target_col */
1768803Smckusick 	write (output, s_code, e_code - s_code);
1778803Smckusick 	cur_col = count_spaces (cur_col, s_code);
1788803Smckusick 	bl_line = false;       /* line not blank */
1798803Smckusick     }
1808803Smckusick 
1818803Smckusick     if ((cur_col - 1) > max_col && output!=1)/* check for line too long */
1828803Smckusick 	printf ("%d: Code has %d chars, max is %d\n", line_no, (cur_col - 1), max_col);
1838803Smckusick 
1848803Smckusick     if (s_com != e_com) {      /* print comment, if any */
1858803Smckusick 	if (cur_col > com_col && count_spaces (cur_col, s_com) >= max_col) {
1868803Smckusick 	/* if comment can't fit on this line, put it on next line */
1878803Smckusick 	    write (output, "\n", 1);
1888803Smckusick 	    cur_col = 1;
1898803Smckusick 	    ++out_lines;
1908803Smckusick 	}
1918803Smckusick 	cur_col = pad_output (cur_col, com_col);
1928803Smckusick 	write (output, s_com, e_com - s_com);
1938803Smckusick 
1948803Smckusick 	cur_col = count_spaces (cur_col, s_com);
1958803Smckusick 	if ((cur_col - 1) > max_col && output!=1)/* check for too long comment */
1968803Smckusick 	    printf ("%d: Comment goes to column %d.  Max is %d\n",
1978803Smckusick 		line_no, (cur_col - 1), max_col);
1988803Smckusick 
1998803Smckusick 	bl_line = false;
2008803Smckusick 	++com_lines;	       /* count lines with comments */
2018803Smckusick     }
2028803Smckusick 
2038803Smckusick     if (use_ff)
2048803Smckusick 	write (output, &ff, 1);/* end the output with a ff */
2058803Smckusick     else
2068803Smckusick 	write (output, "\n", 1); /* or a newline */
2078803Smckusick     use_ff = false;
2088803Smckusick     *(e_lab = s_lab) = '\0';   /* reset buffers */
2098803Smckusick     *(e_code = s_code) = '\0';
2108803Smckusick     *(e_com = s_com) = '\0';
2118803Smckusick 
2128803Smckusick     ind_level = i_l_follow;
2138803Smckusick     paren_level = p_l_follow;
2148803Smckusick     ++out_lines;
2158803Smckusick     decl_on_line = in_decl;    /* if we are in the middle of a
2168803Smckusick 			          declaration, remember that fact for
2178803Smckusick 			          proper comment indentation */
2188803Smckusick     ind_stmt = in_stmt & ~in_decl;
2198803Smckusick  /* next line should be indented if we have not completed this stmt and if
2208803Smckusick     we are not in the middle of a declaration */
2218803Smckusick 
2228803Smckusick     return;
2238803Smckusick };
2248803Smckusick /*
2258803Smckusick 
2268803Smckusick 			  Copyright (C) 1976
2278803Smckusick 				by the
2288803Smckusick 			  Board of Trustees
2298803Smckusick 				of the
2308803Smckusick 			University of Illinois
2318803Smckusick 
2328803Smckusick 			 All rights reserved
2338803Smckusick 
2348803Smckusick 
2358803Smckusick NAME:
2368803Smckusick 	fill_buffer
2378803Smckusick 
2388803Smckusick FUNCTION:
2398803Smckusick 	Reads one block of input into input_buffer
2408803Smckusick 
2418803Smckusick ALGORITHM:
2428803Smckusick 	Trivial
2438803Smckusick 
2448803Smckusick PARAMETERS:
2458803Smckusick 	None
2468803Smckusick 
2478803Smckusick RETURNS:
2488803Smckusick 	Nothing
2498803Smckusick 
2508803Smckusick GLOBALS:
2518803Smckusick 	in_buffer =
2528803Smckusick 	buf_end =	Set to 1 past last character read in
2538803Smckusick 	buf_ptr =	Set to start of buffer
2548803Smckusick 	be_save =	Set to zero if it was non-zero
2558803Smckusick 	bp_save =	Set to zero
2568803Smckusick 
2578803Smckusick CALLS:
2588803Smckusick 	read (lib)
2598803Smckusick 
2608803Smckusick CALLED BY:
2618803Smckusick 	lexi
2628803Smckusick 	main
2638803Smckusick 	pr_comment
2648803Smckusick 
2658803Smckusick HISTORY:
2668803Smckusick 	initial coding 	November 1976	D A Willcox of CAC
2678803Smckusick 	1/7/77		D A Willcox of CAC	Added check for switch back to
2688803Smckusick 						partly full input buffer from
2698803Smckusick 						temporary buffer
2708803Smckusick 
2718803Smckusick */
2728803Smckusick int     fill_buffer () { /* this routine reads stuff from the input */
2738803Smckusick     int     count;
2748803Smckusick     register int    i;
2758803Smckusick 
2768803Smckusick     if (bp_save != 0) {	       /* there is a partly filled input buffer
2778803Smckusick 			          left */
2788803Smckusick 	buf_ptr = bp_save;     /* don't read anything, just switch buffers
2798803Smckusick 			       */
2808803Smckusick 	buf_end = be_save;
2818803Smckusick 	bp_save = be_save = 0;
2828803Smckusick 	if (buf_ptr < buf_end)
2838803Smckusick 	    return;	       /* only return if there is really something
2848803Smckusick 			          in this buffer */
2858803Smckusick     }
2868803Smckusick 
2878803Smckusick     count = read (input, in_buffer, inp_bufs);
2888803Smckusick 
2898803Smckusick     buf_end = in_buffer + count;
2908803Smckusick     buf_ptr = in_buffer;
2918803Smckusick 
2928803Smckusick     if (count == 0) {	       /* count of zero means eof */
2938803Smckusick 	had_eof = true;
2948803Smckusick 	*buf_end++ = ' ';
2958803Smckusick 	*buf_end++ = '\n';     /* insert extra newline.  it will
2968803Smckusick 			          eventually get indent to stop */
2978803Smckusick     }
2988803Smckusick 
2998803Smckusick     return;
3008803Smckusick };
3018803Smckusick /*
3028803Smckusick 
3038803Smckusick 			  Copyright (C) 1976
3048803Smckusick 				by the
3058803Smckusick 			  Board of Trustees
3068803Smckusick 				of the
3078803Smckusick 			University of Illinois
3088803Smckusick 
3098803Smckusick 			 All rights reserved
3108803Smckusick 
3118803Smckusick 
3128803Smckusick NAME:
3138803Smckusick 	pad_output
3148803Smckusick 
3158803Smckusick FUNCTION:
3168803Smckusick 	Writes tabs and spaces to move the current column up to the
3178803Smckusick 	desired position.
3188803Smckusick 
3198803Smckusick ALGORITHM:
3208803Smckusick 	Put tabs and/or blanks into pobuf, then write pobuf.
3218803Smckusick 
3228803Smckusick PARAMETERS:
3238803Smckusick 	current		integer		The current column
3248803Smckusick 	target		integer		The desired column
3258803Smckusick 
3268803Smckusick RETURNS:
3278803Smckusick 	Integer value of the new column.  (If current >= target,
3288803Smckusick 	no action is taken, and current is returned.
3298803Smckusick 
3308803Smckusick GLOBALS:
3318803Smckusick 	None
3328803Smckusick 
3338803Smckusick CALLS:
3348803Smckusick 	write (sys)
3358803Smckusick 
3368803Smckusick CALLED BY:
3378803Smckusick 	dump_line
3388803Smckusick 
3398803Smckusick HISTORY:
3408803Smckusick 	initial coding 	November 1976	D A Willcox of CAC
3418803Smckusick 
3428803Smckusick */
3438803Smckusick int     pad_output (current, target)/* writes tabs and blanks (if necessary) to
3448803Smckusick 			          get the current output position up to
3458803Smckusick 			          the target column */
3468803Smckusick int     current;	       /* the current column value */
3478803Smckusick int     target;		       /* position we want it at */
3488803Smckusick {
3498803Smckusick     register int    curr; /* internal column pointer */
3508803Smckusick     register char  *p; /* pointer into buffer of characters to be written */
3518803Smckusick     char    pobuf[256]; /* pad characters are stored here before writing */
3528803Smckusick     register int tcur;
3538803Smckusick 
3548803Smckusick     if (current >= target)
3558803Smckusick 	return (current);      /* line is already long enough */
3568803Smckusick 
3578803Smckusick     curr = current;
3588803Smckusick     p = pobuf;
3598803Smckusick     while (curr < target) {
3608803Smckusick 	if ((tcur = ((curr - 1) & tabmask) + tabsize + 1) <= target){
3618803Smckusick 	    *p++ = '\t';       /* put a tab into buffer */
3628803Smckusick 	    curr = tcur;
3638803Smckusick 	}
3648803Smckusick 	else {
3658803Smckusick 	    while (curr++ < target)
3668803Smckusick 		*p++ = ' ';    /* pad with final blanks */
3678803Smckusick 	}
3688803Smckusick     }
3698803Smckusick 
3708803Smckusick     write (output, pobuf, p - pobuf); /* write the characters we saved */
3718803Smckusick     return (target);
3728803Smckusick };
3738803Smckusick /*
3748803Smckusick 
3758803Smckusick 			  Copyright (C) 1976
3768803Smckusick 				by the
3778803Smckusick 			  Board of Trustees
3788803Smckusick 				of the
3798803Smckusick 			University of Illinois
3808803Smckusick 
3818803Smckusick 			 All rights reserved
3828803Smckusick 
3838803Smckusick 
3848803Smckusick NAME:
3858803Smckusick 	count_spaces
3868803Smckusick 
3878803Smckusick FUNCTION:
3888803Smckusick 	Find out where printing of a given string will leave the current
3898803Smckusick 	character position on output.
3908803Smckusick 
3918803Smckusick ALGORITHM:
3928803Smckusick 	Run thru input string and add appropriate values to current position.
3938803Smckusick 
3948803Smckusick PARAMETERS:
3958803Smckusick 	current		integer		  The current line character position
3968803Smckusick 	buffer		ptr to character  Pointer to input string
3978803Smckusick 
3988803Smckusick RETURNS:
3998803Smckusick 	Integer value of position after printing "buffer" starting in
4008803Smckusick 	column "current".
4018803Smckusick 
4028803Smckusick GLOBALS:
4038803Smckusick 	None
4048803Smckusick 
4058803Smckusick CALLS:
4068803Smckusick 	None
4078803Smckusick 
4088803Smckusick CALLED BY:
4098803Smckusick 	pr_comment
4108803Smckusick 
4118803Smckusick HISTORY:
4128803Smckusick 	initial coding 	November 1976	D A Willcox of CAC
4138803Smckusick 
4148803Smckusick */
4158803Smckusick int     count_spaces (current, buffer)
4168803Smckusick 			       /* this routine figures out where the
4178803Smckusick 			          character position will be after
4188803Smckusick 			          printing the text in buffer starting at
4198803Smckusick 			          column "current" */
4208803Smckusick int     current;
4218803Smckusick char   *buffer;
4228803Smckusick {
4238803Smckusick     register char  *buf; /* used to look thru buffer */
4248803Smckusick     register int    cur; /* current character counter */
4258803Smckusick 
4268803Smckusick     cur = current;
4278803Smckusick 
4288803Smckusick     for (buf = buffer; *buf != '\0'; ++buf) {
4298803Smckusick 	switch (*buf) {
4308803Smckusick 
4318803Smckusick 	    case '\n':
4328803Smckusick 	    case 014: 	       /* form feed */
4338803Smckusick 		cur = 1;
4348803Smckusick 		break;
4358803Smckusick 
4368803Smckusick 	    case '\t':
4378803Smckusick 		cur = ((cur - 1) & tabmask) + tabsize + 1;
4388803Smckusick 		break;
4398803Smckusick 
4408803Smckusick 	    case '': 	       /* this is a backspace */
4418803Smckusick 		--cur;
4428803Smckusick 		break;
4438803Smckusick 
4448803Smckusick 	    default:
4458803Smckusick 		++cur;
4468803Smckusick 		break;
4478803Smckusick 	}		       /* end of switch */
4488803Smckusick     }			       /* end of for loop */
4498803Smckusick 
4508803Smckusick     return (cur);
4518803Smckusick };
4528803Smckusick /*
4538803Smckusick 
4548803Smckusick 			  Copyright (C) 1976
4558803Smckusick 				by the
4568803Smckusick 			  Board of Trustees
4578803Smckusick 				of the
4588803Smckusick 			University of Illinois
4598803Smckusick 
4608803Smckusick 			 All rights reserved
4618803Smckusick 
4628803Smckusick 
4638803Smckusick NAME:
4648803Smckusick 	eqin
4658803Smckusick 
4668803Smckusick FUNCTION:
4678803Smckusick 	Returns true if the first arg matches the beginning of the second arg.
4688803Smckusick 
4698803Smckusick ALGORITHM:
4708803Smckusick 	Trivial
4718803Smckusick 
4728803Smckusick PARAMETERS:
4738803Smckusick 	str1	pointer to character
4748803Smckusick 	str2	pointer to character
4758803Smckusick 
4768803Smckusick RETURNS:
4778803Smckusick 	1 if first string matches start of second string
4788803Smckusick 	0 otherwise
4798803Smckusick 
4808803Smckusick GLOBALS:
4818803Smckusick 	None
4828803Smckusick 
4838803Smckusick CALLS:
4848803Smckusick 	None
4858803Smckusick 
4868803Smckusick CALLED BY:
4878803Smckusick 	lexi
4888803Smckusick 	main
4898803Smckusick 
4908803Smckusick HISTORY:
4918803Smckusick 	initial coding November 1976 by D A Willcox of CAC
4928803Smckusick 
4938803Smckusick */
4948803Smckusick eqin (str1, str2)
4958803Smckusick char   *str1;
4968803Smckusick char   *str2;
4978803Smckusick {
4988803Smckusick     register char  *s1; /* local pointer into first string */
4998803Smckusick     register char  *s2; /* local pointer into second string */
5008803Smckusick 
5018803Smckusick     s1 = str1;
5028803Smckusick     s2 = str2;
5038803Smckusick     while (*s1) {	       /* compare no further than end of first
5048803Smckusick 			          string */
5058803Smckusick 	if (*s2 == 0)	       /* check that second string isn't too short
5068803Smckusick 			       */
5078803Smckusick 	    return (false);
5088803Smckusick 	if (*s1++ != *s2++)
5098803Smckusick 	    return (false);
5108803Smckusick     }
5118803Smckusick 
5128803Smckusick     return (true);
5138803Smckusick }
5148803Smckusick /*
5158803Smckusick 			  Copyright (C) 1976
5168803Smckusick 				by the
5178803Smckusick 			  Board of Trustees
5188803Smckusick 				of the
5198803Smckusick 			University of Illinois
5208803Smckusick 
5218803Smckusick 			 All rights reserved
5228803Smckusick 
5238803Smckusick NAME:
5248803Smckusick 	cmp
5258803Smckusick 
5268803Smckusick FUNCTION:
5278803Smckusick 	Compares two strings
5288803Smckusick 
5298803Smckusick ALGORITHM:
5308803Smckusick 	Trivial
5318803Smckusick 
5328803Smckusick PARAMETERS:
5338803Smckusick 	a	Pointer to char		First string to compare
5348803Smckusick 	b	Pointer to char		Second string to compare
5358803Smckusick 
5368803Smckusick RETURNS:
5378803Smckusick 	-1 if a < b
5388803Smckusick 	 0 if a = b
5398803Smckusick 	 1 if a > b
5408803Smckusick 
5418803Smckusick GLOBALS:
5428803Smckusick 	None
5438803Smckusick 
5448803Smckusick CALLS:
5458803Smckusick 	None
5468803Smckusick 
5478803Smckusick CALLED BY:
5488803Smckusick 	main
5498803Smckusick 
5508803Smckusick HISTORY:
5518803Smckusick 	1/7/77		D A Willcox of CAC	Initial Coding
5528803Smckusick */
5538803Smckusick int     cmp (a, b)
5548803Smckusick char   *a;
5558803Smckusick char   *b;
5568803Smckusick {
5578803Smckusick     register char  *ta,
5588803Smckusick                    *tb;
5598803Smckusick 
5608803Smckusick     ta = a;
5618803Smckusick     tb = b;
5628803Smckusick 
5638803Smckusick     while (*ta) {
5648803Smckusick 	if (*ta > *tb)
5658803Smckusick 	    return (1);
5668803Smckusick 	if (*ta < *tb)
5678803Smckusick 	    return (-1);
5688803Smckusick 	++ta;
5698803Smckusick 	++tb;
5708803Smckusick     }
5718803Smckusick     if (*tb)
5728803Smckusick 	return (1);
5738803Smckusick     else
5748803Smckusick 	return (0);
5758803Smckusick }
576