home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / INDENTP.ZIP / INDENT2 < prev    next >
Text File  |  1992-04-10  |  61KB  |  2,265 lines

  1. #    This is a shell archive.
  2. #    Remove everything above and including the cut line.
  3. #    Then run the rest of the file through sh.
  4. #----cut here-----cut here-----cut here-----cut here----#
  5. #!/bin/sh
  6. # shar:    Shell Archiver
  7. #    Run the following text with /bin/sh to create:
  8. #    indent.c
  9. #    io.c
  10. # This archive created: Fri Apr 10 20:51:12 1992
  11. echo shar: extracting indent.c
  12. sed 's/^X//' << \SHAR_EOF > indent.c
  13. X/*
  14. X * Copyright 1989 Object Design, Inc.
  15. X * Copyright (c) 1985 Sun Microsystems, Inc.
  16. X * Copyright (c) 1980 The Regents of the University of California.
  17. X * Copyright (c) 1976 Board of Trustees of the University of Illinois.
  18. X * All rights reserved.
  19. X *
  20. X * Redistribution and use in source and binary forms are permitted
  21. X * provided that the above copyright notice and this paragraph are
  22. X * duplicated in all such forms and that any documentation,
  23. X * advertising materials, and other materials related to such
  24. X * distribution and use acknowledge that the software was developed
  25. X * by the University of California, Berkeley, the University of Illinois,
  26. X * Urbana, and Sun Microsystems, Inc.  The name of either University
  27. X * or Sun Microsystems may not be used to endorse or promote products
  28. X * derived from this software without specific prior written permission.
  29. X * THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
  30. X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  31. X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  32. X */
  33. X
  34. X#ifndef lint
  35. Xchar copyright[] =
  36. X"@(#) Copyright 1989 Object Design, Inc.\n\
  37. X @(#) Copyright (c) 1985 Sun Microsystems, Inc.\n\
  38. X @(#) Copyright (c) 1980 The Regents of the University of California.\n\
  39. X @(#) Copyright (c) 1976 Board of Trustees of the University of Illinois.\n\
  40. X All rights reserved.\n";
  41. X
  42. X#endif                            /* not lint */
  43. X
  44. X#ifndef lint
  45. Xstatic char sccsid[] = "@(#)indent.c    5.11 (Berkeley) 88/09/15";
  46. X
  47. X#endif                            /* not lint */
  48. X
  49. X#include "globals.h"
  50. X#include "codes.h"
  51. X
  52. X#ifdef MSDOS                    /* or OS/2 */
  53. X#include <malloc.h>
  54. X#include <stdlib.h>
  55. X#include <process.h>
  56. X#include <string.h>
  57. X#include <io.h>
  58. X#define R_OK 4
  59. X#define INCL_NOPM
  60. X#define INCL_BASE
  61. X#define INCL_DOSFILEMGR
  62. X#include <os2.h>
  63. X#else                            /* not MSDOS or OS/2 */
  64. X#include <sys/param.h>
  65. X#include <unistd.h>
  66. X#endif                            /* BSD */
  67. X
  68. X#include <ctype.h>
  69. X
  70. Xchar *in_name = "Standard Input";    /* will always point to name of input file */
  71. Xchar *out_name = "Standard Output";    /* will always point to name of output file */
  72. Xchar bakfile[MAXPATHLEN] = "";
  73. X
  74. X#ifdef ANSIC
  75. Xstatic void bakcopy(void);
  76. X
  77. X#endif
  78. X
  79. X#ifdef ANSIC
  80. Xvoid main(int argc, char **argv)
  81. X#else
  82. Xmain(argc, argv)
  83. X    int argc;
  84. X    char **argv;
  85. X
  86. X#endif
  87. X{
  88. X
  89. X    extern int found_err;        /* flag set in diag() on error */
  90. X    int dec_ind;                /* current indentation for declarations */
  91. X    int di_stack[20];            /* a stack of structure indentation levels */
  92. X    int flushed_nl;                /* used when buffering up comments to remember
  93. X                                   that a newline was passed over */
  94. X    int force_nl;                /* when true, code must be broken */
  95. X    int hd_type;                /* used to store type of stmt for if (...), for
  96. X                                   (...), etc */
  97. X    register int i;                /* local loop counter */
  98. X    int scase;                    /* set to true when we see a case, so we will
  99. X                                   know what to do with the following colon */
  100. X    int sp_sw;                    /* when true, we are in the expressin of
  101. X                                   if(...), while(...), etc. */
  102. X    int squest;                    /* when this is positive, we have seen a ?
  103. X                                   without the matching : in a <c>?<s>:<s>
  104. X                                   construct */
  105. X    register char *t_ptr;        /* used for copying tokens */
  106. X    int type_code;                /* the type of token, returned by lexi */
  107. X
  108. X    int last_else = 0;            /* true iff last keyword was an else */
  109. X    int ch;                        /* answer to Y/N prompt */
  110. X
  111. X    /*-----------------------------------------------*\
  112. X    |              INITIALIZATION                      |
  113. X    \*-----------------------------------------------*/
  114. X
  115. X
  116. X    ps.p_stack[0] = stmt;        /* this is the parser's stack */
  117. X    ps.last_nl = true;            /* this is true if the last thing scanned was a
  118. X                                   newline */
  119. X    ps.last_token = semicolon;
  120. X    combuf = (char *) malloc(bufsize);
  121. X    labbuf = (char *) malloc(bufsize);
  122. X    codebuf = (char *) malloc(bufsize);
  123. X    l_com = combuf + bufsize - 5;
  124. X    l_lab = labbuf + bufsize - 5;
  125. X    l_code = codebuf + bufsize - 5;
  126. X    combuf[0] = codebuf[0] = labbuf[0] = ' ';    /* set up code, label, and
  127. X                                                   comment buffers */
  128. X    combuf[1] = codebuf[1] = labbuf[1] = '\0';
  129. X    ps.else_if = 1;                /* Default else-if special processing to on */
  130. X    s_lab = e_lab = labbuf + 1;
  131. X    s_code = e_code = codebuf + 1;
  132. X    s_com = e_com = combuf + 1;
  133. X
  134. X    buf_ptr = buf_end = in_buffer;
  135. X    line_no = 1;
  136. X    had_eof = ps.in_decl = ps.decl_on_line = break_comma = false;
  137. X    sp_sw = force_nl = false;
  138. X    ps.in_or_st = false;
  139. X    ps.bl_line = true;
  140. X    dec_ind = 0;
  141. X    di_stack[ps.dec_nest = 0] = 0;
  142. X    ps.want_blank = ps.in_stmt = ps.ind_stmt = false;
  143. X    ps.cc_comment = 0;
  144. X
  145. X
  146. X    scase = ps.pcase = false;
  147. X    squest = 0;
  148. X    sc_end = 0;
  149. X    bp_save = 0;
  150. X    be_save = 0;
  151. X
  152. X    output = NULL;
  153. X
  154. X
  155. X
  156. X    /*--------------------------------------------------*\
  157. X    |           COMMAND LINE SCAN                        |
  158. X    \*--------------------------------------------------*/
  159. X
  160. X#ifdef undef
  161. X    max_col = 78;                /* -l78 */
  162. X    lineup_to_parens = 1;        /* -lp */
  163. X    ps.ljust_decl = 0;            /* -ndj */
  164. X    ps.com_ind = 33;            /* -c33 */
  165. X    star_comment_cont = 1;        /* -sc */
  166. X    ps.ind_size = 8;            /* -i8 */
  167. X    verbose = 0;
  168. X    ps.decl_indent = 16;        /* -di16 */
  169. X    ps.indent_parameters = 1;    /* -ip */
  170. X    ps.decl_com_ind = 0;        /* if this is not set to some positive value by
  171. X                                   an arg, we will set this equal to ps.com_ind */
  172. X    btype_2 = 1;                /* -br */
  173. X    btype_3 = 0;                /* not -brr */
  174. X    cuddle_else = 1;            /* -ce */
  175. X    ps.unindent_displace = 0;    /* -d0 */
  176. X    ps.case_indent = 0;            /* -cli0 */
  177. X    ps.case_code_indent = 1;    /* -cci1 */
  178. X    format_col1_comments = 1;    /* -fc1 */
  179. X    procnames_start_line = 1;    /* -psl */
  180. X    proc_calls_space = 0;        /* -npcs */
  181. X    parens_space = 0;            /* -nprs */
  182. X    comment_delimiter_on_blankline = 1;    /* -cdb */
  183. X    ps.leave_comma = 1;            /* -nbc */
  184. X#endif
  185. X
  186. X    for (i = 1; i < argc; ++i)
  187. X        if (strcmp(argv[i], "-npro") == 0)
  188. X            break;
  189. X    set_defaults();
  190. X    if (i >= argc)
  191. X        set_profile();
  192. X
  193. X    for (i = 1; i < argc; ++i)
  194. X    {
  195. X
  196. X        /*
  197. X           look thru args (if any) for changes to defaults
  198. X        */
  199. X        if (argv[i][0] != '-')
  200. X        {                        /* no flag on parameter */
  201. X            if (input == NULL)
  202. X            {                    /* we must have the input file */
  203. X                in_name = argv[i];    /* remember name of input file */
  204. X                input = fopen(in_name, "r");
  205. X                if (input == NULL)
  206. X                {                /* check for open error */
  207. X                    fprintf(stderr, "indent: can't open %s\n", argv[i]);
  208. X                    exit(1);
  209. X                }
  210. X                continue;
  211. X            }
  212. X            else if (output == NULL)
  213. X            {                    /* we have the output file */
  214. X                out_name = argv[i];    /* remember name of output file */
  215. X                if (strcmp(in_name, out_name) == 0)
  216. X                {                /* attempt to overwrite the file */
  217. X                    fprintf(stderr, "indent: input and output files must be different\n");
  218. X                    exit(1);
  219. X                }
  220. X                if (access(out_name, R_OK) == 0)
  221. X                {
  222. X                    fprintf(stderr, "Reformatting input file %s to produce output file %s\n",
  223. X                                in_name, out_name);
  224. X                    fprintf(stderr, "Output file %s exists; overwrite it? ", out_name);
  225. X                    fflush(stderr);
  226. X                    if ((ch = getchar()) != 'y' && ch != 'Y')
  227. X                    {
  228. X                        fprintf (stderr, "indent: can't create %s\n", argv[i]);
  229. X                        exit(1);
  230. X                    }
  231. X                }
  232. X                output = fopen(out_name, "w");
  233. X                if (output == NULL)
  234. X                {                /* check for create error */
  235. X                    fprintf(stderr, "indent: can't create %s\n", argv[i]);
  236. X                    exit(1);
  237. X                }
  238. X                continue;
  239. X            }
  240. X            fprintf(stderr, "indent: unknown parameter: %s\n", argv[i]);
  241. X            exit(1);
  242. X        }
  243. X        else
  244. X            set_option(argv[i]);
  245. X    }                            /* end of for */
  246. X    if (input == NULL)
  247. X    {
  248. X        fprintf(stderr, "indent: usage: indent file [ outfile ] [ options ]\n");
  249. X        exit(1);
  250. X    }
  251. X    /* set -+ mode by default for .C */
  252. X    if (!cplus)                    /* don't bother if explicit */
  253. X    {
  254. X        char *dot;
  255. X
  256. X        dot = in_name + strlen(in_name) - 2;
  257. X        if ((dot > in_name) && (strcmp(dot, ".C") == 0))
  258. X            set_option("-+");
  259. X    }
  260. X
  261. X    if (output == NULL)
  262. X        if (troff)
  263. X            output = stdout;
  264. X        else
  265. X        {
  266. X            out_name = in_name;
  267. X            bakcopy();
  268. X        }
  269. X    if (ps.com_ind <= 1)
  270. X        ps.com_ind = 2;            /* don't put normal comments before column 2 */
  271. X    if (troff)
  272. X    {
  273. X        if (bodyf.font[0] == 0)
  274. X            parsefont(&bodyf, "R");
  275. X        if (scomf.font[0] == 0)
  276. X            parsefont(&scomf, "I");
  277. X        if (blkcomf.font[0] == 0)
  278. X            blkcomf = scomf, blkcomf.size += 2;
  279. X        if (boxcomf.font[0] == 0)
  280. X            boxcomf = blkcomf;
  281. X        if (stringf.font[0] == 0)
  282. X            parsefont(&stringf, "L");
  283. X        if (keywordf.font[0] == 0)
  284. X            parsefont(&keywordf, "B");
  285. X        writefdef(&bodyf, 'B');
  286. X        writefdef(&scomf, 'C');
  287. X        writefdef(&blkcomf, 'L');
  288. X        writefdef(&boxcomf, 'X');
  289. X        writefdef(&stringf, 'S');
  290. X        writefdef(&keywordf, 'K');
  291. X    }
  292. X    if (block_comment_max_col <= 0)
  293. X        block_comment_max_col = max_col;
  294. X    if (ps.decl_com_ind <= 0)    /* if not specified by user, set this */
  295. X        ps.decl_com_ind = ps.ljust_decl ? (ps.com_ind <= 10 ? 2 : ps.com_ind - 8) : ps.com_ind;
  296. X    if (continuation_indent == 0)
  297. X        continuation_indent = ps.ind_size;
  298. X    fill_buffer();                /* get first batch of stuff into input buffer */
  299. X
  300. X    parse(semicolon);
  301. X    {
  302. X        register char *p = buf_ptr;
  303. X        register col = 1;
  304. X
  305. X        while (1)
  306. X        {
  307. X            if (*p == ' ')
  308. X                col++;
  309. X            else if (*p == '\t')
  310. X                col += (tabsize - ((col - 1) % tabsize));    /* JHT 22oct89 */
  311. X            else
  312. X                break;
  313. X            p++;
  314. X        };
  315. X        if (col > ps.ind_size)
  316. X            ps.ind_level = ps.i_l_follow = col / ps.ind_size;
  317. X    }
  318. X    if (troff)
  319. X    {
  320. X        register char *p = in_name, *beg = in_name;
  321. X
  322. X        while (*p)
  323. X            if (*p++ == '/')
  324. X                beg = p;
  325. X        fprintf(output, ".Fn \"%s\"\n", beg);
  326. X    }
  327. X    /*
  328. X       START OF MAIN LOOP
  329. X    */
  330. X
  331. X    while (1)
  332. X    {                            /* this is the main loop.  it will go until we
  333. X                                   reach eof */
  334. X        int is_procname;
  335. X
  336. X        type_code = lexi();        /* lexi reads one token.  The actual characters
  337. X                                   read are stored in "token". lexi returns a
  338. X                                   code indicating the type of token */
  339. X        is_procname = ps.procname[0];
  340. X
  341. X        /*
  342. X           The following code moves everything following an if (), while (),
  343. X           else, etc. up to the start of the following stmt to a buffer. This
  344. X           allows proper handling of both kinds of brace placement.
  345. X        */
  346. X
  347. X        flushed_nl = false;
  348. X        while (ps.search_brace)
  349. X        {                        /* if we scanned an if(), while(), etc., we
  350. X                                   might need to copy stuff into a buffer we
  351. X                                   must loop, copying stuff into save_com,
  352. X                                   until we find the start of the stmt which
  353. X                                   follows the if, or whatever */
  354. X            switch (type_code)
  355. X            {
  356. X            case newline:
  357. X                ++line_no;
  358. X                flushed_nl = true;
  359. X            case form_feed:
  360. X                break;            /* form feeds and newlines found here will be
  361. X                                   ignored */
  362. X
  363. X            case lbrace:        /* this is a brace that starts the compound
  364. X                                   stmt */
  365. X                if (sc_end == 0)
  366. X                {                /* ignore buffering if a comment wasn't stored
  367. X                                   up */
  368. X                    ps.search_brace = false;
  369. X                    goto check_type;
  370. X                }
  371. X        /*        if (btype_2)        Bug notified by Steve Comen, 16 Mar 92 */
  372. X                {
  373. X                    save_com[0] = '{';    /* we either want to put the brace
  374. X                                           right after the if */
  375. X                    goto sw_buffer;    /* go to common code to get out of this
  376. X                                       loop */
  377. X                }
  378. X            case comment:        /* we have a comment, so we must copy it into
  379. X                                   the buffer */
  380. X                if (!flushed_nl || sc_end != 0)
  381. X                {
  382. X                    if (sc_end == 0)
  383. X                    {            /* if this is the first comment, we must set up
  384. X                                   the buffer */
  385. X                        save_com[0] = save_com[1] = ' ';
  386. X                        sc_end = &(save_com[2]);
  387. X                    }
  388. X                    else
  389. X                    {
  390. X                        *sc_end++ = '\n';    /* add newline between comments */
  391. X                        *sc_end++ = ' ';
  392. X                        --line_no;
  393. X                    }
  394. X                    *sc_end++ = '/';    /* copy in start of comment */
  395. X                    *sc_end++ = '*';
  396. X
  397. X                    for (;;)
  398. X                    {            /* loop until we get to the end of the comment */
  399. X                        *sc_end = *buf_ptr++;
  400. X                        if (buf_ptr >= buf_end)
  401. X                            fill_buffer();
  402. X
  403. X                        if (*sc_end++ == '*' && *buf_ptr == '/')
  404. X                            break;    /* we are at end of comment */
  405. X
  406. X                        if (sc_end >= &(save_com[sc_size]))
  407. X                        {        /* check for temp buffer overflow */
  408. X                            diag(1, "Internal buffer overflow - Move big comment from right after if, while, or whatever.");
  409. X                            fflush(output);
  410. X                            exit(1);
  411. X                        }
  412. X                    }
  413. X                    *sc_end++ = '/';    /* add ending slash */
  414. X                    if (++buf_ptr >= buf_end)    /* get past / in buffer */
  415. X                        fill_buffer();
  416. X                    break;
  417. X                }
  418. X            case cc_commnt:    /* we have a comment, so we must copy it into
  419. X                                   the buffer */
  420. X                /* C++ comment */
  421. X                if (!flushed_nl || sc_end != 0)
  422. X                {
  423. X                    if (sc_end == 0)
  424. X                    {            /* if this is the first comment, we must set up
  425. X                                   the buffer */
  426. X                        save_com[0] = save_com[1] = ' ';
  427. X                        sc_end = &(save_com[2]);
  428. X                    }
  429. X                    else
  430. X                    {
  431. X                        *sc_end++ = '\n';    /* add newline between comments */
  432. X                        *sc_end++ = ' ';
  433. X                        --line_no;
  434. X                    }
  435. X                    *sc_end++ = '/';    /* copy in start of comment */
  436. X                    *sc_end++ = '/';
  437. X
  438. X                    for (;;)
  439. X                    {            /* loop until we get to the end of the comment */
  440. X                        *sc_end++ = *buf_ptr++;
  441. X                        if (buf_ptr >= buf_end)
  442. X                            fill_buffer();
  443. X
  444. X                        if (*buf_ptr == '\n')
  445. X                            break;    /* we are at end of comment */
  446. X
  447. X                        if (sc_end >= &(save_com[sc_size]))
  448. X                        {        /* check for temp buffer overflow */
  449. X                            diag(1, "Internal buffer overflow - Move big comment from right after if, while, or whatever.");
  450. X                            fflush(output);
  451. X                            exit(1);
  452. X                        }
  453. X                    }
  454. X                    if (++buf_ptr >= buf_end)    /* eat '\n' */
  455. X                        fill_buffer();
  456. X                    break;
  457. X                }
  458. X            default:            /* it is the start of a normal statment */
  459. X                if (flushed_nl)    /* if we flushed a newline, make sure it is put
  460. X                                   back */
  461. X                    force_nl = true;
  462. X                if (type_code == sp_paren && *token == 'i'
  463. X                    && last_else && ps.else_if
  464. X                    || type_code == sp_nparen && *token == 'e'
  465. X                    && e_code != s_code && e_code[-1] == '}')
  466. X                    force_nl = false;
  467. X
  468. X                if (sc_end == 0)
  469. X                {                /* ignore buffering if comment wasnt saved up */
  470. X                    ps.search_brace = false;
  471. X                    goto check_type;
  472. X                }
  473. X                if (force_nl)
  474. X                {                /* if we should insert a nl here, put it into
  475. X                                   the buffer */
  476. X                    force_nl = false;
  477. X                    --line_no;    /* this will be re-increased when the nl is
  478. X                                   read from the buffer */
  479. X                    *sc_end++ = '\n';
  480. X                    *sc_end++ = ' ';
  481. X                    if (verbose && !flushed_nl)    /* print error msg if the line
  482. X                                                   was not already broken */
  483. X                        diag(0, "Line broken");
  484. X                    flushed_nl = false;
  485. X                }
  486. X                for (t_ptr = token; *t_ptr; ++t_ptr)
  487. X                    *sc_end++ = *t_ptr;    /* copy token into temp buffer */
  488. X                ps.procname[0] = 0;
  489. X
  490. X        sw_buffer:
  491. X                ps.search_brace = false;    /* stop looking for start of stmt */
  492. X                bp_save = buf_ptr;    /* save current input buffer */
  493. X                be_save = buf_end;
  494. X                buf_ptr = save_com;    /* fix so that subsequent calls to lexi
  495. X                                       will take tokens out of save_com */
  496. X                *sc_end++ = ' ';/* add trailing blank, just in case */
  497. X                buf_end = sc_end;
  498. X                sc_end = 0;
  499. X                break;
  500. X            }                    /* end of switch */
  501. X            if (type_code != 0)    /* we must make this check, just in case there
  502. X                                   was an unexpected EOF */
  503. X                type_code = lexi();    /* read another token */
  504. X            /* if (ps.search_brace) ps.procname[0] = 0; */
  505. X            if ((is_procname = ps.procname[0]) && flushed_nl
  506. X                && !procnames_start_line && ps.in_decl
  507. X                && type_code == ident)
  508. X                flushed_nl = 0;
  509. X        }                        /* end of while (search_brace) */
  510. X        last_else = 0;
  511. Xcheck_type:
  512. X        if (type_code == 0)
  513. X        {                        /* we got eof */
  514. X            if (s_lab != e_lab || s_code != e_code
  515. X                || s_com != e_com)    /* must dump end of line */
  516. X                dump_line();
  517. X            if (ps.tos > 1)        /* check for balanced braces */
  518. X                diag(1, "Stuff missing from end of file.");
  519. X
  520. X            if (verbose)
  521. X            {
  522. X                printf("There were %d output lines and %d comments\n",
  523. X                       ps.out_lines, ps.out_coms);
  524. X                printf("(Lines with comments)/(Lines with code): %6.3f\n",
  525. X                       (1.0 * ps.com_lines) / code_lines);
  526. X            }
  527. X            fflush(output);
  528. X            exit(found_err);
  529. X        }
  530. X        if (
  531. X            (type_code != comment) &&
  532. X            (type_code != cc_commnt) &&
  533. X            (type_code != newline) &&
  534. X            (type_code != preesc) &&
  535. X            (type_code != form_feed))
  536. X        {
  537. X            if (force_nl &&
  538. X                (type_code != semicolon) &&
  539. X                (type_code != lbrace || btype_3 || !btype_2))
  540. X            {
  541. X                /* we should force a broken line here */
  542. X                if (verbose && !flushed_nl)
  543. X                    diag(0, "Line broken");
  544. X                flushed_nl = false;
  545. X                dump_line();
  546. X                ps.want_blank = false;    /* dont insert blank at line start */
  547. X                force_nl = false;
  548. X            }
  549. X            ps.in_stmt = true;    /* turn on flag which causes an extra level of
  550. X                                   indentation. this is turned off by a ; or
  551. X                                   '}' */
  552. X            if (s_com != e_com)
  553. X            {                    /* the turkey has embedded a comment in a line.
  554. X                                   fix it */
  555. X                *e_code++ = ' ';
  556. X                for (t_ptr = s_com; *t_ptr; ++t_ptr)
  557. X                {
  558. X                    check_size(code);
  559. X                    *e_code++ = *t_ptr;
  560. X                }
  561. X                *e_code++ = ' ';
  562. X                *e_code = '\0';    /* null terminate code sect */
  563. X                ps.want_blank = false;
  564. X                e_com = s_com;
  565. X            }
  566. X        }
  567. X        else if (type_code != comment && type_code != cc_commnt)
  568. X            /* preserve force_nl thru a comment */
  569. X            force_nl = false;    /* cancel forced newline after newline, form
  570. X                                   feed, etc */
  571. X
  572. X
  573. X
  574. X        /*-----------------------------------------------------*\
  575. X        |       do switch on type of token scanned               |
  576. X        \*-----------------------------------------------------*/
  577. X        check_size(code);
  578. X        switch (type_code)
  579. X        {                        /* now, decide what to do with the token */
  580. X
  581. X        case form_feed:        /* found a form feed in line */
  582. X            ps.use_ff = true;    /* a form feed is treated much like a newline */
  583. X            dump_line();
  584. X            ps.want_blank = false;
  585. X            break;
  586. X
  587. X        case newline:
  588. X            if (ps.last_token != comma || ps.p_l_follow > 0
  589. X                || !ps.leave_comma || ps.block_init || !break_comma || s_com != e_com)
  590. X            {
  591. X                dump_line();
  592. X                ps.want_blank = false;
  593. X            }
  594. X            ++line_no;            /* keep track of input line number */
  595. X            break;
  596. X
  597. X        case lparen:            /* got a '(' or '[' */
  598. X            ++ps.p_l_follow;    /* count parens to make Healy happy */
  599. X            if (ps.want_blank && *token != '[' &&
  600. X                (ps.last_token != ident || proc_calls_space
  601. X               || (ps.its_a_keyword && (!ps.sizeof_keyword || Bill_Shannon))))
  602. X                *e_code++ = ' ';
  603. X            if (ps.in_decl && !ps.block_init)
  604. X                if (troff && !ps.dumped_decl_indent && !is_procname && ps.last_token == decl)
  605. X                {
  606. X                    ps.dumped_decl_indent = 1;
  607. X                    sprintf(e_code, "\n.Du %dp+\200p \"%s\"\n", dec_ind * 7, token);
  608. X                    e_code += strlen(e_code);
  609. X                }
  610. X                else
  611. X                {
  612. X                    while ((e_code - s_code) < dec_ind)
  613. X                    {
  614. X                        check_size(code);
  615. X                        *e_code++ = ' ';
  616. X                    }
  617. X                    *e_code++ = token[0];
  618. X                }
  619. X            else
  620. X                *e_code++ = token[0];
  621. X            if (parens_space && *token != '[')
  622. X                *e_code++ = ' ';
  623. X            ps.paren_indents[ps.p_l_follow - 1] = (short) (e_code - s_code);
  624. X            if (sp_sw && ps.p_l_follow == 1 && extra_expression_indent
  625. X                && ps.paren_indents[0] < (short) (2 * ps.ind_size))
  626. X                ps.paren_indents[0] = (short) (2 * ps.ind_size);
  627. X            ps.want_blank = false;
  628. X            if (ps.in_or_st && *token == '(' && ps.tos <= 2)
  629. X            {
  630. X                /*
  631. X                   this is a kluge to make sure that declarations will be
  632. X                   aligned right if proc decl has an explicit type on it, i.e.
  633. X                   "int a(x) {..."
  634. X                */
  635. X                parse(semicolon);    /* I said this was a kluge... */
  636. X                ps.in_or_st = false;    /* turn off flag for structure decl or
  637. X                                           initialization */
  638. X            }
  639. X            if (ps.sizeof_keyword)
  640. X                ps.sizeof_mask |= 1 << ps.p_l_follow;
  641. X            break;
  642. X
  643. X        case rparen:            /* got a ')' or ']' */
  644. X            if (ps.cast_mask & (1 << ps.p_l_follow) & ~ps.sizeof_mask)
  645. X            {
  646. X                ps.last_u_d = true;
  647. X                ps.cast_mask &= (1 << ps.p_l_follow) - 1;
  648. X            }
  649. X            ps.sizeof_mask &= (1 << ps.p_l_follow) - 1;
  650. X            if (--ps.p_l_follow < 0)
  651. X            {
  652. X                ps.p_l_follow = 0;
  653. X                diag(0, "Extra %c", *token);
  654. X            }
  655. X            if (e_code == s_code)    /* if the paren starts the line */
  656. X                ps.paren_level = ps.p_l_follow;    /* then indent it */
  657. X
  658. X            if (parens_space && *token != ']')
  659. X                *e_code++ = ' ';
  660. X            *e_code++ = token[0];
  661. X            ps.want_blank = true;
  662. X
  663. X            if (sp_sw && (ps.p_l_follow == 0))
  664. X            {                    /* check for end of if (...), or some such */
  665. X                sp_sw = false;
  666. X                force_nl = true;/* must force newline after if */
  667. X                ps.last_u_d = true;    /* inform lexi that a following operator is
  668. X                                       unary */
  669. X                ps.in_stmt = false;    /* dont use stmt continuation indentation */
  670. X
  671. X                parse(hd_type);    /* let parser worry about if, or whatever */
  672. X            }
  673. X            ps.search_brace = btype_2 && !btype_3;
  674. X            /*
  675. X               this should insure that constructs such as main(){...} and
  676. X               int[]{...} have their braces put in the right place
  677. X            */
  678. X            break;
  679. X
  680. X        case unary_op:            /* this could be any unary operation */
  681. X            if (ps.want_blank)
  682. X                *e_code++ = ' ';
  683. X
  684. X            if (troff && !ps.dumped_decl_indent && ps.in_decl && !is_procname)
  685. X            {
  686. X                sprintf(e_code, "\n.Du %dp+\200p \"%s\"\n", dec_ind * 7, token);
  687. X                ps.dumped_decl_indent = 1;
  688. X                e_code += strlen(e_code);
  689. X            }
  690. X            else
  691. X            {
  692. X                char *res = token;
  693. X
  694. X                if (ps.in_decl && !ps.block_init)
  695. X                {                /* if this is a unary op in a declaration, we
  696. X                                   should indent this token */
  697. X                    for (i = 0; token[i]; ++i);    /* find length of token */
  698. X                    while ((e_code - s_code) < (dec_ind - i))
  699. X                    {
  700. X                        check_size(code);
  701. X                        *e_code++ = ' ';    /* pad it */
  702. X                    }
  703. X                }
  704. X                if (troff && token[0] == '-' && token[1] == '>')
  705. X                    res = "\\(->";
  706. X                for (t_ptr = res; *t_ptr; ++t_ptr)
  707. X                {
  708. X                    check_size(code);
  709. X                    *e_code++ = *t_ptr;
  710. X                }
  711. X            }
  712. X            ps.want_blank = false;
  713. X            break;
  714. X
  715. X        case binary_op:        /* any binary operation */
  716. X
  717. X            if (ps.want_blank)
  718. X                *e_code++ = ' ';
  719. X            {
  720. X                char *res = token;
  721. X
  722. X                if (troff)
  723. X                    switch (token[0])
  724. X                    {
  725. X                    case '<':
  726. X                        if (token[1] == '=')
  727. X                            res = "\\(<=";
  728. X                        break;
  729. X                    case '>':
  730. X                        if (token[1] == '=')
  731. X                            res = "\\(>=";
  732. X                        break;
  733. X                    case '!':
  734. X                        if (token[1] == '=')
  735. X                            res = "\\(!=";
  736. X                        break;
  737. X                    case '|':
  738. X                        if (token[1] == '|')
  739. X                            res = "\\(br\\(br";
  740. X                        else if (token[1] == 0)
  741. X                            res = "\\(br";
  742. X                        break;
  743. X                    }
  744. X                for (t_ptr = res; *t_ptr; ++t_ptr)
  745. X                {
  746. X                    check_size(code);
  747. X                    *e_code++ = *t_ptr;    /* move the operator */
  748. X                }
  749. X            }
  750. X            ps.want_blank = true;
  751. X            break;
  752. X
  753. X        case postop:            /* got a trailing ++ or -- */
  754. X            *e_code++ = token[0];
  755. X            *e_code++ = token[1];
  756. X            ps.want_blank = true;
  757. X            break;
  758. X
  759. X        case question:            /* got a ? */
  760. X            squest++;            /* this will be used when a later colon appears
  761. X                                   so we can distinguish the <c>?<n>:<n>
  762. X                                   construct */
  763. X            if (ps.want_blank)
  764. X                *e_code++ = ' ';
  765. X            *e_code++ = '?';
  766. X            ps.want_blank = true;
  767. X            break;
  768. X
  769. X        case casestmt:            /* got word 'case' or 'default' */
  770. X            scase = true;        /* so we can process the later colon properly */
  771. X            goto copy_id;
  772. X
  773. X        case privpub:            /* got public, private or protected */
  774. X            strcpy(s_lab, token);
  775. X            e_lab = s_lab + strlen(token);
  776. X            *e_lab++ = ':';
  777. X            *e_lab++ = ' ';
  778. X            *e_lab = '\0';
  779. X            force_nl = true;
  780. X            break;
  781. X
  782. X        case colon:            /* got a ':' */
  783. X            if (squest > 0)
  784. X            {                    /* it is part of the <c>?<n>: <n> construct */
  785. X                --squest;
  786. X                if (ps.want_blank)
  787. X                    *e_code++ = ' ';
  788. X                *e_code++ = ':';
  789. X                ps.want_blank = true;
  790. X                break;
  791. X            }
  792. X            if (ps.in_decl)
  793. X            {
  794. X                if (cplus)        /* assume public, private, or protected */
  795. X                {
  796. X                    for (t_ptr = s_code; *t_ptr; ++t_ptr)
  797. X                        *e_lab++ = *t_ptr;    /* turn everything so far into a
  798. X                                               label */
  799. X                    e_code = s_code;
  800. X                    *e_lab++ = ':';
  801. X                    *e_lab++ = ' ';
  802. X                    *e_lab = '\0';
  803. X                    force_nl = true;
  804. X                    scase = false;
  805. X                    ps.pcase = true;
  806. X                    break;
  807. X                }
  808. X                *e_code++ = ':';
  809. X                ps.want_blank = false;
  810. X                break;
  811. X            }
  812. X            ps.in_stmt = false;    /* seeing a label does not imply we are in a
  813. X                                   stmt */
  814. X            for (t_ptr = s_code; *t_ptr; ++t_ptr)
  815. X                *e_lab++ = *t_ptr;    /* turn everything so far into a label */
  816. X            e_code = s_code;
  817. X            *e_lab++ = ':';
  818. X            *e_lab++ = ' ';
  819. X            *e_lab = '\0';
  820. X
  821. X            force_nl = ps.pcase = scase;    /* ps.pcase will be used by
  822. X                                               dump_line to decide how to
  823. X                                               indent the label. force_nl will
  824. X                                               force a case n: to be on a line
  825. X                                               by itself */
  826. X            scase = false;
  827. X            ps.want_blank = false;
  828. X            break;
  829. X
  830. X        case semicolon:        /* got a ';' */
  831. X            ps.in_or_st = false;/* we are not in an initialization or structure
  832. X                                   declaration */
  833. X            scase = false;        /* these will only need resetting in a error */
  834. X            squest = 0;
  835. X            if (ps.last_token == rparen)
  836. X                ps.in_parameter_declaration = 0;
  837. X            ps.cast_mask = 0;
  838. X            ps.sizeof_mask = 0;
  839. X            ps.block_init = 0;
  840. X            ps.block_init_level = 0;
  841. X            ps.just_saw_decl--;
  842. X
  843. X            if (ps.in_decl && s_code == e_code && !ps.block_init)
  844. X                while ((e_code - s_code) < (dec_ind - 1))
  845. X                {
  846. X                    check_size(code);
  847. X                    *e_code++ = ' ';
  848. X                }
  849. X
  850. X            ps.in_decl = (ps.dec_nest > 0);    /* if we were in a first level
  851. X                                               structure declaration, we arent
  852. X                                               any more */
  853. X
  854. X            if ((!sp_sw || hd_type != forstmt) && ps.p_l_follow > 0)
  855. X            {
  856. X
  857. X                /*
  858. X                   This should be true iff there were unbalanced parens in the
  859. X                   stmt.  It is a bit complicated, because the semicolon might
  860. X                   be in a for stmt
  861. X                */
  862. X                diag(1, "Unbalanced parens");
  863. X                ps.p_l_follow = 0;
  864. X                if (sp_sw)
  865. X                {                /* this is a check for a if, while, etc. with
  866. X                                   unbalanced parens */
  867. X                    sp_sw = false;
  868. X                    parse(hd_type);    /* dont lose the if, or whatever */
  869. X                }
  870. X            }
  871. X            *e_code++ = ';';
  872. X            ps.want_blank = true;
  873. X            ps.in_stmt = (ps.p_l_follow > 0);    /* we are no longer in the
  874. X                                                   middle of a stmt */
  875. X
  876. X            if (!sp_sw)
  877. X            {                    /* if not if for (;;) */
  878. X                parse(semicolon);    /* let parser know about end of stmt */
  879. X                force_nl = true;/* force newline after a end of stmt */
  880. X            }
  881. X            break;
  882. X
  883. X        case lbrace:            /* got a '{' */
  884. X            ps.in_stmt = false;    /* dont indent the {} */
  885. X            if (!ps.block_init)
  886. X                force_nl = true;/* force other stuff on same line as '{' onto
  887. X                                   new line */
  888. X            else if (ps.block_init_level <= 0)
  889. X                ps.block_init_level = 1;
  890. X            else
  891. X                ps.block_init_level++;
  892. X
  893. X            if (s_code != e_code && !ps.block_init)
  894. X            {
  895. X                if (btype_3 || !btype_2)
  896. X                {
  897. X                    dump_line();
  898. X                    ps.want_blank = false;
  899. X                }
  900. X                else if (ps.in_parameter_declaration && !ps.in_or_st)
  901. X                {
  902. X                    ps.i_l_follow = 0;
  903. X                    dump_line();
  904. X                    ps.want_blank = false;
  905. X                }
  906. X            }
  907. X            if (ps.in_parameter_declaration)
  908. X                prefix_blankline_requested = 0;
  909. X
  910. X            if (ps.p_l_follow > 0)
  911. X            {                    /* check for preceeding unbalanced parens */
  912. X                diag(1, "Unbalanced parens");
  913. X                ps.p_l_follow = 0;
  914. X                if (sp_sw)
  915. X                {                /* check for unclosed if, for, etc. */
  916. X                    sp_sw = false;
  917. X                    parse(hd_type);
  918. X                    ps.ind_level = ps.i_l_follow;
  919. X                }
  920. X            }
  921. X            if (btype_3)
  922. X                ps.ind_stmt = true;
  923. X            else if (s_code == e_code)
  924. X                ps.ind_stmt = false;    /* dont put extra indentation on line
  925. X                                           with '{' */
  926. X            if (ps.in_decl && ps.in_or_st)
  927. X            {                    /* this is either a structure declaration or an
  928. X                                   init */
  929. X                di_stack[ps.dec_nest++] = dec_ind;
  930. X                /* ?        dec_ind = 0; */
  931. X            }
  932. X            else
  933. X            {
  934. X                ps.decl_on_line = false;    /* we cant be in the middle of a
  935. X                                               declaration, so dont do special
  936. X                                               indentation of comments */
  937. X                if (blanklines_after_declarations_at_proctop
  938. X                    && ps.in_parameter_declaration)
  939. X                    postfix_blankline_requested = 1;
  940. X                ps.in_parameter_declaration = 0;
  941. X            }
  942. X            dec_ind = 0;
  943. X            parse(lbrace);        /* let parser know about this */
  944. X            if (ps.want_blank)    /* put a blank before '{' if '{' is not at
  945. X                                   start of line */
  946. X                *e_code++ = ' ';
  947. X            ps.want_blank = false;
  948. X            *e_code++ = '{';
  949. X            ps.just_saw_decl = 0;
  950. X            break;
  951. X
  952. X        case rbrace:            /* got a '}' */
  953. X            if (ps.p_stack[ps.tos] == decl && !ps.block_init)    /* semicolons can be
  954. X                                                                   omitted in
  955. X                                                                   declarations */
  956. X                parse(semicolon);
  957. X            if (ps.p_l_follow)
  958. X            {                    /* check for unclosed if, for, else. */
  959. X                diag(1, "Unbalanced parens");
  960. X                ps.p_l_follow = 0;
  961. X                sp_sw = false;
  962. X            }
  963. X            ps.just_saw_decl = 0;
  964. X            ps.block_init_level--;
  965. X            if (s_code != e_code && !ps.block_init)
  966. X            {                    /* '}' must be first on line */
  967. X                if (verbose)
  968. X                    diag(0, "Line broken");
  969. X                dump_line();
  970. X            }
  971. X            *e_code++ = '}';
  972. X            ps.want_blank = true;
  973. X            ps.in_stmt = ps.ind_stmt = false;
  974. X            if (ps.dec_nest > 0)
  975. X            {                    /* we are in multi-level structure declaration */
  976. X                dec_ind = di_stack[--ps.dec_nest];
  977. X                if (ps.dec_nest == 0 && !ps.in_parameter_declaration)
  978. X                    ps.just_saw_decl = 2;
  979. X                ps.in_decl = true;
  980. X            }
  981. X            prefix_blankline_requested = 0;
  982. X            parse(rbrace);        /* let parser know about this */
  983. X            ps.search_brace = cuddle_else && ps.p_stack[ps.tos] == ifhead
  984. X                && ps.il[ps.tos] >= ps.ind_level;
  985. X            if (ps.tos <= 1 && blanklines_after_procs && ps.dec_nest <= 0)
  986. X                postfix_blankline_requested = 1;
  987. X            if (btype_3 && ps.p_stack[ps.tos] == dohead)
  988. X            {
  989. X                if (verbose)
  990. X                    diag(0, "Line broken");
  991. X                dump_line();
  992. X                ps.want_blank = false;
  993. X            }
  994. X            break;
  995. X
  996. X        case swstmt:            /* got keyword "switch" */
  997. X            sp_sw = true;
  998. X            hd_type = swstmt;    /* keep this for when we have seen the
  999. X                                   expression */
  1000. X            goto copy_id;        /* go move the token into buffer */
  1001. X
  1002. X        case sp_paren:            /* token is if, while, for */
  1003. X            sp_sw = true;        /* the interesting stuff is done after the
  1004. X                                   expression is scanned */
  1005. X            hd_type = (*token == 'i' ? ifstmt :
  1006. X                       (*token == 'w' ? whilestmt : forstmt));
  1007. X
  1008. X            /*
  1009. X               remember the type of header for later use by parser
  1010. X            */
  1011. X            goto copy_id;        /* copy the token into line */
  1012. X
  1013. X        case sp_nparen:        /* got else, do */
  1014. X            ps.in_stmt = false;
  1015. X            if (*token == 'e')
  1016. X            {
  1017. X                if (e_code != s_code && (!cuddle_else || e_code[-1] != '}'))
  1018. X                {
  1019. X                    if (verbose)
  1020. X                        diag(0, "Line broken");
  1021. X                    dump_line();/* make sure this starts a line */
  1022. X                    ps.want_blank = false;
  1023. X                }
  1024. X                force_nl = true;/* also, following stuff must go onto new line */
  1025. X                last_else = 1;
  1026. X                parse(elselit);
  1027. X            }
  1028. X            else
  1029. X            {
  1030. X                if (e_code != s_code)
  1031. X                {                /* make sure this starts a line */
  1032. X                    if (verbose)
  1033. X                        diag(0, "Line broken");
  1034. X                    dump_line();
  1035. X                    ps.want_blank = false;
  1036. X                }
  1037. X                force_nl = true;/* also, following stuff must go onto new line */
  1038. X                last_else = 0;
  1039. X                parse(dolit);
  1040. X            }
  1041. X            goto copy_id;        /* move the token into line */
  1042. X
  1043. X        case decl:                /* we have a declaration type (int, register,
  1044. X                                   etc.) */
  1045. X            parse(decl);        /* let parser worry about indentation */
  1046. X            if (ps.last_token == rparen && ps.tos <= 1)
  1047. X            {
  1048. X                ps.in_parameter_declaration = 1;
  1049. X                if (s_code != e_code)
  1050. X                {
  1051. X                    dump_line();
  1052. X                    ps.want_blank = 0;
  1053. X                }
  1054. X            }
  1055. X            if (ps.in_parameter_declaration && ps.indent_parameters && ps.dec_nest == 0)
  1056. X            {
  1057. X                ps.ind_level = ps.i_l_follow = 1;
  1058. X                ps.ind_stmt = 0;
  1059. X            }
  1060. X            ps.in_or_st = true;    /* this might be a structure or initialization
  1061. X                                   declaration */
  1062. X            ps.in_decl = ps.decl_on_line = true;
  1063. X            if ( /* !ps.in_or_st && */ ps.dec_nest <= 0)
  1064. X                ps.just_saw_decl = 2;
  1065. X            prefix_blankline_requested = 0;
  1066. X            for (i = 0; token[i++];);    /* get length of token */
  1067. X
  1068. X            /*
  1069. X               dec_ind = e_code - s_code + (ps.decl_indent>i ? ps.decl_indent :
  1070. X               i);
  1071. X            */
  1072. X            dec_ind = ps.decl_indent > 0 ? ps.decl_indent : i;
  1073. X            goto copy_id;
  1074. X
  1075. X        case ident:            /* got an identifier or constant */
  1076. X            if (ps.in_decl)
  1077. X            {                    /* if we are in a declaration, we must indent
  1078. X                                   identifier */
  1079. X                if (ps.want_blank)
  1080. X                    *e_code++ = ' ';
  1081. X                ps.want_blank = false;
  1082. X                if (is_procname == 0 || !procnames_start_line)
  1083. X                {
  1084. X                    if (!ps.block_init)
  1085. X                        if (troff && !ps.dumped_decl_indent)
  1086. X                        {
  1087. X                            sprintf(e_code, "\n.De %dp+\200p\n", dec_ind * 7);
  1088. X                            ps.dumped_decl_indent = 1;
  1089. X                            e_code += strlen(e_code);
  1090. X                        }
  1091. X                        else
  1092. X                            while ((e_code - s_code) < dec_ind)
  1093. X                            {
  1094. X                                check_size(code);
  1095. X                                *e_code++ = ' ';
  1096. X                            }
  1097. X                }
  1098. X                else
  1099. X                {
  1100. X                    if (dec_ind && s_code != e_code)
  1101. X                        dump_line();
  1102. X                    dec_ind = 0;
  1103. X                    ps.want_blank = false;
  1104. X                }
  1105. X            }
  1106. X            else if (sp_sw && ps.p_l_follow == 0)
  1107. X            {
  1108. X                sp_sw = false;
  1109. X                force_nl = true;
  1110. X                ps.last_u_d = true;
  1111. X                ps.in_stmt = false;
  1112. X                parse(hd_type);
  1113. X            }
  1114. X    copy_id:
  1115. X            if (ps.want_blank)
  1116. X                *e_code++ = ' ';
  1117. X            if (troff && ps.its_a_keyword)
  1118. X            {
  1119. X                e_code = chfont(&bodyf, &keywordf, e_code);
  1120. X                for (t_ptr = token; *t_ptr; ++t_ptr)
  1121. X                {
  1122. X                    check_size(code);
  1123. X                    *e_code++ = keywordf.allcaps && islower(*t_ptr)
  1124. X                        ? (char) toupper(*t_ptr) : *t_ptr;
  1125. X                }
  1126. X                e_code = chfont(&keywordf, &bodyf, e_code);
  1127. X            }
  1128. X            else
  1129. X                for (t_ptr = token; *t_ptr; ++t_ptr)
  1130. X                {
  1131. X                    check_size(code);
  1132. X                    *e_code++ = *t_ptr;
  1133. X                }
  1134. X            ps.want_blank = true;
  1135. X            break;
  1136. X
  1137. X        case period:            /* treat a period kind of like a binary
  1138. X                                   operation */
  1139. X            *e_code++ = '.';    /* move the period into line */
  1140. X            ps.want_blank = false;    /* dont put a blank after a period */
  1141. X            break;
  1142. X
  1143. X        case comma:
  1144. X            ps.want_blank = (s_code != e_code);    /* only put blank after comma
  1145. X                                                   if comma does not start the
  1146. X                                                   line */
  1147. X            if (ps.in_decl && is_procname == 0 && !ps.block_init)
  1148. X                while ((e_code - s_code) < (dec_ind - 1))
  1149. X                {
  1150. X                    check_size(code);
  1151. X                    *e_code++ = ' ';
  1152. X                }
  1153. X
  1154. X            *e_code++ = ',';
  1155. X            if (ps.p_l_follow == 0)
  1156. X            {
  1157. X                if (ps.block_init_level <= 0)
  1158. X                    ps.block_init = 0;
  1159. X                if (break_comma && !ps.leave_comma)
  1160. X                    force_nl = true;
  1161. X            }
  1162. X            break;
  1163. X
  1164. X        case preesc:            /* got the character '#' */
  1165. X            if ((s_com != e_com) ||
  1166. X                (s_lab != e_lab) ||
  1167. X                (s_code != e_code))
  1168. X                dump_line();
  1169. X            *e_lab++ = '#';        /* move whole line to 'label' buffer */
  1170. X            {
  1171. X                int in_comment = 0;
  1172. X                int com_start = 0;
  1173. X                char quote = 0;
  1174. X                int com_end = 0;
  1175. X
  1176. X                while (*buf_ptr != '\n' || in_comment)
  1177. X                {
  1178. X                    check_size(lab);
  1179. X                    *e_lab = *buf_ptr++;
  1180. X                    if (buf_ptr >= buf_end)
  1181. X                        fill_buffer();
  1182. X                    switch (*e_lab++)
  1183. X                    {
  1184. X                    case BACKSLASH:
  1185. X                        if (troff)
  1186. X                            *e_lab++ = BACKSLASH;
  1187. X                        if (!in_comment)
  1188. X                        {
  1189. X                            *e_lab++ = *buf_ptr++;
  1190. X                            if (buf_ptr >= buf_end)
  1191. X                                fill_buffer();
  1192. X                        }
  1193. X                        break;
  1194. X                    case '/':
  1195. X                        if (*buf_ptr == '*' && !in_comment && !quote)
  1196. X                        {
  1197. X                            in_comment = 1;
  1198. X                            *e_lab++ = *buf_ptr++;
  1199. X                            com_start = e_lab - s_lab - 2;
  1200. X                        }
  1201. X                        else if (*buf_ptr == '/' && !in_comment && !quote)
  1202. X                        {
  1203. X                            in_comment = 2;
  1204. X                            *e_lab++ = *buf_ptr++;
  1205. X                            com_start = e_lab - s_lab - 2;
  1206. X                        }
  1207. X                        break;
  1208. X                    case '"':
  1209. X                        if (quote == '"')
  1210. X                            quote = 0;
  1211. X                        break;
  1212. X                    case '\'':
  1213. X                        if (quote == '\'')
  1214. X                            quote = 0;
  1215. X                        break;
  1216. X                    case '*':
  1217. X                        if (*buf_ptr == '/' && in_comment == 1)
  1218. X                        {
  1219. X                            in_comment = 0;
  1220. X                            *e_lab++ = *buf_ptr++;
  1221. X                            com_end = e_lab - s_lab;
  1222. X                        }
  1223. X                        break;
  1224. X                    case '\n':
  1225. X                        if (in_comment == 2)
  1226. X                        {
  1227. X                            in_comment = 0;
  1228. X                            --buf_ptr;    /* so while loop will exit */
  1229. X                            com_end = e_lab - s_lab;
  1230. X                        }
  1231. X                        break;
  1232. X                    }
  1233. X                }
  1234. X
  1235. X                while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t'))
  1236. X                    e_lab--;
  1237. X                if (e_lab - s_lab == com_end && bp_save == 0)
  1238. X                {                /* comment on preprocessor line */
  1239. X                    if (sc_end == 0)    /* if this is the first comment, we
  1240. X                                           must set up the buffer */
  1241. X                        sc_end = &(save_com[0]);
  1242. X                    else
  1243. X                    {
  1244. X                        *sc_end++ = '\n';    /* add newline between comments */
  1245. X                        *sc_end++ = ' ';
  1246. X                        --line_no;
  1247. X                    }
  1248. X#ifdef BSD                        /* gst 24 Mar 89 */
  1249. X                    bcopy(s_lab + com_start, sc_end, com_end - com_start);
  1250. X#else
  1251. X                    memcpy(sc_end, s_lab + com_start, com_end - com_start);
  1252. X#endif
  1253. X                    sc_end += com_end - com_start;
  1254. X                    if (sc_end >= &save_com[sc_size])
  1255. X                        abort();
  1256. X                    e_lab = s_lab + com_start;
  1257. X                    while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t'))
  1258. X                        e_lab--;
  1259. X                    bp_save = buf_ptr;    /* save current input buffer */
  1260. X                    be_save = buf_end;
  1261. X                    buf_ptr = save_com;    /* fix so that subsequent calls to lexi
  1262. X                                           will take tokens out of save_com */
  1263. X                    *sc_end++ = ' ';    /* add trailing blank, just in case */
  1264. X                    buf_end = sc_end;
  1265. X                    sc_end = 0;
  1266. X                }
  1267. X                *e_lab = '\0';    /* null terminate line */
  1268. X                ps.pcase = false;
  1269. X            }
  1270. X
  1271. X            if (strncmp(s_lab, "#if", 3) == 0)
  1272. X            {
  1273. X                if (blanklines_around_conditional_compilation)
  1274. X                {
  1275. X                    register c;
  1276. X
  1277. X                    prefix_blankline_requested++;
  1278. X                    while ((c = getc(input)) == '\n');
  1279. X                    ungetc(c, input);
  1280. X                }
  1281. X                if (ifdef_level < sizeof state_stack / sizeof state_stack[0])
  1282. X                {
  1283. X                    match_state[ifdef_level].tos = -1;
  1284. X                    state_stack[ifdef_level++] = ps;
  1285. X                }
  1286. X                else
  1287. X                    diag(1, "#if stack overflow");
  1288. X            }
  1289. X            else if (strncmp(s_lab, "#else", 5) == 0)
  1290. X                if (ifdef_level <= 0)
  1291. X                    diag(1, "Unmatched #else");
  1292. X                else
  1293. X                {
  1294. X                    match_state[ifdef_level - 1] = ps;
  1295. X                    ps = state_stack[ifdef_level - 1];
  1296. X                }
  1297. X            else if (strncmp(s_lab, "#endif", 6) == 0)
  1298. X            {
  1299. X                if (ifdef_level <= 0)
  1300. X                    diag(1, "Unmatched #endif");
  1301. X                else
  1302. X                {
  1303. X                    ifdef_level--;
  1304. X
  1305. X#ifdef undef
  1306. X                    /*
  1307. X                       This match needs to be more intelligent before the
  1308. X                       message is useful
  1309. X                    */
  1310. X                    if (match_state[ifdef_level].tos >= 0
  1311. X                        && bcmp(&ps, &match_state[ifdef_level], sizeof ps))
  1312. X                        diag(0, "Syntactically inconsistant #ifdef alternatives.");
  1313. X#endif
  1314. X                }
  1315. X                if (blanklines_around_conditional_compilation)
  1316. X                {
  1317. X                    postfix_blankline_requested++;
  1318. X                    n_real_blanklines = 0;
  1319. X                }
  1320. X            }
  1321. X            break;                /* subsequent processing of the newline
  1322. X                                   character will cause the line to be printed */
  1323. X
  1324. X        case cc_commnt:        /* we have gotten a //  this is a biggie */
  1325. X        case comment:            /* we have gotten a /*  this is a biggie */
  1326. X
  1327. X            if (flushed_nl)
  1328. X            {                    /* we should force a broken line here */
  1329. X                flushed_nl = false;
  1330. X                dump_line();
  1331. X                ps.want_blank = false;    /* dont insert blank at line start */
  1332. X                force_nl = false;
  1333. X            }
  1334. X            pr_comment();
  1335. X            /*
  1336. X               pr_comment()'s parsing sequence for a C++ comment is quite
  1337. X               different from that for a standard comment and without the next
  1338. X               statement a C++ comment causes the next line to be formatted
  1339. X               with an extra blank space before the code or to be preceded by
  1340. X               an extra blank line.       jrs 12 Mar 92
  1341. X            */
  1342. X            if (type_code == cc_commnt)    /* jrs 12 Mar 92 */
  1343. X                force_nl = ps.want_blank = false;    /* jrs 12 Mar 92 */
  1344. X            break;
  1345. X        }                        /* end of big switch stmt */
  1346. X
  1347. X        *e_code = '\0';            /* make sure code section is null terminated */
  1348. X        if (type_code != comment && type_code != newline && type_code != preesc && type_code != cc_commnt)
  1349. X            ps.last_token = type_code;
  1350. X    }                            /* end of main while (1) loop */
  1351. X};
  1352. X
  1353. X/*
  1354. X * copy input file to backup file if in_name is /blah/blah/blah/file, then
  1355. X * backup file will be ".Bfile" then make the backup file the input and
  1356. X * original input file the output
  1357. X */
  1358. X#ifdef ANSIC
  1359. Xstatic void bakcopy(void)
  1360. X#else
  1361. Xbakcopy()
  1362. X#endif
  1363. X{
  1364. X#ifdef MSDOS                    /* or OS/2 */
  1365. X    int fat = 0;                /* File system type = FAT? */
  1366. X    char *q;
  1367. X
  1368. X#endif
  1369. X    int n, bakchn;
  1370. X
  1371. X/*  char        buff[8 * 1024];        Ouch!  Such a big stack!
  1372. X    Let's allocate a buffer from the heap instead .... jrs 12 Mar 92 */
  1373. X
  1374. X    char *buff;
  1375. X
  1376. X# define COPY_BUFFER_SIZE 8*1024
  1377. X    register char *p;
  1378. X
  1379. X    if ((buff = (char *)malloc(COPY_BUFFER_SIZE)) == NULL)
  1380. X    {
  1381. X        fprintf(stderr, "indent: no memory for backup file copy buffer");
  1382. X        exit(1);
  1383. X    }
  1384. X
  1385. X    /* construct file name .Bfile */
  1386. X
  1387. X#ifdef MSDOS                    /* or OS/2 */
  1388. X# ifndef M_I386                    /* then must be OS/2 1.x or MSDOS */
  1389. X#   define DosQueryFSAttach(a,b,c,d,e) DosQFSAttach(a,b,c,(BYTE *)d,e,0L)
  1390. X#   define DosQueryCurrentDisk DosQCurDisk
  1391. X#   define PARAM_T USHORT
  1392. X
  1393. X    DosGetMachineMode(&buff[0]);
  1394. X    if (buff[0] == MODE_REAL)    /* DOS can only handle FAT */
  1395. X        fat = 1;
  1396. X# else
  1397. X#   define PARAM_T ULONG
  1398. X# endif
  1399. X
  1400. X    if (!fat)
  1401. X    {
  1402. X        PARAM_T DriveNumber, cbData;
  1403. X        ULONG DriveMap;
  1404. X        struct fsqb
  1405. X        {
  1406. X# ifdef M_I386
  1407. X            FSQBUFFER2 bData;
  1408. X# else
  1409. X            FSQBUFFER bData;
  1410. X# endif
  1411. X            BYTE filler[60];
  1412. X        }
  1413. X            fsq;
  1414. X
  1415. X        cbData = sizeof fsq;
  1416. X        if (isalpha(in_name[0]) && in_name[1] == ':')
  1417. X            DriveNumber = toupper(in_name[0]) - '@';
  1418. X        else
  1419. X            DosQueryCurrentDisk(&DriveNumber, &DriveMap);
  1420. X
  1421. X        if (DosQueryFSAttach(NULL, DriveNumber, FSAIL_DRVNUMBER,
  1422. X                             &fsq.bData, &cbData))
  1423. X            fat = 0;
  1424. X        else
  1425. X            fat = !strcmp(&fsq.bData.szFSDName[fsq.bData.cbName], "FAT");
  1426. X    }
  1427. X
  1428. X    for (p = strcpy(bakfile, in_name); *p; ++p);    /* skip to end of string */
  1429. X    while (p > bakfile && *p != '/' && *p != '\\')
  1430. X        p--;
  1431. X    if (*p == '/' || *p == '\\')
  1432. X        p++;
  1433. X    if (fat && (q = strchr(p, '.')) != NULL)
  1434. X        *q = '\0';
  1435. X    strcat(bakfile, ".BAK");
  1436. X
  1437. X#else                            /* it isn't MSDOS or OS/2 */
  1438. X
  1439. X    for (p = in_name; *p; p++);    /* skip to end of string */
  1440. X    while (p > in_name && *p != '/')    /* find last '/' */
  1441. X        p--;
  1442. X    if (*p == '/')
  1443. X        p++;
  1444. X
  1445. X    sprintf(bakfile, "%s.BAK", p);
  1446. X
  1447. X#endif
  1448. X
  1449. X    /* copy in_name to backup file */
  1450. X    bakchn = creat(bakfile, 0600);
  1451. X    if (bakchn < 0)
  1452. X    {
  1453. X        fprintf(stderr, "indent: can't create backup file \"%s\"\n", bakfile);
  1454. X        exit(1);
  1455. X    }
  1456. X    while (n = read(fileno(input), buff, COPY_BUFFER_SIZE))
  1457. X        if (write(bakchn, buff, n) != n)
  1458. X        {
  1459. X            fprintf(stderr, "indent: error writing backup file \"%s\"\n",
  1460. X                    bakfile);
  1461. X            exit(1);
  1462. X        }
  1463. X    if (n < 0)
  1464. X    {
  1465. X        fprintf(stderr, "indent: error reading input file \"%s\"\n", in_name);
  1466. X        exit(1);
  1467. X    }
  1468. X    close(bakchn);
  1469. X    fclose(input);
  1470. X
  1471. X    free(buff);
  1472. X
  1473. X    /* re-open backup file as the input file */
  1474. X    input = fopen(bakfile, "r");
  1475. X    if (input == NULL)
  1476. X    {
  1477. X        fprintf(stderr, "indent: can't re-open backup file\n");
  1478. X        exit(1);
  1479. X    }
  1480. X    /* now the original input file will be the output */
  1481. X    output = fopen(in_name, "w");
  1482. X    if (output == NULL)
  1483. X    {
  1484. X        fprintf(stderr, "indent: can't create %s\n", in_name);
  1485. X        unlink(bakfile);
  1486. X        exit(1);
  1487. X    }
  1488. X}
  1489. SHAR_EOF
  1490. if test 40490 -ne "`wc -c indent.c`"
  1491. then
  1492. echo shar: error transmitting indent.c '(should have been 40490 characters)'
  1493. fi
  1494. echo shar: extracting io.c
  1495. sed 's/^X//' << \SHAR_EOF > io.c
  1496. X/*
  1497. X * Copyright 1989 Object Design, Inc.
  1498. X * Copyright (c) 1985 Sun Microsystems, Inc.
  1499. X * Copyright (c) 1980 The Regents of the University of California.
  1500. X * Copyright (c) 1976 Board of Trustees of the University of Illinois.
  1501. X * All rights reserved.
  1502. X *
  1503. X * Redistribution and use in source and binary forms are permitted
  1504. X * provided that the above copyright notice and this paragraph are
  1505. X * duplicated in all such forms and that any documentation,
  1506. X * advertising materials, and other materials related to such
  1507. X * distribution and use acknowledge that the software was developed
  1508. X * by the University of California, Berkeley, the University of Illinois,
  1509. X * Urbana, and Sun Microsystems, Inc.  The name of either University
  1510. X * or Sun Microsystems may not be used to endorse or promote products
  1511. X * derived from this software without specific prior written permission.
  1512. X * THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
  1513. X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  1514. X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  1515. X */
  1516. X
  1517. X#ifndef lint
  1518. Xstatic char sccsid[] = "@(#)io.c    5.10 (Berkeley) 88/09/15";
  1519. X
  1520. X#endif                            /* not lint */
  1521. X
  1522. X#include "globals.h"
  1523. X#include <ctype.h>
  1524. X
  1525. X#ifdef MSDOS                    /* or OS/2 */
  1526. X#include <string.h>
  1527. X#include <process.h>
  1528. X#define bzero(achBuf, cbLength) memset(achBuf, 0, cbLength)
  1529. X#endif
  1530. X
  1531. Xint comment_open;
  1532. Xstatic paren_target;
  1533. X
  1534. X#ifdef ANSIC
  1535. X#include <stdarg.h>
  1536. Xstatic int pad_output(int, int);
  1537. X
  1538. X#endif
  1539. X
  1540. X#ifdef ANSIC
  1541. Xvoid dump_line(void)
  1542. X#else
  1543. Xdump_line(void)
  1544. X#endif
  1545. X{                                /* dump_line is the routine that actually
  1546. X                                   effects the printing of the new source. It
  1547. X                                   prints the label section, followed by the
  1548. X                                   code section with the appropriate nesting
  1549. X                                   level, followed by any comments */
  1550. X    register int cur_col, target_col;
  1551. X    static not_first_line;
  1552. X
  1553. X    if (ps.procname[0])
  1554. X    {
  1555. X        if (troff)
  1556. X        {
  1557. X            if (comment_open)
  1558. X            {
  1559. X                comment_open = 0;
  1560. X                fprintf(output, ".*/\n");
  1561. X            }
  1562. X            fprintf(output, ".Pr \"%s\"\n", ps.procname);
  1563. X        }
  1564. X        ps.ind_level = 0;
  1565. X        ps.procname[0] = 0;
  1566. X    }
  1567. X    if (s_code == e_code && s_lab == e_lab && s_com == e_com)
  1568. X    {
  1569. X        if (suppress_blanklines > 0)
  1570. X            suppress_blanklines--;
  1571. X        else
  1572. X        {
  1573. X            ps.bl_line = true;
  1574. X            n_real_blanklines++;
  1575. X        }
  1576. X    }
  1577. X    else if (!inhibit_formatting)
  1578. X    {
  1579. X        suppress_blanklines = 0;
  1580. X        ps.bl_line = false;
  1581. X        if (prefix_blankline_requested && not_first_line)
  1582. X            if (swallow_optional_blanklines)
  1583. X            {
  1584. X                if (n_real_blanklines == 1)
  1585. X                    n_real_blanklines = 0;
  1586. X            }
  1587. X            else
  1588. X            {
  1589. X                if (n_real_blanklines == 0)
  1590. X                    n_real_blanklines = 1;
  1591. X            }
  1592. X        while (--n_real_blanklines >= 0)
  1593. X            putc('\n', output);
  1594. X        n_real_blanklines = 0;
  1595. X        if (ps.ind_level == 0)
  1596. X        {
  1597. X            if (!btype_3)
  1598. X                ps.ind_stmt = 0;/* this is a class A kludge. dont do additional
  1599. X                                   statement indentation if we are at bracket
  1600. X                                   level 0 */
  1601. X            else if (*s_code != '{')
  1602. X                ps.ind_stmt = 0;/* this one is a class AA kludge: defeat the
  1603. X                                   class A kludge if the statement is '{' */
  1604. X        }
  1605. X
  1606. X        if (e_lab != s_lab || e_code != s_code)
  1607. X            ++code_lines;        /* keep count of lines with code */
  1608. X
  1609. X
  1610. X        if (e_lab != s_lab)
  1611. X        {                        /* print lab, if any */
  1612. X            if (comment_open)
  1613. X            {
  1614. X                comment_open = 0;
  1615. X                fprintf(output, ".*/\n");
  1616. X            }
  1617. X            while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t'))
  1618. X                e_lab--;
  1619. X            cur_col = pad_output(1, compute_label_target());
  1620. X            fprintf(output, "%.*s", e_lab - s_lab, s_lab);
  1621. X            cur_col = count_spaces(cur_col, s_lab);
  1622. X        }
  1623. X        else
  1624. X            cur_col = 1;        /* there is no label section */
  1625. X
  1626. X        ps.pcase = false;
  1627. X
  1628. X        if (s_code != e_code)
  1629. X        {                        /* print code section, if any */
  1630. X            register char *p;
  1631. X
  1632. X            if (comment_open)
  1633. X            {
  1634. X                comment_open = 0;
  1635. X                fprintf(output, ".*/\n");
  1636. X            }
  1637. X            target_col = compute_code_target();
  1638. X            {
  1639. X                register i;
  1640. X
  1641. X                for (i = 0; i < ps.p_l_follow; i++)
  1642. X                    if (ps.paren_indents[i] >= 0)
  1643. X                        ps.paren_indents[i] = -(short) (ps.paren_indents[i] + target_col);
  1644. X            }
  1645. X            cur_col = pad_output(cur_col, target_col);
  1646. X            for (p = s_code; p < e_code; p++)
  1647. X                if (*p == (char) 0200)
  1648. X                    fprintf(output, "%d", target_col * 7);
  1649. X                else
  1650. X                    putc(*p, output);
  1651. X            cur_col = count_spaces(cur_col, s_code);
  1652. X        }
  1653. X        if (s_com != e_com)
  1654. X            if (troff)
  1655. X            {
  1656. X                int all_here = 0;
  1657. X                register char *p;
  1658. X
  1659. X                if (ps.cc_comment)
  1660. X                    all_here++;
  1661. X                else if (e_com[-1] == '/' && e_com[-2] == '*')
  1662. X                    e_com -= 2, all_here++;
  1663. X                while (e_com > s_com && e_com[-1] == ' ')
  1664. X                    e_com--;
  1665. X                *e_com = 0;
  1666. X                p = s_com;
  1667. X                while (*p == ' ')
  1668. X                    p++;
  1669. X                if (p[0] == '/' && (p[1] == '*' || p[1] == '/'))
  1670. X                    p += 2, all_here++;
  1671. X                else if (p[0] == '*')
  1672. X                    p += p[1] == '/' ? 2 : 1;
  1673. X                while (*p == ' ')
  1674. X                    p++;
  1675. X                if (*p == 0)
  1676. X                    goto inhibit_newline;
  1677. X                if (comment_open < 2 && ps.box_com)
  1678. X                {
  1679. X                    comment_open = 0;
  1680. X                    fprintf(output, ".*/\n");
  1681. X                }
  1682. X                if (comment_open == 0)
  1683. X                {
  1684. X                    if ('a' <= *p && *p <= 'z')
  1685. X                        *p += 'A' - 'a';
  1686. X                    if (e_com - p < 50 && all_here == 2)
  1687. X                    {
  1688. X                        register char *follow = p;
  1689. X
  1690. X                        fprintf(output, "\n.nr C! \\w\1");
  1691. X                        while (follow < e_com)
  1692. X                        {
  1693. X                            switch (*follow)
  1694. X                            {
  1695. X                            case '\n':
  1696. X                                putc(' ', output);
  1697. X                            case 1:
  1698. X                                break;
  1699. X                            case '\\':
  1700. X                                putc('\\', output);
  1701. X                            default:
  1702. X                                putc(*follow, output);
  1703. X                            }
  1704. X                            follow++;
  1705. X                        }
  1706. X                        putc(1, output);
  1707. X                    }
  1708. X                    fprintf(output, "\n./* %dp %d %dp\n",
  1709. X                            ps.com_col * 7,
  1710. X                            (s_code != e_code || s_lab != e_lab) - ps.box_com,
  1711. X                            target_col * 7);
  1712. X                }
  1713. X                comment_open = 1 + ps.box_com;
  1714. X                while (*p)
  1715. X                {
  1716. X                    if (*p == BACKSLASH)
  1717. X                        putc(BACKSLASH, output);
  1718. X                    putc(*p++, output);
  1719. X                }
  1720. X            }
  1721. X            else
  1722. X            {                    /* print comment, if any */
  1723. X                register target = ps.com_col;
  1724. X                register char *com_st = s_com;
  1725. X
  1726. X                target += ps.comment_delta;
  1727. X                while (*com_st == '\t')
  1728. X                    com_st++, target += tabsize;    /* JHT 22oct89 */
  1729. X                while (target <= 0)
  1730. X                    if (*com_st == ' ')
  1731. X                        target++, com_st++;
  1732. X                    else if (*com_st == '\t')
  1733. X                    {
  1734. X                        target += (tabsize - ((target - 1) % tabsize));    /* JHT 22oct89 */
  1735. X                        com_st++;
  1736. X                    }
  1737. X                    else
  1738. X                        target = 1;
  1739. X                if (cur_col > target)
  1740. X                {                /* if comment cant fit on this line, put it on
  1741. X                                   next line */
  1742. X                    putc('\n', output);
  1743. X                    cur_col = 1;
  1744. X                    ++ps.out_lines;
  1745. X                }
  1746. X                while (e_com > com_st && isspace(e_com[-1]))
  1747. X                    e_com--;
  1748. X                cur_col = pad_output(cur_col, target);
  1749. X                if (!ps.box_com && !ps.cc_comment)
  1750. X                {
  1751. X                    if (star_comment_cont && (com_st[1] != '*' || e_com <= com_st + 1))
  1752. X                        if (com_st[1] == ' ' && com_st[0] == ' ' && e_com > com_st + 1)
  1753. X                            com_st[1] = '*';
  1754. X                        else
  1755. X                            fwrite(" * ", com_st[0] == '\t' ? 2 : com_st[0] == '*' ? 1 : 3, 1, output);
  1756. X                }
  1757. X                fwrite(com_st, e_com - com_st, 1, output);
  1758. X                ps.comment_delta = ps.n_comment_delta;
  1759. X                cur_col = count_spaces(cur_col, com_st);
  1760. X                ++ps.com_lines;    /* count lines with comments */
  1761. X            }
  1762. X        if (ps.use_ff)
  1763. X            putc('\014', output);
  1764. X        else
  1765. X            putc('\n', output);
  1766. Xinhibit_newline:
  1767. X        ++ps.out_lines;
  1768. X        if (ps.just_saw_decl == 1 && blanklines_after_declarations)
  1769. X        {
  1770. X            prefix_blankline_requested = 1;
  1771. X            ps.just_saw_decl = 0;
  1772. X        }
  1773. X        else
  1774. X            prefix_blankline_requested = postfix_blankline_requested;
  1775. X        postfix_blankline_requested = 0;
  1776. X    }
  1777. X    ps.decl_on_line = ps.in_decl;    /* if we are in the middle of a
  1778. X                                       declaration, remember that fact for
  1779. X                                       proper comment indentation */
  1780. X    ps.ind_stmt = ps.in_stmt & ~ps.in_decl;    /* next line should be indented if
  1781. X                                               we have not completed this stmt
  1782. X                                               and if we are not in the middle
  1783. X                                               of a declaration */
  1784. X    ps.use_ff = false;
  1785. X    ps.dumped_decl_indent = 0;
  1786. X    *(e_lab = s_lab) = '\0';    /* reset buffers */
  1787. X    *(e_code = s_code) = '\0';
  1788. X    *(e_com = s_com) = '\0';
  1789. X    ps.ind_level = ps.i_l_follow;
  1790. X    ps.paren_level = ps.p_l_follow;
  1791. X    paren_target = -ps.paren_indents[ps.paren_level - 1];
  1792. X    not_first_line = 1;
  1793. X    return;
  1794. X};
  1795. X
  1796. X#ifdef ANSIC
  1797. Xint compute_code_target(void)
  1798. X#else
  1799. Xcompute_code_target()
  1800. X#endif
  1801. X{
  1802. X    register target_col = ps.ind_size * ps.ind_level + 1;
  1803. X
  1804. X    if (ps.paren_level)
  1805. X        if (!lineup_to_parens)
  1806. X            target_col += continuation_indent * ps.paren_level;
  1807. X        else
  1808. X        {
  1809. X            register w;
  1810. X            register t = paren_target;
  1811. X
  1812. X            if ((w = count_spaces(t, s_code) - max_col) > 0
  1813. X                && count_spaces(target_col, s_code) <= max_col)
  1814. X            {
  1815. X                t -= w + 1;
  1816. X                if (t > target_col)
  1817. X                    target_col = t;
  1818. X            }
  1819. X            else
  1820. X                target_col = t;
  1821. X        }
  1822. X    else if (ps.ind_stmt)
  1823. X        target_col += continuation_indent;
  1824. X    return target_col;
  1825. X}
  1826. X
  1827. X#ifdef ANSIC
  1828. Xint compute_label_target(void)
  1829. X#else
  1830. Xcompute_label_target()
  1831. X#endif
  1832. X{
  1833. X    return
  1834. X        ps.pcase ?
  1835. X        (cplus && ps.in_decl) ? cplus_ppp_indent
  1836. X        : (int) (case_ind * ps.ind_size) + 1
  1837. X        : *s_lab == '#' ? 1
  1838. X        : ps.ind_size * (ps.ind_level - label_offset) + 1;
  1839. X}
  1840. X
  1841. X
  1842. X/*
  1843. X * Copyright (C) 1976 by the Board of Trustees of the University of Illinois
  1844. X *
  1845. X * All rights reserved
  1846. X *
  1847. X *
  1848. X * NAME: fill_buffer
  1849. X *
  1850. X * FUNCTION: Reads one block of input into input_buffer
  1851. X *
  1852. X * HISTORY: initial coding     November 1976    D A Willcox of CAC 1/7/77 A
  1853. X * Willcox of CAC    Added check for switch back to partly full input
  1854. X * buffer from temporary buffer
  1855. X *
  1856. X */
  1857. X#ifdef ANSIC
  1858. Xvoid fill_buffer(void)
  1859. X#else
  1860. Xfill_buffer()
  1861. X#endif
  1862. X{                                /* this routine reads stuff from the input */
  1863. X    register char *p;
  1864. X    register int i;
  1865. X    register FILE *f = input;
  1866. X
  1867. X    if (bp_save != 0)
  1868. X    {                            /* there is a partly filled input buffer left */
  1869. X        buf_ptr = bp_save;        /* dont read anything, just switch buffers */
  1870. X        buf_end = be_save;
  1871. X        bp_save = be_save = 0;
  1872. X        if (buf_ptr < buf_end)
  1873. X            return;                /* only return if there is really something in
  1874. X                                   this buffer */
  1875. X    }
  1876. X    for (p = buf_ptr = in_buffer; p < &in_buffer[inp_bufs];)
  1877. X    {
  1878. X        if ((i = getc(f)) == EOF)
  1879. X        {
  1880. X            *p++ = ' ';
  1881. X            *p++ = '\n';
  1882. X            if (p >= &in_buffer[inp_bufs])
  1883. X            {
  1884. X                diag (1, "Internal buffer overflow - Line is too long.");
  1885. X                fflush (output);
  1886. X                exit (1);
  1887. X            }
  1888. X            had_eof = true;
  1889. X            break;
  1890. X        }
  1891. X        *p++ = (char) i;
  1892. X        if (i == '\n')
  1893. X            break;
  1894. X    }
  1895. X    buf_end = p;
  1896. X    if (p[-2] == '/' && p[-3] == '*')
  1897. X    {
  1898. X        if (in_buffer[3] == 'I' && strncmp(in_buffer, "/**INDENT**", 11) == 0)
  1899. X            fill_buffer();        /* flush indent error message */
  1900. X        else
  1901. X        {
  1902. X            int com = 0;
  1903. X
  1904. X            p = in_buffer;
  1905. X            while (*p == ' ' || *p == '\t')
  1906. X                p++;
  1907. X            if (*p == '/' && p[1] == '*')
  1908. X            {
  1909. X                p += 2;
  1910. X                while (*p == ' ' || *p == '\t')
  1911. X                    p++;
  1912. X                if (p[0] == 'I' && p[1] == 'N' && p[2] == 'D' && p[3] == 'E'
  1913. X                    && p[4] == 'N' && p[5] == 'T')
  1914. X                {
  1915. X                    p += 6;
  1916. X                    if (*p == ':')
  1917. X                    {
  1918. X#define MAX_SOURCE_ARG 100
  1919. X                        char argbuf[MAX_SOURCE_ARG];    /* how big can they get
  1920. X                                                           ...  */
  1921. X                        char *a;
  1922. X
  1923. X                        p++;    /* skip the : */
  1924. X                        /*
  1925. X                           since set_option changes flags, process pending
  1926. X                           stuff now
  1927. X                        */
  1928. X                        if (s_com != e_com || s_lab != e_lab || s_code != e_code)
  1929. X                            dump_line();
  1930. X                        while (1)
  1931. X                        {
  1932. X                            a = argbuf;    /* accumulate an option */
  1933. X                            while (*p <= ' ')    /* skip whitespace */
  1934. X                                p++;
  1935. X                            if (*p == '*')
  1936. X                                break;
  1937. X                            while (*p > ' ')
  1938. X                                *a++ = *p++;
  1939. X                            *a++ = '\0';
  1940. X                            set_option(argbuf);
  1941. X                        }
  1942. X                        goto End_Magic_Comment;
  1943. X                    }
  1944. X                    while (*p == ' ' || *p == '\t')
  1945. X                        p++;
  1946. X                    if (*p == '*')
  1947. X                        com = 1;
  1948. X                    else if (*p == 'O')
  1949. X                        if (*++p == 'N')
  1950. X                            p++, com = 1;
  1951. X                        else if (*p == 'F' && *++p == 'F')
  1952. X                            p++, com = 2;
  1953. X                    while (*p == ' ' || *p == '\t')
  1954. X                        p++;
  1955. X                    if (p[0] == '*' && p[1] == '/' && p[2] == '\n' && com)
  1956. X                    {
  1957. X                        if (s_com != e_com || s_lab != e_lab || s_code != e_code)
  1958. X                            dump_line();
  1959. X                        if (!(inhibit_formatting = com - 1))
  1960. X                        {
  1961. X                            n_real_blanklines = 0;
  1962. X                            postfix_blankline_requested = 0;
  1963. X                            prefix_blankline_requested = 0;
  1964. X                            suppress_blanklines = 1;
  1965. X                        }
  1966. X                    }
  1967. X                }
  1968. X            }
  1969. X        }
  1970. X    }
  1971. XEnd_Magic_Comment:
  1972. X    if (inhibit_formatting)
  1973. X    {
  1974. X        p = in_buffer;
  1975. X        do
  1976. X            putc(*p, output);
  1977. X        while (*p++ != '\n');
  1978. X    }
  1979. X    return;
  1980. X};
  1981. X
  1982. X/*
  1983. X * Copyright (C) 1976 by the Board of Trustees of the University of Illinois
  1984. X *
  1985. X * All rights reserved
  1986. X *
  1987. X *
  1988. X * NAME: pad_output
  1989. X *
  1990. X * FUNCTION: Writes tabs and spaces to move the current column up to the desired
  1991. X * position.
  1992. X *
  1993. X * ALGORITHM: Put tabs and/or blanks into pobuf, then write pobuf.
  1994. X *
  1995. X * PARAMETERS: current        integer        The current column target
  1996. X * nteger        The desired column
  1997. X *
  1998. X * RETURNS: Integer value of the new column.  (If current >= target, no action is
  1999. X * taken, and current is returned.
  2000. X *
  2001. X * GLOBALS: None
  2002. X *
  2003. X * CALLS: write (sys)
  2004. X *
  2005. X * CALLED BY: dump_line
  2006. X *
  2007. X * HISTORY: initial coding     November 1976    D A Willcox of CAC
  2008. X *
  2009. X */
  2010. X
  2011. X#ifdef ANSIC
  2012. Xint pad_output(int current, int target)
  2013. X#else
  2014. Xpad_output(current, target)
  2015. X    int current;                /* the current column value */
  2016. X    int target;                    /* position we want it at */
  2017. X
  2018. X#endif
  2019. X /*
  2020. X    writes tabs and blanks (if necessary) to get the current output position up
  2021. X    to the target column
  2022. X */
  2023. X{
  2024. X    register int tstop;            /* Current tab stop being visited */
  2025. X
  2026. X    if (troff)
  2027. X        fprintf(output, "\\h'|%dp'", (target - 1) * 7);
  2028. X    else
  2029. X    {
  2030. X        if (current >= target)
  2031. X            return (current);    /* line is already long enough */
  2032. X        /* Compute where next tab stop lies: */
  2033. X
  2034. X        tstop = current + tabsize - ((current - 1) % tabsize);
  2035. X
  2036. X        for (; tstop <= target; tstop += tabsize)
  2037. X            putc('\t', output);    /* Tab to each tabstop */
  2038. X
  2039. X        tstop -= tabsize;        /* Account for overshoot */
  2040. X
  2041. X        while (tstop++ < target)
  2042. X            putc(' ', output);    /* Space over to where we want to be */
  2043. X    }
  2044. X    return (target);
  2045. X};
  2046. X
  2047. X/*
  2048. X * Copyright (C) 1976 by the Board of Trustees of the University of Illinois
  2049. X *
  2050. X * All rights reserved
  2051. X *
  2052. X *
  2053. X * NAME: count_spaces
  2054. X *
  2055. X * FUNCTION: Find out where printing of a given string will leave the current
  2056. X * character position on output.
  2057. X *
  2058. X * ALGORITHM: Run thru input string and add appropriate values to current
  2059. X * position.
  2060. X *
  2061. X * RETURNS: Integer value of position after printing "buffer" starting in column
  2062. X * "current".
  2063. X *
  2064. X * HISTORY: initial coding     November 1976    D A Willcox of CAC
  2065. X *
  2066. X */
  2067. X
  2068. X#ifdef ANSIC
  2069. Xint count_spaces(int current, char *buffer)
  2070. X#else
  2071. Xint count_spaces(current, buffer)
  2072. X    int current;
  2073. X    char *buffer;
  2074. X
  2075. X#endif
  2076. X/*
  2077. X * this routine figures out where the character position will be after
  2078. X * printing the text in buffer starting at column "current"
  2079. X */
  2080. X{
  2081. X    register char *buf;            /* used to look thru buffer */
  2082. X    register int cur;            /* current character counter */
  2083. X
  2084. X    cur = current;
  2085. X
  2086. X    for (buf = buffer; *buf != '\0'; ++buf)
  2087. X    {
  2088. X        switch (*buf)
  2089. X        {
  2090. X
  2091. X        case '\n':
  2092. X        case 014:                /* form feed */
  2093. X            cur = 1;
  2094. X            break;
  2095. X
  2096. X        case '\t':
  2097. X            cur = cur + (tabsize - ((cur - 1) % tabsize));
  2098. X            break;
  2099. X
  2100. X        case '\b':                /* this is a backspace */
  2101. X            --cur;
  2102. X            break;
  2103. X
  2104. X        default:
  2105. X            ++cur;
  2106. X            break;
  2107. X        }                        /* end of switch */
  2108. X    }                            /* end of for loop */
  2109. X    return (cur);
  2110. X};
  2111. X
  2112. Xint found_err;
  2113. X
  2114. X#ifdef ANSIC
  2115. Xvoid diag(int level, char *msg,...)
  2116. X{
  2117. X    va_list
  2118. X        a;
  2119. X
  2120. X    va_start(a, msg);
  2121. X    if (level)
  2122. X        found_err = 1;
  2123. X    if (output == stdout)
  2124. X    {
  2125. X        fprintf(stdout, "/**INDENT** %s@%d: ", level == 0 ? "Warning" : "Error", line_no);
  2126. X        vfprintf(stdout, msg, a);
  2127. X        fprintf(stdout, " */\n");
  2128. X    }
  2129. X    else
  2130. X    {
  2131. X        fprintf(stderr, "%s@%d: ", level == 0 ? "Warning" : "Error", line_no);
  2132. X        vfprintf(stderr, msg, a);
  2133. X        fprintf(stderr, "\n");
  2134. X    }
  2135. X}
  2136. X
  2137. X#else
  2138. Xdiag(level, msg, a, b)
  2139. X{
  2140. X    if (level)
  2141. X        found_err = 1;
  2142. X    if (output == stdout)
  2143. X    {
  2144. X        fprintf(stdout, "/**INDENT** %s@%d: ", level == 0 ? "Warning" : "Error", line_no);
  2145. X        fprintf(stdout, msg, a, b);
  2146. X        fprintf(stdout, " */\n");
  2147. X    }
  2148. X    else
  2149. X    {
  2150. X        fprintf(stderr, "%s@%d: ", level == 0 ? "Warning" : "Error", line_no);
  2151. X        fprintf(stderr, msg, a, b);
  2152. X        fprintf(stderr, "\n");
  2153. X    }
  2154. X}
  2155. X
  2156. X#endif
  2157. X
  2158. X#ifdef ANSIC
  2159. Xvoid writefdef(struct fstate * f, int nm)
  2160. X#else
  2161. Xwritefdef(f, nm)
  2162. X    register struct fstate *f;
  2163. X
  2164. X#endif
  2165. X{
  2166. X    fprintf(output, ".ds f%c %s\n.nr s%c %d\n",
  2167. X            nm, f->font, nm, f->size);
  2168. X}
  2169. X
  2170. X#ifdef ANSIC
  2171. Xchar *chfont(struct fstate * of, struct fstate * nf, char *s)
  2172. X#else
  2173. Xchar *
  2174. X    chfont(of, nf, s)
  2175. X    register struct fstate *of, *nf;
  2176. X    char *s;
  2177. X
  2178. X#endif
  2179. X{
  2180. X    if (of->font[0] != nf->font[0]
  2181. X        || of->font[1] != nf->font[1])
  2182. X    {
  2183. X        *s++ = '\\';
  2184. X        *s++ = 'f';
  2185. X        if (nf->font[1])
  2186. X        {
  2187. X            *s++ = '(';
  2188. X            *s++ = nf->font[0];
  2189. X            *s++ = nf->font[1];
  2190. X        }
  2191. X        else
  2192. X            *s++ = nf->font[0];
  2193. X    }
  2194. X    if (nf->size != of->size)
  2195. X    {
  2196. X        *s++ = '\\';
  2197. X        *s++ = 's';
  2198. X        if (nf->size < of->size)
  2199. X        {
  2200. X            *s++ = '-';
  2201. X            *s++ = (char) ('0' + of->size - nf->size);
  2202. X        }
  2203. X        else
  2204. X        {
  2205. X            *s++ = '+';
  2206. X            *s++ = (char) ('0' + nf->size - of->size);
  2207. X        }
  2208. X    }
  2209. X    return s;
  2210. X}
  2211. X
  2212. X#ifdef ANSIC
  2213. Xvoid parsefont(register struct fstate * f, char *s0)
  2214. X#else
  2215. Xparsefont(f, s0)
  2216. X    register struct fstate *f;
  2217. X    char *s0;
  2218. X
  2219. X#endif
  2220. X{
  2221. X    register char *s = s0;
  2222. X    int sizedelta = 0;
  2223. X
  2224. X    bzero(f, sizeof *f);
  2225. X    while (*s)
  2226. X    {
  2227. X        if (isdigit(*s))
  2228. X            f->size = (char) (f->size * 10 + *s - '0');
  2229. X        else if (isupper(*s))
  2230. X            if (f->font[0])
  2231. X                f->font[1] = *s;
  2232. X            else
  2233. X                f->font[0] = *s;
  2234. X        else if (*s == 'c')
  2235. X            f->allcaps = 1;
  2236. X        else if (*s == '+')
  2237. X            sizedelta++;
  2238. X        else if (*s == '-')
  2239. X            sizedelta--;
  2240. X        else
  2241. X        {
  2242. X            fprintf(stderr, "indent: bad font specification: %s\n", s0);
  2243. X            exit(1);
  2244. X        }
  2245. X        s++;
  2246. X    }
  2247. X    if (f->font[0] == 0)
  2248. X        f->font[0] = 'R';
  2249. X    if (bodyf.size == 0)
  2250. X        bodyf.size = 11;
  2251. X    if (f->size == 0)
  2252. X        f->size = (char) (bodyf.size + sizedelta);
  2253. X    else if (sizedelta > 0)
  2254. X        f->size += bodyf.size;
  2255. X    else
  2256. X        f->size = bodyf.size - f->size;
  2257. X}
  2258. SHAR_EOF
  2259. if test 17143 -ne "`wc -c io.c`"
  2260. then
  2261. echo shar: error transmitting io.c '(should have been 17143 characters)'
  2262. fi
  2263. #    End of shell archive
  2264. exit 0
  2265.