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