xref: /original-bsd/usr.bin/indent/io.c (revision f0fd5f8a)
1 static char sccsid[] = "@(#)io.c	4.1	(Berkeley)	10/21/82";
2 
3 /*
4 
5 			  Copyright (C) 1976
6 				by the
7 			  Board of Trustees
8 				of the
9 			University of Illinois
10 
11 			 All rights reserved
12 
13 
14 FILE NAME:
15 	io.c
16 
17 PURPOSE:
18 	Contains routines to handle i/o related stuff for indent.
19 
20 GLOBALS:
21 	None
22 
23 FUNCTIONS:
24 	dump_line
25 	fill_buffer
26 	pad_output
27 	count_spaces
28 	eqin
29 	cmp
30 
31 */
32 /*
33 
34 			  Copyright (C) 1976
35 				by the
36 			  Board of Trustees
37 				of the
38 			University of Illinois
39 
40 			 All rights reserved
41 
42 
43 NAME:
44 	dump_line
45 
46 FUNCTION:
47 	Does the actual printing of the stored up line
48 
49 ALGORITHM:
50 	For each of the label, code, and comment sections which are used on
51 	this line:
52 
53 	1) Use pad_output to get the section aligned properly.
54 	2) write the section
55 
56 	The indentation level used for the code is set by ind_level.  After
57 	printing, ind_level is set to i_l_follow.
58 
59 	An extra level of indentation is added if ind_stmt is 1.  After
60 	printing, ind_stmt is set to 1 iff the line just printed has an
61 	unterminated, non-declaration statement.
62 
63 PARAMETERS:
64 	None
65 
66 RETURNS:
67 	Nothing
68 
69 GLOBALS:
70 	labbuf
71 	s_lab
72 	e_lab =		Reset to s_lab
73 
74 	codebuf
75 	s_code
76 	e_code =	Reset to s_code
77 
78 	combuf
79 	s_com
80 	e_com =		Reset to s_com
81 
82 	bl_line =	Set to true iff the line was blank
83 	case_ind
84 	code_lines =	Count lines with code
85 	com_col
86 	com_lines =	Keep track of lines with comments
87 	decl_on_line =	Set to in_decl after line is printed
88 	i_l_follow
89 	in_decl
90 	in_stmt
91 	ind_level =	Set to i_l_follow at completion
92 	ind_size
93 	ind_stmt =	Set to in_stmt at completion if not in declaration
94 	out_lines =	Count output lines
95 	p_l_follow
96 	paren_level =	Set to p_l_follow at completion
97 	pcase
98 	use_ff =	Reset to false
99 
100 CALLS:
101 	pad_output
102 	printf (lib)
103 	write (lib)
104 
105 CALLED BY:
106 	main
107 	pr_comment
108 
109 HISTORY:
110 	initial coding 	November 1976	D A Willcox of CAC
111 
112 */
113 #include "indent_globs.h";
114 
115 
116 
117 int     ff = 014;	       /* used to write a form feed */
118 
119 
120 dump_line () {		       /* dump_line is the routine that actually
121 			          effects the printing of the new source.
122 			          It prints the label section, followed by
123 			          the code section with the appropriate
124 			          nesting level, followed by any comments
125 			       */
126     register int    cur_col,
127                     temp_col,
128                     target_col;
129 
130     bl_line = true;	       /* if we don't find otherwise, assume a
131 			          blank line */
132 
133     if (ind_level == 0)
134 	ind_stmt = 0;	       /* this is a class A kludge. don't do
135 			          additional statement indentation if we
136 			          are at bracket level 0 */
137 
138     if (e_lab != s_lab || e_code != s_code)
139 	++code_lines;	       /* keep count of lines with code */
140 
141     if (e_lab != s_lab) {      /* print lab, if any */
142 	if (pcase)	       /* if the label is really a case, we must
143 			          indent */
144 	    cur_col = pad_output (1, case_ind * ind_size + 1);
145 	else {
146 	    if (*s_lab == '#') /* check for #define, etc */
147 		cur_col = 1;
148 	    else
149 		cur_col = pad_output (1, ind_size * (ind_level - label_offset) + 1);
150 	}
151 
152 	write (output, s_lab, e_lab - s_lab);
153 	cur_col = count_spaces (cur_col, s_lab);
154     /* count_spaces gives number of characters, considering tabs */
155 	bl_line = false;       /* line not blank after all */
156     }
157     else
158 	cur_col = 1;	       /* there is no label section */
159 
160     pcase = false;
161 
162     if (s_code != e_code) {    /* print code section, if any */
163 	target_col = ind_size * (ind_level + paren_level + ind_stmt) + 1;
164 
165 	cur_col = pad_output (cur_col, target_col);
166     /* pad_output writes enough tabs and spaces to get the current char
167        position up to target_col */
168 	write (output, s_code, e_code - s_code);
169 	cur_col = count_spaces (cur_col, s_code);
170 	bl_line = false;       /* line not blank */
171     }
172 
173     if ((cur_col - 1) > max_col && output!=1)/* check for line too long */
174 	printf ("%d: Code has %d chars, max is %d\n", line_no, (cur_col - 1), max_col);
175 
176     if (s_com != e_com) {      /* print comment, if any */
177 	if (cur_col > com_col && count_spaces (cur_col, s_com) >= max_col) {
178 	/* if comment can't fit on this line, put it on next line */
179 	    write (output, "\n", 1);
180 	    cur_col = 1;
181 	    ++out_lines;
182 	}
183 	cur_col = pad_output (cur_col, com_col);
184 	write (output, s_com, e_com - s_com);
185 
186 	cur_col = count_spaces (cur_col, s_com);
187 	if ((cur_col - 1) > max_col && output!=1)/* check for too long comment */
188 	    printf ("%d: Comment goes to column %d.  Max is %d\n",
189 		line_no, (cur_col - 1), max_col);
190 
191 	bl_line = false;
192 	++com_lines;	       /* count lines with comments */
193     }
194 
195     if (use_ff)
196 	write (output, &ff, 1);/* end the output with a ff */
197     else
198 	write (output, "\n", 1); /* or a newline */
199     use_ff = false;
200     *(e_lab = s_lab) = '\0';   /* reset buffers */
201     *(e_code = s_code) = '\0';
202     *(e_com = s_com) = '\0';
203 
204     ind_level = i_l_follow;
205     paren_level = p_l_follow;
206     ++out_lines;
207     decl_on_line = in_decl;    /* if we are in the middle of a
208 			          declaration, remember that fact for
209 			          proper comment indentation */
210     ind_stmt = in_stmt & ~in_decl;
211  /* next line should be indented if we have not completed this stmt and if
212     we are not in the middle of a declaration */
213 
214     return;
215 };
216 /*
217 
218 			  Copyright (C) 1976
219 				by the
220 			  Board of Trustees
221 				of the
222 			University of Illinois
223 
224 			 All rights reserved
225 
226 
227 NAME:
228 	fill_buffer
229 
230 FUNCTION:
231 	Reads one block of input into input_buffer
232 
233 ALGORITHM:
234 	Trivial
235 
236 PARAMETERS:
237 	None
238 
239 RETURNS:
240 	Nothing
241 
242 GLOBALS:
243 	in_buffer =
244 	buf_end =	Set to 1 past last character read in
245 	buf_ptr =	Set to start of buffer
246 	be_save =	Set to zero if it was non-zero
247 	bp_save =	Set to zero
248 
249 CALLS:
250 	read (lib)
251 
252 CALLED BY:
253 	lexi
254 	main
255 	pr_comment
256 
257 HISTORY:
258 	initial coding 	November 1976	D A Willcox of CAC
259 	1/7/77		D A Willcox of CAC	Added check for switch back to
260 						partly full input buffer from
261 						temporary buffer
262 
263 */
264 int     fill_buffer () { /* this routine reads stuff from the input */
265     int     count;
266     register int    i;
267 
268     if (bp_save != 0) {	       /* there is a partly filled input buffer
269 			          left */
270 	buf_ptr = bp_save;     /* don't read anything, just switch buffers
271 			       */
272 	buf_end = be_save;
273 	bp_save = be_save = 0;
274 	if (buf_ptr < buf_end)
275 	    return;	       /* only return if there is really something
276 			          in this buffer */
277     }
278 
279     count = read (input, in_buffer, inp_bufs);
280 
281     buf_end = in_buffer + count;
282     buf_ptr = in_buffer;
283 
284     if (count == 0) {	       /* count of zero means eof */
285 	had_eof = true;
286 	*buf_end++ = ' ';
287 	*buf_end++ = '\n';     /* insert extra newline.  it will
288 			          eventually get indent to stop */
289     }
290 
291     return;
292 };
293 /*
294 
295 			  Copyright (C) 1976
296 				by the
297 			  Board of Trustees
298 				of the
299 			University of Illinois
300 
301 			 All rights reserved
302 
303 
304 NAME:
305 	pad_output
306 
307 FUNCTION:
308 	Writes tabs and spaces to move the current column up to the
309 	desired position.
310 
311 ALGORITHM:
312 	Put tabs and/or blanks into pobuf, then write pobuf.
313 
314 PARAMETERS:
315 	current		integer		The current column
316 	target		integer		The desired column
317 
318 RETURNS:
319 	Integer value of the new column.  (If current >= target,
320 	no action is taken, and current is returned.
321 
322 GLOBALS:
323 	None
324 
325 CALLS:
326 	write (sys)
327 
328 CALLED BY:
329 	dump_line
330 
331 HISTORY:
332 	initial coding 	November 1976	D A Willcox of CAC
333 
334 */
335 int     pad_output (current, target)/* writes tabs and blanks (if necessary) to
336 			          get the current output position up to
337 			          the target column */
338 int     current;	       /* the current column value */
339 int     target;		       /* position we want it at */
340 {
341     register int    curr; /* internal column pointer */
342     register char  *p; /* pointer into buffer of characters to be written */
343     char    pobuf[256]; /* pad characters are stored here before writing */
344     register int tcur;
345 
346     if (current >= target)
347 	return (current);      /* line is already long enough */
348 
349     curr = current;
350     p = pobuf;
351     while (curr < target) {
352 	if ((tcur = ((curr - 1) & tabmask) + tabsize + 1) <= target){
353 	    *p++ = '\t';       /* put a tab into buffer */
354 	    curr = tcur;
355 	}
356 	else {
357 	    while (curr++ < target)
358 		*p++ = ' ';    /* pad with final blanks */
359 	}
360     }
361 
362     write (output, pobuf, p - pobuf); /* write the characters we saved */
363     return (target);
364 };
365 /*
366 
367 			  Copyright (C) 1976
368 				by the
369 			  Board of Trustees
370 				of the
371 			University of Illinois
372 
373 			 All rights reserved
374 
375 
376 NAME:
377 	count_spaces
378 
379 FUNCTION:
380 	Find out where printing of a given string will leave the current
381 	character position on output.
382 
383 ALGORITHM:
384 	Run thru input string and add appropriate values to current position.
385 
386 PARAMETERS:
387 	current		integer		  The current line character position
388 	buffer		ptr to character  Pointer to input string
389 
390 RETURNS:
391 	Integer value of position after printing "buffer" starting in
392 	column "current".
393 
394 GLOBALS:
395 	None
396 
397 CALLS:
398 	None
399 
400 CALLED BY:
401 	pr_comment
402 
403 HISTORY:
404 	initial coding 	November 1976	D A Willcox of CAC
405 
406 */
407 int     count_spaces (current, buffer)
408 			       /* this routine figures out where the
409 			          character position will be after
410 			          printing the text in buffer starting at
411 			          column "current" */
412 int     current;
413 char   *buffer;
414 {
415     register char  *buf; /* used to look thru buffer */
416     register int    cur; /* current character counter */
417 
418     cur = current;
419 
420     for (buf = buffer; *buf != '\0'; ++buf) {
421 	switch (*buf) {
422 
423 	    case '\n':
424 	    case 014: 	       /* form feed */
425 		cur = 1;
426 		break;
427 
428 	    case '\t':
429 		cur = ((cur - 1) & tabmask) + tabsize + 1;
430 		break;
431 
432 	    case '': 	       /* this is a backspace */
433 		--cur;
434 		break;
435 
436 	    default:
437 		++cur;
438 		break;
439 	}		       /* end of switch */
440     }			       /* end of for loop */
441 
442     return (cur);
443 };
444 /*
445 
446 			  Copyright (C) 1976
447 				by the
448 			  Board of Trustees
449 				of the
450 			University of Illinois
451 
452 			 All rights reserved
453 
454 
455 NAME:
456 	eqin
457 
458 FUNCTION:
459 	Returns true if the first arg matches the beginning of the second arg.
460 
461 ALGORITHM:
462 	Trivial
463 
464 PARAMETERS:
465 	str1	pointer to character
466 	str2	pointer to character
467 
468 RETURNS:
469 	1 if first string matches start of second string
470 	0 otherwise
471 
472 GLOBALS:
473 	None
474 
475 CALLS:
476 	None
477 
478 CALLED BY:
479 	lexi
480 	main
481 
482 HISTORY:
483 	initial coding November 1976 by D A Willcox of CAC
484 
485 */
486 eqin (str1, str2)
487 char   *str1;
488 char   *str2;
489 {
490     register char  *s1; /* local pointer into first string */
491     register char  *s2; /* local pointer into second string */
492 
493     s1 = str1;
494     s2 = str2;
495     while (*s1) {	       /* compare no further than end of first
496 			          string */
497 	if (*s2 == 0)	       /* check that second string isn't too short
498 			       */
499 	    return (false);
500 	if (*s1++ != *s2++)
501 	    return (false);
502     }
503 
504     return (true);
505 }
506 /*
507 			  Copyright (C) 1976
508 				by the
509 			  Board of Trustees
510 				of the
511 			University of Illinois
512 
513 			 All rights reserved
514 
515 NAME:
516 	cmp
517 
518 FUNCTION:
519 	Compares two strings
520 
521 ALGORITHM:
522 	Trivial
523 
524 PARAMETERS:
525 	a	Pointer to char		First string to compare
526 	b	Pointer to char		Second string to compare
527 
528 RETURNS:
529 	-1 if a < b
530 	 0 if a = b
531 	 1 if a > b
532 
533 GLOBALS:
534 	None
535 
536 CALLS:
537 	None
538 
539 CALLED BY:
540 	main
541 
542 HISTORY:
543 	1/7/77		D A Willcox of CAC	Initial Coding
544 */
545 int     cmp (a, b)
546 char   *a;
547 char   *b;
548 {
549     register char  *ta,
550                    *tb;
551 
552     ta = a;
553     tb = b;
554 
555     while (*ta) {
556 	if (*ta > *tb)
557 	    return (1);
558 	if (*ta < *tb)
559 	    return (-1);
560 	++ta;
561 	++tb;
562     }
563     if (*tb)
564 	return (1);
565     else
566 	return (0);
567 }
568