1 /* 2 * Copyright (c) 1985 Sun Microsystems, Inc. 3 * Copyright (c) 1980 The Regents of the University of California. 4 * Copyright (c) 1976 Board of Trustees of the University of Illinois. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #ifndef lint 37 /*static char sccsid[] = "from: @(#)io.c 5.15 (Berkeley) 2/26/91";*/ 38 static char rcsid[] = "$Id: io.c,v 1.2 1993/08/01 18:14:32 mycroft Exp $"; 39 #endif /* not lint */ 40 41 #include <stdio.h> 42 #include <ctype.h> 43 #include <stdlib.h> 44 #include <string.h> 45 #include "indent_globs.h" 46 47 48 int comment_open; 49 static paren_target; 50 51 dump_line() 52 { /* dump_line is the routine that actually 53 * effects the printing of the new source. It 54 * prints the label section, followed by the 55 * code section with the appropriate nesting 56 * level, followed by any comments */ 57 register int cur_col, 58 target_col; 59 static not_first_line; 60 61 if (ps.procname[0]) { 62 if (troff) { 63 if (comment_open) { 64 comment_open = 0; 65 fprintf(output, ".*/\n"); 66 } 67 fprintf(output, ".Pr \"%s\"\n", ps.procname); 68 } 69 ps.ind_level = 0; 70 ps.procname[0] = 0; 71 } 72 if (s_code == e_code && s_lab == e_lab && s_com == e_com) { 73 if (suppress_blanklines > 0) 74 suppress_blanklines--; 75 else { 76 ps.bl_line = true; 77 n_real_blanklines++; 78 } 79 } 80 else if (!inhibit_formatting) { 81 suppress_blanklines = 0; 82 ps.bl_line = false; 83 if (prefix_blankline_requested && not_first_line) 84 if (swallow_optional_blanklines) { 85 if (n_real_blanklines == 1) 86 n_real_blanklines = 0; 87 } 88 else { 89 if (n_real_blanklines == 0) 90 n_real_blanklines = 1; 91 } 92 while (--n_real_blanklines >= 0) 93 putc('\n', output); 94 n_real_blanklines = 0; 95 if (ps.ind_level == 0) 96 ps.ind_stmt = 0; /* this is a class A kludge. dont do 97 * additional statement indentation if we are 98 * at bracket level 0 */ 99 100 if (e_lab != s_lab || e_code != s_code) 101 ++code_lines; /* keep count of lines with code */ 102 103 104 if (e_lab != s_lab) { /* print lab, if any */ 105 if (comment_open) { 106 comment_open = 0; 107 fprintf(output, ".*/\n"); 108 } 109 while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t')) 110 e_lab--; 111 cur_col = pad_output(1, compute_label_target()); 112 if (s_lab[0] == '#' && (strncmp(s_lab, "#else", 5) == 0 113 || strncmp(s_lab, "#endif", 6) == 0)) { 114 register char *s = s_lab; 115 if (e_lab[-1] == '\n') e_lab--; 116 do putc(*s++, output); 117 while (s < e_lab && 'a' <= *s && *s<='z'); 118 while ((*s == ' ' || *s == '\t') && s < e_lab) 119 s++; 120 if (s < e_lab) 121 fprintf(output, s[0]=='/' && s[1]=='*' ? "\t%.*s" : "\t/* %.*s */", 122 e_lab - s, s); 123 } 124 else fprintf(output, "%.*s", e_lab - s_lab, s_lab); 125 cur_col = count_spaces(cur_col, s_lab); 126 } 127 else 128 cur_col = 1; /* there is no label section */ 129 130 ps.pcase = false; 131 132 if (s_code != e_code) { /* print code section, if any */ 133 register char *p; 134 135 if (comment_open) { 136 comment_open = 0; 137 fprintf(output, ".*/\n"); 138 } 139 target_col = compute_code_target(); 140 { 141 register i; 142 143 for (i = 0; i < ps.p_l_follow; i++) 144 if (ps.paren_indents[i] >= 0) 145 ps.paren_indents[i] = -(ps.paren_indents[i] + target_col); 146 } 147 cur_col = pad_output(cur_col, target_col); 148 for (p = s_code; p < e_code; p++) 149 if (*p == (char) 0200) 150 fprintf(output, "%d", target_col * 7); 151 else 152 putc(*p, output); 153 cur_col = count_spaces(cur_col, s_code); 154 } 155 if (s_com != e_com) 156 if (troff) { 157 int all_here = 0; 158 register char *p; 159 160 if (e_com[-1] == '/' && e_com[-2] == '*') 161 e_com -= 2, all_here++; 162 while (e_com > s_com && e_com[-1] == ' ') 163 e_com--; 164 *e_com = 0; 165 p = s_com; 166 while (*p == ' ') 167 p++; 168 if (p[0] == '/' && p[1] == '*') 169 p += 2, all_here++; 170 else if (p[0] == '*') 171 p += p[1] == '/' ? 2 : 1; 172 while (*p == ' ') 173 p++; 174 if (*p == 0) 175 goto inhibit_newline; 176 if (comment_open < 2 && ps.box_com) { 177 comment_open = 0; 178 fprintf(output, ".*/\n"); 179 } 180 if (comment_open == 0) { 181 if ('a' <= *p && *p <= 'z') 182 *p = *p + 'A' - 'a'; 183 if (e_com - p < 50 && all_here == 2) { 184 register char *follow = p; 185 fprintf(output, "\n.nr C! \\w\1"); 186 while (follow < e_com) { 187 switch (*follow) { 188 case '\n': 189 putc(' ', output); 190 case 1: 191 break; 192 case '\\': 193 putc('\\', output); 194 default: 195 putc(*follow, output); 196 } 197 follow++; 198 } 199 putc(1, output); 200 } 201 fprintf(output, "\n./* %dp %d %dp\n", 202 ps.com_col * 7, 203 (s_code != e_code || s_lab != e_lab) - ps.box_com, 204 target_col * 7); 205 } 206 comment_open = 1 + ps.box_com; 207 while (*p) { 208 if (*p == BACKSLASH) 209 putc(BACKSLASH, output); 210 putc(*p++, output); 211 } 212 } 213 else { /* print comment, if any */ 214 register target = ps.com_col; 215 register char *com_st = s_com; 216 217 target += ps.comment_delta; 218 while (*com_st == '\t') 219 com_st++, target += 8; /* ? */ 220 while (target <= 0) 221 if (*com_st == ' ') 222 target++, com_st++; 223 else if (*com_st == '\t') 224 target = ((target - 1) & ~7) + 9, com_st++; 225 else 226 target = 1; 227 if (cur_col > target) { /* if comment cant fit on this line, 228 * put it on next line */ 229 putc('\n', output); 230 cur_col = 1; 231 ++ps.out_lines; 232 } 233 while (e_com > com_st && isspace(e_com[-1])) 234 e_com--; 235 cur_col = pad_output(cur_col, target); 236 if (!ps.box_com) { 237 if (star_comment_cont && (com_st[1] != '*' || e_com <= com_st + 1)) 238 if (com_st[1] == ' ' && com_st[0] == ' ' && e_com > com_st + 1) 239 com_st[1] = '*'; 240 else 241 fwrite(" * ", com_st[0] == '\t' ? 2 : com_st[0] == '*' ? 1 : 3, 1, output); 242 } 243 fwrite(com_st, e_com - com_st, 1, output); 244 ps.comment_delta = ps.n_comment_delta; 245 cur_col = count_spaces(cur_col, com_st); 246 ++ps.com_lines; /* count lines with comments */ 247 } 248 if (ps.use_ff) 249 putc('\014', output); 250 else 251 putc('\n', output); 252 inhibit_newline: 253 ++ps.out_lines; 254 if (ps.just_saw_decl == 1 && blanklines_after_declarations) { 255 prefix_blankline_requested = 1; 256 ps.just_saw_decl = 0; 257 } 258 else 259 prefix_blankline_requested = postfix_blankline_requested; 260 postfix_blankline_requested = 0; 261 } 262 ps.decl_on_line = ps.in_decl; /* if we are in the middle of a 263 * declaration, remember that fact for 264 * proper comment indentation */ 265 ps.ind_stmt = ps.in_stmt & ~ps.in_decl; /* next line should be 266 * indented if we have not 267 * completed this stmt and if 268 * we are not in the middle of 269 * a declaration */ 270 ps.use_ff = false; 271 ps.dumped_decl_indent = 0; 272 *(e_lab = s_lab) = '\0'; /* reset buffers */ 273 *(e_code = s_code) = '\0'; 274 *(e_com = s_com) = '\0'; 275 ps.ind_level = ps.i_l_follow; 276 ps.paren_level = ps.p_l_follow; 277 paren_target = -ps.paren_indents[ps.paren_level - 1]; 278 not_first_line = 1; 279 return; 280 } 281 282 compute_code_target() 283 { 284 register target_col = ps.ind_size * ps.ind_level + 1; 285 286 if (ps.paren_level) 287 if (!lineup_to_parens) 288 target_col += continuation_indent * ps.paren_level; 289 else { 290 register w; 291 register t = paren_target; 292 293 if ((w = count_spaces(t, s_code) - max_col) > 0 294 && count_spaces(target_col, s_code) <= max_col) { 295 t -= w + 1; 296 if (t > target_col) 297 target_col = t; 298 } 299 else 300 target_col = t; 301 } 302 else if (ps.ind_stmt) 303 target_col += continuation_indent; 304 return target_col; 305 } 306 307 compute_label_target() 308 { 309 return 310 ps.pcase ? (int) (case_ind * ps.ind_size) + 1 311 : *s_lab == '#' ? 1 312 : ps.ind_size * (ps.ind_level - label_offset) + 1; 313 } 314 315 316 /* 317 * Copyright (C) 1976 by the Board of Trustees of the University of Illinois 318 * 319 * All rights reserved 320 * 321 * 322 * NAME: fill_buffer 323 * 324 * FUNCTION: Reads one block of input into input_buffer 325 * 326 * HISTORY: initial coding November 1976 D A Willcox of CAC 1/7/77 A 327 * Willcox of CAC Added check for switch back to partly full input 328 * buffer from temporary buffer 329 * 330 */ 331 int 332 fill_buffer() 333 { /* this routine reads stuff from the input */ 334 register char *p; 335 register int i; 336 register FILE *f = input; 337 338 if (bp_save != 0) { /* there is a partly filled input buffer left */ 339 buf_ptr = bp_save; /* dont read anything, just switch buffers */ 340 buf_end = be_save; 341 bp_save = be_save = 0; 342 if (buf_ptr < buf_end) 343 return; /* only return if there is really something in 344 * this buffer */ 345 } 346 for (p = in_buffer;;) { 347 if (p >= in_buffer_limit) { 348 register size = (in_buffer_limit - in_buffer) * 2 + 10; 349 register offset = p - in_buffer; 350 in_buffer = (char *) realloc(in_buffer, size); 351 if (in_buffer == 0) 352 err("input line too long"); 353 p = in_buffer + offset; 354 in_buffer_limit = in_buffer + size - 2; 355 } 356 if ((i = getc(f)) == EOF) { 357 *p++ = ' '; 358 *p++ = '\n'; 359 had_eof = true; 360 break; 361 } 362 *p++ = i; 363 if (i == '\n') 364 break; 365 } 366 buf_ptr = in_buffer; 367 buf_end = p; 368 if (p[-2] == '/' && p[-3] == '*') { 369 if (in_buffer[3] == 'I' && strncmp(in_buffer, "/**INDENT**", 11) == 0) 370 fill_buffer(); /* flush indent error message */ 371 else { 372 int com = 0; 373 374 p = in_buffer; 375 while (*p == ' ' || *p == '\t') 376 p++; 377 if (*p == '/' && p[1] == '*') { 378 p += 2; 379 while (*p == ' ' || *p == '\t') 380 p++; 381 if (p[0] == 'I' && p[1] == 'N' && p[2] == 'D' && p[3] == 'E' 382 && p[4] == 'N' && p[5] == 'T') { 383 p += 6; 384 while (*p == ' ' || *p == '\t') 385 p++; 386 if (*p == '*') 387 com = 1; 388 else if (*p == 'O') 389 if (*++p == 'N') 390 p++, com = 1; 391 else if (*p == 'F' && *++p == 'F') 392 p++, com = 2; 393 while (*p == ' ' || *p == '\t') 394 p++; 395 if (p[0] == '*' && p[1] == '/' && p[2] == '\n' && com) { 396 if (s_com != e_com || s_lab != e_lab || s_code != e_code) 397 dump_line(); 398 if (!(inhibit_formatting = com - 1)) { 399 n_real_blanklines = 0; 400 postfix_blankline_requested = 0; 401 prefix_blankline_requested = 0; 402 suppress_blanklines = 1; 403 } 404 } 405 } 406 } 407 } 408 } 409 if (inhibit_formatting) { 410 p = in_buffer; 411 do 412 putc(*p, output); 413 while (*p++ != '\n'); 414 } 415 return; 416 } 417 418 /* 419 * Copyright (C) 1976 by the Board of Trustees of the University of Illinois 420 * 421 * All rights reserved 422 * 423 * 424 * NAME: pad_output 425 * 426 * FUNCTION: Writes tabs and spaces to move the current column up to the desired 427 * position. 428 * 429 * ALGORITHM: Put tabs and/or blanks into pobuf, then write pobuf. 430 * 431 * PARAMETERS: current integer The current column target 432 * nteger The desired column 433 * 434 * RETURNS: Integer value of the new column. (If current >= target, no action is 435 * taken, and current is returned. 436 * 437 * GLOBALS: None 438 * 439 * CALLS: write (sys) 440 * 441 * CALLED BY: dump_line 442 * 443 * HISTORY: initial coding November 1976 D A Willcox of CAC 444 * 445 */ 446 pad_output(current, target) /* writes tabs and blanks (if necessary) to 447 * get the current output position up to the 448 * target column */ 449 int current; /* the current column value */ 450 int target; /* position we want it at */ 451 { 452 register int curr; /* internal column pointer */ 453 register int tcur; 454 455 if (troff) 456 fprintf(output, "\\h'|%dp'", (target - 1) * 7); 457 else { 458 if (current >= target) 459 return (current); /* line is already long enough */ 460 curr = current; 461 while ((tcur = ((curr - 1) & tabmask) + tabsize + 1) <= target) { 462 putc('\t', output); 463 curr = tcur; 464 } 465 while (curr++ < target) 466 putc(' ', output); /* pad with final blanks */ 467 } 468 return (target); 469 } 470 471 /* 472 * Copyright (C) 1976 by the Board of Trustees of the University of Illinois 473 * 474 * All rights reserved 475 * 476 * 477 * NAME: count_spaces 478 * 479 * FUNCTION: Find out where printing of a given string will leave the current 480 * character position on output. 481 * 482 * ALGORITHM: Run thru input string and add appropriate values to current 483 * position. 484 * 485 * RETURNS: Integer value of position after printing "buffer" starting in column 486 * "current". 487 * 488 * HISTORY: initial coding November 1976 D A Willcox of CAC 489 * 490 */ 491 int 492 count_spaces(current, buffer) 493 /* 494 * this routine figures out where the character position will be after 495 * printing the text in buffer starting at column "current" 496 */ 497 int current; 498 char *buffer; 499 { 500 register char *buf; /* used to look thru buffer */ 501 register int cur; /* current character counter */ 502 503 cur = current; 504 505 for (buf = buffer; *buf != '\0'; ++buf) { 506 switch (*buf) { 507 508 case '\n': 509 case 014: /* form feed */ 510 cur = 1; 511 break; 512 513 case '\t': 514 cur = ((cur - 1) & tabmask) + tabsize + 1; 515 break; 516 517 case 010: /* backspace */ 518 --cur; 519 break; 520 521 default: 522 ++cur; 523 break; 524 } /* end of switch */ 525 } /* end of for loop */ 526 return (cur); 527 } 528 529 int found_err; 530 /* VARARGS2 */ 531 diag(level, msg, a, b) 532 char *msg; 533 { 534 if (level) 535 found_err = 1; 536 if (output == stdout) { 537 fprintf(stdout, "/**INDENT** %s@%d: ", level == 0 ? "Warning" : "Error", line_no); 538 fprintf(stdout, msg, a, b); 539 fprintf(stdout, " */\n"); 540 } 541 else { 542 fprintf(stderr, "%s@%d: ", level == 0 ? "Warning" : "Error", line_no); 543 fprintf(stderr, msg, a, b); 544 fprintf(stderr, "\n"); 545 } 546 } 547 548 writefdef(f, nm) 549 register struct fstate *f; 550 { 551 fprintf(output, ".ds f%c %s\n.nr s%c %d\n", 552 nm, f->font, nm, f->size); 553 } 554 555 char * 556 chfont(of, nf, s) 557 register struct fstate *of, 558 *nf; 559 char *s; 560 { 561 if (of->font[0] != nf->font[0] 562 || of->font[1] != nf->font[1]) { 563 *s++ = '\\'; 564 *s++ = 'f'; 565 if (nf->font[1]) { 566 *s++ = '('; 567 *s++ = nf->font[0]; 568 *s++ = nf->font[1]; 569 } 570 else 571 *s++ = nf->font[0]; 572 } 573 if (nf->size != of->size) { 574 *s++ = '\\'; 575 *s++ = 's'; 576 if (nf->size < of->size) { 577 *s++ = '-'; 578 *s++ = '0' + of->size - nf->size; 579 } 580 else { 581 *s++ = '+'; 582 *s++ = '0' + nf->size - of->size; 583 } 584 } 585 return s; 586 } 587 588 589 parsefont(f, s0) 590 register struct fstate *f; 591 char *s0; 592 { 593 register char *s = s0; 594 int sizedelta = 0; 595 bzero(f, sizeof *f); 596 while (*s) { 597 if (isdigit(*s)) 598 f->size = f->size * 10 + *s - '0'; 599 else if (isupper(*s)) 600 if (f->font[0]) 601 f->font[1] = *s; 602 else 603 f->font[0] = *s; 604 else if (*s == 'c') 605 f->allcaps = 1; 606 else if (*s == '+') 607 sizedelta++; 608 else if (*s == '-') 609 sizedelta--; 610 else { 611 fprintf(stderr, "indent: bad font specification: %s\n", s0); 612 exit(1); 613 } 614 s++; 615 } 616 if (f->font[0] == 0) 617 f->font[0] = 'R'; 618 if (bodyf.size == 0) 619 bodyf.size = 11; 620 if (f->size == 0) 621 f->size = bodyf.size + sizedelta; 622 else if (sizedelta > 0) 623 f->size += bodyf.size; 624 else 625 f->size = bodyf.size - f->size; 626 } 627