home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume30 / indent / part02 < prev    next >
Encoding:
Text File  |  1992-07-05  |  59.5 KB  |  1,564 lines

  1. Newsgroups: comp.sources.misc
  2. From: jrs@panix.com (Jon Saxton)
  3. Subject:  v30i096:  indent - C/C++ indent for UNIX, OS/2 and MSDOS, Part02/04
  4. Message-ID: <1992Jul5.190331.26788@sparky.imd.sterling.com>
  5. X-Md4-Signature: 983f6e1abea0cc454ac7b8f075ba377d
  6. Date: Sun, 5 Jul 1992 19:03:31 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: jrs@panix.com (Jon Saxton)
  10. Posting-number: Volume 30, Issue 96
  11. Archive-name: indent/part02
  12. Environment: UNIX, OS/2, MSDOS
  13.  
  14. #! /bin/sh
  15. # This is a shell archive.  Remove anything before this line, then feed it
  16. # into a shell via "sh file" or similar.  To overwrite existing files,
  17. # type "sh file -c".
  18. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  19. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  20. # Contents:  indent.c indent.def
  21. # Wrapped by kent@sparky on Tue Jun 30 00:01:41 1992
  22. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  23. echo If this archive is complete, you will see the following message:
  24. echo '          "shar: End of archive 2 (of 4)."'
  25. if test -f 'indent.c' -a "${1}" != "-c" ; then 
  26.   echo shar: Will not clobber existing file \"'indent.c'\"
  27. else
  28.   echo shar: Extracting \"'indent.c'\" \(57244 characters\)
  29.   sed "s/^X//" >'indent.c' <<'END_OF_FILE'
  30. X/*
  31. X * Copyright 1989 Object Design, Inc.
  32. X * Copyright (c) 1985 Sun Microsystems, Inc.
  33. X * Copyright (c) 1980 The Regents of the University of California.
  34. X * Copyright (c) 1976 Board of Trustees of the University of Illinois.
  35. X * All rights reserved.
  36. X *
  37. X * Redistribution and use in source and binary forms are permitted
  38. X * provided that the above copyright notice and this paragraph are
  39. X * duplicated in all such forms and that any documentation,
  40. X * advertising materials, and other materials related to such
  41. X * distribution and use acknowledge that the software was developed
  42. X * by the University of California, Berkeley, the University of Illinois,
  43. X * Urbana, and Sun Microsystems, Inc.  The name of either University
  44. X * or Sun Microsystems may not be used to endorse or promote products
  45. X * derived from this software without specific prior written permission.
  46. X * THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
  47. X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  48. X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  49. X */
  50. X
  51. X#ifndef lint
  52. X# ifndef OS2
  53. Xchar copyright[] =
  54. X"@(#) Copyright 1989 Object Design, Inc.\n\
  55. X @(#) Copyright (c) 1985 Sun Microsystems, Inc.\n\
  56. X @(#) Copyright (c) 1980 The Regents of the University of California.\n\
  57. X @(#) Copyright (c) 1976 Board of Trustees of the University of Illinois.\n\
  58. X All rights reserved.\n";
  59. X
  60. X    static char sccsid[] = "@(#)indent.c    6.0 (Berkeley) 92/06/15";
  61. X# endif
  62. X#endif                          /* not lint */
  63. X
  64. X#include "globals.h"
  65. X#include "codes.h"
  66. X
  67. X#ifdef OS2                      /* or MSDOS */
  68. X#include <malloc.h>
  69. X#include <stdlib.h>
  70. X#include <process.h>
  71. X#include <string.h>
  72. X#include <io.h>
  73. X#define R_OK 4
  74. X#define INCL_NOPM
  75. X#define INCL_NOPMAPI
  76. X#define INCL_BASE
  77. X#define INCL_DOSFILEMGR
  78. X#include <os2.h>
  79. X#define MAXPATHLEN CCHMAXPATH
  80. X#else                           /* not OS/2 or MSDOS */
  81. X#include <sys/param.h>
  82. X#include <unistd.h>
  83. X#endif                          /* BSD */
  84. X
  85. X#include <ctype.h>
  86. X
  87. Xchar *in_name = "Standard Input"; /* will always point to name of input file */
  88. Xchar *out_name = "Standard Output"; /* will always point to name of output file */
  89. Xchar bakfile[MAXPATHLEN] = "";
  90. X
  91. X#ifdef ANSIC
  92. Xstatic void bakcopy(void);
  93. X
  94. X#endif
  95. X
  96. X#ifdef ANSIC
  97. Xvoid main(int argc, char **argv)
  98. X#else
  99. Xmain(argc, argv)
  100. X    int argc;
  101. X    char **argv;
  102. X
  103. X#endif
  104. X{
  105. X
  106. X    extern int found_err;       /* flag set in diag() on error */
  107. X    int dec_ind;                /* current indentation for declarations */
  108. X    int di_stack[20];           /* a stack of structure indentation levels */
  109. X    int flushed_nl;             /* used when buffering up comments to remember
  110. X                                   that a newline was passed over */
  111. X    int force_nl;               /* when true, code must be broken */
  112. X    int hd_type;                /* used to store type of stmt for if (...), for
  113. X                                   (...), etc */
  114. X    register int i;             /* local loop counter */
  115. X    int scase;                  /* set to true when we see a case, so we will
  116. X                                   know what to do with the following colon */
  117. X    int sp_sw;                  /* when true, we are in the expressin of
  118. X                                   if(...), while(...), etc. */
  119. X    int squest;                 /* when this is positive, we have seen a ?
  120. X                                   without the matching : in a <c>?<s>:<s>
  121. X                                   construct */
  122. X    register char *t_ptr;       /* used for copying tokens */
  123. X    int type_code;              /* the type of token, returned by lexi */
  124. X
  125. X    int last_else = 0;          /* true iff last keyword was an else */
  126. X    int ch;                     /* answer to Y/N prompt */
  127. X
  128. X    int just_saw_cc_cmnt = 0;   /* true if // comment was just emitted
  129. X                                   (jrs 8jun92) */
  130. X    /*-----------------------------------------------*\
  131. X    |                INITIALIZATION                   |
  132. X    \*-----------------------------------------------*/
  133. X
  134. X
  135. X    ps.p_stack[0] = stmt;       /* this is the parser's stack */
  136. X    ps.last_nl = true;          /* this is true if the last thing scanned was a
  137. X                                   newline */
  138. X    ps.last_token = semicolon;
  139. X    combuf = (char *) malloc(bufsize);
  140. X    labbuf = (char *) malloc(bufsize);
  141. X    codebuf = (char *) malloc(bufsize);
  142. X    l_com = combuf + bufsize - 5;
  143. X    l_lab = labbuf + bufsize - 5;
  144. X    l_code = codebuf + bufsize - 5;
  145. X    combuf[0] = codebuf[0] = labbuf[0] = ' '; /* set up code, label, and
  146. X                                                 comment buffers */
  147. X    combuf[1] = codebuf[1] = labbuf[1] = '\0';
  148. X    ps.else_if = 1;             /* Default else-if special processing to on */
  149. X    s_lab = e_lab = labbuf + 1;
  150. X    s_code = e_code = codebuf + 1;
  151. X    s_com = e_com = combuf + 1;
  152. X
  153. X    buf_ptr = buf_end = in_buffer;
  154. X    line_no = 1;
  155. X    had_eof = ps.in_decl = ps.decl_on_line = break_comma = false;
  156. X    sp_sw = force_nl = false;
  157. X    ps.in_or_st = false;
  158. X    ps.bl_line = true;
  159. X    dec_ind = 0;
  160. X    di_stack[ps.dec_nest = 0] = 0;
  161. X    ps.want_blank = ps.in_stmt = ps.ind_stmt = false;
  162. X    ps.cc_comment = 0;
  163. X
  164. X
  165. X    scase = ps.pcase = false;
  166. X    squest = 0;
  167. X    sc_end = 0;
  168. X    bp_save = 0;
  169. X    be_save = 0;
  170. X
  171. X    output = NULL;
  172. X
  173. X
  174. X
  175. X    /*--------------------------------------------------*\
  176. X    |                COMMAND LINE SCAN                   |
  177. X    \*--------------------------------------------------*/
  178. X
  179. X#ifdef undef
  180. X    max_col = 78;               /* -l78 */
  181. X    lineup_to_parens = 1;       /* -lp */
  182. X    ps.ljust_decl = 0;          /* -ndj */
  183. X    ps.com_ind = 33;            /* -c33 */
  184. X    star_comment_cont = 1;      /* -sc */
  185. X    ps.ind_size = 8;            /* -i8 */
  186. X    verbose = 0;
  187. X    ps.decl_indent = 16;        /* -di16 */
  188. X    ps.indent_parameters = 1;   /* -ip */
  189. X    ps.decl_com_ind = 0;        /* if this is not set to some positive value by
  190. X                                   an arg, we will set this equal to ps.com_ind */
  191. X    btype_2 = 1;                /* -br */
  192. X    btype_3 = 0;                /* not -brr */
  193. X    cuddle_else = 1;            /* -ce */
  194. X    ps.unindent_displace = 0;   /* -d0 */
  195. X    ps.case_indent = 0;         /* -cli0 */
  196. X    ps.case_code_indent = 1;    /* -cci1 */
  197. X    format_col1_comments = 1;   /* -fc1 */
  198. X    procnames_start_line = 1;   /* -psl */
  199. X    proc_calls_space = 0;       /* -npcs */
  200. X    parens_space = 0;           /* -nprs */
  201. X    comment_delimiter_on_blankline = 1; /* -cdb */
  202. X    ps.leave_comma = 1;         /* -nbc */
  203. X#endif
  204. X
  205. X    for (i = 1; i < argc; ++i)
  206. X        if (strcmp(argv[i], "-npro") == 0)
  207. X            break;
  208. X    set_defaults();
  209. X    if (i >= argc)
  210. X        set_profile();
  211. X
  212. X    for (i = 1; i < argc; ++i)
  213. X    {
  214. X
  215. X        /*
  216. X           look thru args (if any) for changes to defaults
  217. X        */
  218. X        if (argv[i][0] != '-')
  219. X        {                       /* no flag on parameter */
  220. X            if (input == NULL)
  221. X            {                   /* we must have the input file */
  222. X                in_name = argv[i];  /* remember name of input file */
  223. X                input = fopen(in_name, "r");
  224. X                if (input == NULL)
  225. X                {               /* check for open error */
  226. X                    fprintf(stderr, "indent: can't open %s\n", argv[i]);
  227. X                    exit(1);
  228. X                }
  229. X                continue;
  230. X            }
  231. X            else if (output == NULL)
  232. X            {                   /* we have the output file */
  233. X                out_name = argv[i]; /* remember name of output file */
  234. X                if (strcmp(in_name, out_name) == 0)
  235. X                {               /* attempt to overwrite the file */
  236. X                    fprintf(stderr, "indent: input and output files must be different\n");
  237. X                    exit(1);
  238. X                }
  239. X                if (access(out_name, R_OK) == 0)
  240. X                {
  241. X                    fprintf(stderr, "Reformatting input file %s to produce output file %s\n",
  242. X                            in_name, out_name);
  243. X                    fprintf(stderr, "Output file %s exists; overwrite it? ", out_name);
  244. X                    fflush(stderr);
  245. X                    if ((ch = getchar()) != 'y' && ch != 'Y')
  246. X                    {
  247. X                        fprintf(stderr, "indent: can't create %s\n", argv[i]);
  248. X                        exit(1);
  249. X                    }
  250. X                }
  251. X                output = fopen(out_name, "w");
  252. X                if (output == NULL)
  253. X                {               /* check for create error */
  254. X                    fprintf(stderr, "indent: can't create %s\n", argv[i]);
  255. X                    exit(1);
  256. X                }
  257. X                continue;
  258. X            }
  259. X            fprintf(stderr, "indent: unknown parameter: %s\n", argv[i]);
  260. X            exit(1);
  261. X        }
  262. X        else
  263. X            set_option(argv[i]);
  264. X    }                           /* end of for */
  265. X    if (input == NULL)
  266. X    {
  267. X        fprintf(stderr, "indent: usage: indent file [ outfile ] [ options ]\n");
  268. X        exit(1);
  269. X    }
  270. X    /* set -+ mode by default for .C */
  271. X    if (!cplus)                 /* don't bother if explicit */
  272. X    {
  273. X        char *dot;
  274. X
  275. X        dot = in_name + strlen(in_name) - 2;
  276. X        if ((dot > in_name) && (strcmp(dot, ".C") == 0))
  277. X            set_option("-+");
  278. X    }
  279. X
  280. X    if (output == NULL)
  281. X        if (troff)
  282. X            output = stdout;
  283. X        else
  284. X        {
  285. X            out_name = in_name;
  286. X            bakcopy();
  287. X        }
  288. X    if (ps.com_ind <= 1)
  289. X        ps.com_ind = 2;         /* don't put normal comments before column 2 */
  290. X    if (troff)
  291. X    {
  292. X        if (bodyf.font[0] == 0)
  293. X            parsefont(&bodyf, "R");
  294. X        if (scomf.font[0] == 0)
  295. X            parsefont(&scomf, "I");
  296. X        if (blkcomf.font[0] == 0)
  297. X            blkcomf = scomf, blkcomf.size += 2;
  298. X        if (boxcomf.font[0] == 0)
  299. X            boxcomf = blkcomf;
  300. X        if (stringf.font[0] == 0)
  301. X            parsefont(&stringf, "L");
  302. X        if (keywordf.font[0] == 0)
  303. X            parsefont(&keywordf, "B");
  304. X        writefdef(&bodyf, 'B');
  305. X        writefdef(&scomf, 'C');
  306. X        writefdef(&blkcomf, 'L');
  307. X        writefdef(&boxcomf, 'X');
  308. X        writefdef(&stringf, 'S');
  309. X        writefdef(&keywordf, 'K');
  310. X    }
  311. X    if (block_comment_max_col <= 0)
  312. X        block_comment_max_col = max_col;
  313. X    if (ps.decl_com_ind <= 0)   /* if not specified by user, set this */
  314. X        ps.decl_com_ind = ps.ljust_decl ? (ps.com_ind <= 10 ? 2 : ps.com_ind - 8) : ps.com_ind;
  315. X    if (continuation_indent == 0)
  316. X        continuation_indent = ps.ind_size;
  317. X
  318. X    if (tabsize <= 2)           /* If tab spacing is unreasonably small */
  319. X        tabsize = 2;            /* force indent to use spaces instead. */
  320. X    /* pad_output() will test this value. */
  321. X
  322. X    fill_buffer();              /* get first batch of stuff into input buffer */
  323. X
  324. X    parse(semicolon);
  325. X    {
  326. X        register char *p = buf_ptr;
  327. X        register col = 1;
  328. X
  329. X        while (1)
  330. X        {
  331. X            if (*p == ' ')
  332. X                col++;
  333. X            else if (*p == '\t')
  334. X                col += (tabsize - ((col - 1) % tabsize)); /* JHT 22oct89 */
  335. X            else
  336. X                break;
  337. X            p++;
  338. X        };
  339. X        if (col > ps.ind_size)
  340. X            ps.ind_level = ps.i_l_follow = col / ps.ind_size;
  341. X    }
  342. X    if (troff)
  343. X    {
  344. X        register char *p = in_name, *beg = in_name;
  345. X
  346. X        while (*p)
  347. X            if (*p++ == '/')
  348. X                beg = p;
  349. X        fprintf(output, ".Fn \"%s\"\n", beg);
  350. X    }
  351. X    /*
  352. X       START OF MAIN LOOP
  353. X    */
  354. X
  355. X    while (1)
  356. X    {                           /* this is the main loop.  it will go until we
  357. X                                   reach eof */
  358. X        int is_procname;
  359. X
  360. X        type_code = lexi();     /* lexi reads one token.  The actual characters
  361. X                                   read are stored in "token". lexi returns a
  362. X                                   code indicating the type of token */
  363. X        is_procname = ps.procname[0];
  364. X
  365. X        /*
  366. X           The following code moves everything following an if (), while (),
  367. X           else, etc. up to the start of the following stmt to a buffer. This
  368. X           allows proper handling of both kinds of brace placement.
  369. X        */
  370. X
  371. X        flushed_nl = false;
  372. X        while (ps.search_brace)
  373. X        {                       /* if we scanned an if(), while(), etc., we
  374. X                                   might need to copy stuff into a buffer we
  375. X                                   must loop, copying stuff into save_com,
  376. X                                   until we find the start of the stmt which
  377. X                                   follows the if, or whatever */
  378. X            switch (type_code)
  379. X            {
  380. X            case newline:
  381. X                ++line_no;
  382. X                flushed_nl = true;
  383. X            case form_feed:
  384. X                break;          /* form feeds and newlines found here will be
  385. X                                   ignored */
  386. X
  387. X            case lbrace:       /* this is a brace that starts the compound
  388. X                                   stmt */
  389. X                if (sc_end == 0)
  390. X                {               /* ignore buffering if a comment wasn't stored
  391. X                                   up */
  392. X                    ps.search_brace = false;
  393. X                    goto check_type;
  394. X                }
  395. X                /* if (btype_2)        Bug notified by Steve Comen, 16 Mar 92 */
  396. X                {
  397. X                    save_com[0] = '{';  /* we either want to put the brace
  398. X                                           right after the if */
  399. X                    goto sw_buffer; /* go to common code to get out of this
  400. X                                       loop */
  401. X                }
  402. X            case comment:      /* we have a comment, so we must copy it into
  403. X                                   the buffer */
  404. X                if (!flushed_nl || sc_end != 0)
  405. X                {
  406. X                    if (sc_end == 0)
  407. X                    {           /* if this is the first comment, we must set up
  408. X                                   the buffer */
  409. X                        save_com[0] = save_com[1] = ' ';
  410. X                        sc_end = &(save_com[2]);
  411. X                    }
  412. X                    else
  413. X                    {
  414. X                        *sc_end++ = '\n'; /* add newline between comments */
  415. X                        *sc_end++ = ' ';
  416. X                        --line_no;
  417. X                    }
  418. X                    *sc_end++ = '/';  /* copy in start of comment */
  419. X                    *sc_end++ = '*';
  420. X
  421. X                    for (;;)
  422. X                    {           /* loop until we get to the end of the comment */
  423. X                        *sc_end = *buf_ptr++;
  424. X                        if (buf_ptr >= buf_end)
  425. X                            fill_buffer();
  426. X
  427. X                        if (*sc_end++ == '*' && *buf_ptr == '/')
  428. X                            break;  /* we are at end of comment */
  429. X
  430. X                        if (sc_end >= &(save_com[sc_size]))
  431. X                        {       /* check for temp buffer overflow */
  432. X                            diag(1, "Internal buffer overflow - Move big comment from right after if, while, or whatever.");
  433. X                            fflush(output);
  434. X                            exit(1);
  435. X                        }
  436. X                    }
  437. X                    *sc_end++ = '/';  /* add ending slash */
  438. X                    if (++buf_ptr >= buf_end) /* get past / in buffer */
  439. X                        fill_buffer();
  440. X                    break;
  441. X                }
  442. X            case cc_commnt:    /* we have a comment, so we must copy it into
  443. X                                   the buffer */
  444. X                /* C++ comment */
  445. X                if (!flushed_nl || sc_end != 0)
  446. X                {
  447. X                    if (sc_end == 0)
  448. X                    {           /* if this is the first comment, we must set up
  449. X                                   the buffer */
  450. X                        save_com[0] = save_com[1] = ' ';
  451. X                        sc_end = &(save_com[2]);
  452. X                    }
  453. X                    else
  454. X                    {
  455. X                        *sc_end++ = '\n'; /* add newline between comments */
  456. X                        *sc_end++ = ' ';
  457. X                        --line_no;
  458. X                    }
  459. X                    *sc_end++ = '/';  /* copy in start of comment */
  460. X                    *sc_end++ = '/';
  461. X
  462. X                    for (;;)
  463. X                    {           /* loop until we get to the end of the comment */
  464. X                        *sc_end++ = *buf_ptr++;
  465. X                        if (buf_ptr >= buf_end)
  466. X                            fill_buffer();
  467. X
  468. X                        if (*buf_ptr == '\n')
  469. X                            break;  /* we are at end of comment */
  470. X
  471. X                        if (sc_end >= &(save_com[sc_size]))
  472. X                        {       /* check for temp buffer overflow */
  473. X                            diag(1, "Internal buffer overflow - Move big comment from right after if, while, or whatever.");
  474. X                            fflush(output);
  475. X                            exit(1);
  476. X                        }
  477. X                    }
  478. X                    if (++buf_ptr >= buf_end) /* eat '\n' */
  479. X                        fill_buffer();
  480. X                    break;
  481. X                }
  482. X            default:           /* it is the start of a normal statment */
  483. X                if (flushed_nl) /* if we flushed a newline, make sure it is put
  484. X                                   back */
  485. X                    force_nl = true;
  486. X                if (type_code == sp_paren && *token == 'i'
  487. X                    && last_else && ps.else_if
  488. X                    || type_code == sp_nparen && *token == 'e'
  489. X                    && e_code != s_code && e_code[-1] == '}')
  490. X                    force_nl = false;
  491. X
  492. X                if (just_saw_cc_cmnt)           /* jrs 8jun92 */
  493. X                {                               /* jrs 8jun92 */
  494. X                    force_nl = true;            /* jrs 8jun92 */
  495. X                    just_saw_cc_cmnt = false;   /* jrs 8jun92 */
  496. X                }                               /* jrs 8jun92 */
  497. X
  498. X                if (sc_end == 0)
  499. X                {               /* ignore buffering if comment wasnt saved up */
  500. X                    ps.search_brace = false;
  501. X                    goto check_type;
  502. X                }
  503. X                if (force_nl)
  504. X                {               /* if we should insert a nl here, put it into
  505. X                                   the buffer */
  506. X                    force_nl = false;
  507. X                    --line_no;  /* this will be re-increased when the nl is
  508. X                                   read from the buffer */
  509. X                    *sc_end++ = '\n';
  510. X                    *sc_end++ = ' ';
  511. X                    if (verbose && !flushed_nl) /* print error msg if the line
  512. X                                                   was not already broken */
  513. X                        diag(0, "Line broken");
  514. X                    flushed_nl = false;
  515. X                }
  516. X                for (t_ptr = token; *t_ptr; ++t_ptr)
  517. X                    *sc_end++ = *t_ptr; /* copy token into temp buffer */
  518. X                ps.procname[0] = 0;
  519. X
  520. X        sw_buffer:
  521. X                ps.search_brace = false;  /* stop looking for start of stmt */
  522. X                bp_save = buf_ptr;  /* save current input buffer */
  523. X                be_save = buf_end;
  524. X                buf_ptr = save_com; /* fix so that subsequent calls to lexi
  525. X                                       will take tokens out of save_com */
  526. X                *sc_end++ = ' ';/* add trailing blank, just in case */
  527. X                buf_end = sc_end;
  528. X                sc_end = 0;
  529. X                break;
  530. X            }                   /* end of switch */
  531. X
  532. X            just_saw_cc_cmnt = type_code == cc_commnt; /* jrs 8jun92 */
  533. X
  534. X            if (type_code != 0) /* we must make this check, just in case there
  535. X                                   was an unexpected EOF */
  536. X                type_code = lexi(); /* read another token */
  537. X            /* if (ps.search_brace) ps.procname[0] = 0; */
  538. X            if ((is_procname = ps.procname[0]) && flushed_nl
  539. X                && !procnames_start_line && ps.in_decl
  540. X                && type_code == ident)
  541. X                flushed_nl = 0;
  542. X        }                       /* end of while (search_brace) */
  543. X        last_else = 0;
  544. Xcheck_type:
  545. X        if (type_code == 0)
  546. X        {                       /* we got eof */
  547. X            if (s_lab != e_lab || s_code != e_code
  548. X                || s_com != e_com)  /* must dump end of line */
  549. X                dump_line();
  550. X            if (ps.tos > 1)     /* check for balanced braces */
  551. X                diag(1, "Stuff missing from end of file.");
  552. X
  553. X            if (verbose)
  554. X            {
  555. X                printf("There were %d output lines and %d comments\n",
  556. X                       ps.out_lines, ps.out_coms);
  557. X                printf("(Lines with comments)/(Lines with code): %6.3f\n",
  558. X                       (1.0 * ps.com_lines) / code_lines);
  559. X            }
  560. X            fflush(output);
  561. X            exit(found_err);
  562. X        }
  563. X        if (
  564. X            (type_code != comment) &&
  565. X            (type_code != cc_commnt) &&
  566. X            (type_code != newline) &&
  567. X            (type_code != preesc) &&
  568. X            (type_code != form_feed))
  569. X        {
  570. X            if (force_nl &&
  571. X                (type_code != semicolon) &&
  572. X                (type_code != lbrace || btype_3 || !btype_2))
  573. X            {
  574. X                /* we should force a broken line here */
  575. X                if (verbose && !flushed_nl)
  576. X                    diag(0, "Line broken");
  577. X                flushed_nl = false;
  578. X                dump_line();
  579. X                ps.want_blank = false;  /* dont insert blank at line start */
  580. X                force_nl = false;
  581. X            }
  582. X            ps.in_stmt = true;  /* turn on flag which causes an extra level of
  583. X                                   indentation. this is turned off by a ; or
  584. X                                   '}' */
  585. X            if (s_com != e_com)
  586. X            {                   /* the turkey has embedded a comment in a line.
  587. X                                   fix it */
  588. X                *e_code++ = ' ';
  589. X                for (t_ptr = s_com; *t_ptr; ++t_ptr)
  590. X                {
  591. X                    check_size(code);
  592. X                    *e_code++ = *t_ptr;
  593. X                }
  594. X                *e_code++ = ' ';
  595. X                *e_code = '\0'; /* null terminate code sect */
  596. X                ps.want_blank = false;
  597. X                e_com = s_com;
  598. X            }
  599. X        }
  600. X        else if (type_code != comment && type_code != cc_commnt)
  601. X            /* preserve force_nl thru a comment */
  602. X            force_nl = false;   /* cancel forced newline after newline, form
  603. X                                   feed, etc */
  604. X
  605. X
  606. X
  607. X        /*-----------------------------------------------------*\
  608. X        |         do switch on type of token scanned            |
  609. X        \*-----------------------------------------------------*/
  610. X
  611. X        check_size(code);
  612. X        switch (type_code)
  613. X        {                       /* now, decide what to do with the token */
  614. X
  615. X        case form_feed:        /* found a form feed in line */
  616. X            ps.use_ff = true;   /* a form feed is treated much like a newline */
  617. X            dump_line();
  618. X            ps.want_blank = false;
  619. X            break;
  620. X
  621. X        case newline:
  622. X            if (ps.last_token != comma || ps.p_l_follow > 0
  623. X                || !ps.leave_comma || ps.block_init || !break_comma || s_com != e_com)
  624. X            {
  625. X                dump_line();
  626. X                ps.want_blank = false;
  627. X            }
  628. X            ++line_no;          /* keep track of input line number */
  629. X            break;
  630. X
  631. X        case lparen:           /* got a '(' or '[' */
  632. X            ++ps.p_l_follow;    /* count parens to make Healy happy */
  633. X            if (ps.want_blank && *token != '[' &&
  634. X                (ps.last_token != ident || proc_calls_space
  635. X               || (ps.its_a_keyword && (!ps.sizeof_keyword || Bill_Shannon))))
  636. X                *e_code++ = ' ';
  637. X            if (ps.in_decl && !ps.block_init)
  638. X                if (troff && !ps.dumped_decl_indent && !is_procname && ps.last_token == decl)
  639. X                {
  640. X                    ps.dumped_decl_indent = 1;
  641. X                    sprintf(e_code, "\n.Du %dp+\200p \"%s\"\n", dec_ind * 7, token);
  642. X                    e_code += strlen(e_code);
  643. X                }
  644. X                else
  645. X                {
  646. X                    while ((e_code - s_code) < dec_ind)
  647. X                    {
  648. X                        check_size(code);
  649. X                        *e_code++ = ' ';
  650. X                    }
  651. X                    *e_code++ = token[0];
  652. X                }
  653. X            else
  654. X                *e_code++ = token[0];
  655. X            if (parens_space && *token != '[')
  656. X                *e_code++ = ' ';
  657. X            ps.paren_indents[ps.p_l_follow - 1] = (short) (e_code - s_code);
  658. X            if (sp_sw && ps.p_l_follow == 1 && extra_expression_indent
  659. X                && ps.paren_indents[0] < (short) (2 * ps.ind_size))
  660. X                ps.paren_indents[0] = (short) (2 * ps.ind_size);
  661. X            ps.want_blank = false;
  662. X            if (ps.in_or_st && *token == '(' && ps.tos <= 2)
  663. X            {
  664. X                /*
  665. X                   this is a kluge to make sure that declarations will be
  666. X                   aligned right if proc decl has an explicit type on it, i.e.
  667. X                   "int a(x) {..."
  668. X                */
  669. X                parse(semicolon); /* I said this was a kluge... */
  670. X                ps.in_or_st = false;  /* turn off flag for structure decl or
  671. X                                         initialization */
  672. X            }
  673. X            if (ps.sizeof_keyword)
  674. X                ps.sizeof_mask |= 1 << ps.p_l_follow;
  675. X            break;
  676. X
  677. X        case rparen:           /* got a ')' or ']' */
  678. X            if (ps.cast_mask & (1 << ps.p_l_follow) & ~ps.sizeof_mask)
  679. X            {
  680. X                ps.last_u_d = true;
  681. X                ps.cast_mask &= (1 << ps.p_l_follow) - 1;
  682. X            }
  683. X            ps.sizeof_mask &= (1 << ps.p_l_follow) - 1;
  684. X            if (--ps.p_l_follow < 0)
  685. X            {
  686. X                ps.p_l_follow = 0;
  687. X                diag(0, "Extra %c", *token);
  688. X            }
  689. X            if (e_code == s_code) /* if the paren starts the line */
  690. X                ps.paren_level = ps.p_l_follow; /* then indent it */
  691. X
  692. X            if (parens_space && *token != ']')
  693. X                *e_code++ = ' ';
  694. X            *e_code++ = token[0];
  695. X            ps.want_blank = true;
  696. X
  697. X            if (sp_sw && (ps.p_l_follow == 0))
  698. X            {                   /* check for end of if (...), or some such */
  699. X                sp_sw = false;
  700. X                force_nl = true;/* must force newline after if */
  701. X                ps.last_u_d = true; /* inform lexi that a following operator is
  702. X                                       unary */
  703. X                ps.in_stmt = false; /* dont use stmt continuation indentation */
  704. X
  705. X                parse(hd_type); /* let parser worry about if, or whatever */
  706. X            }
  707. X            ps.search_brace = btype_2 && !btype_3;
  708. X            /*
  709. X               this should insure that constructs such as main(){...} and
  710. X               int[]{...} have their braces put in the right place
  711. X            */
  712. X            break;
  713. X
  714. X        case unary_op:         /* this could be any unary operation */
  715. X            if (ps.want_blank)
  716. X                *e_code++ = ' ';
  717. X
  718. X            if (troff && !ps.dumped_decl_indent && ps.in_decl && !is_procname)
  719. X            {
  720. X                sprintf(e_code, "\n.Du %dp+\200p \"%s\"\n", dec_ind * 7, token);
  721. X                ps.dumped_decl_indent = 1;
  722. X                e_code += strlen(e_code);
  723. X            }
  724. X            else
  725. X            {
  726. X                char *res = token;
  727. X
  728. X                if (ps.in_decl && !ps.block_init)
  729. X                {               /* if this is a unary op in a declaration, we
  730. X                                   should indent this token */
  731. X                    for (i = 0; token[i]; ++i); /* find length of token */
  732. X                    while ((e_code - s_code) < (dec_ind - i))
  733. X                    {
  734. X                        check_size(code);
  735. X                        *e_code++ = ' ';  /* pad it */
  736. X                    }
  737. X                }
  738. X                if (troff && token[0] == '-' && token[1] == '>')
  739. X                    res = "\\(->";
  740. X                for (t_ptr = res; *t_ptr; ++t_ptr)
  741. X                {
  742. X                    check_size(code);
  743. X                    *e_code++ = *t_ptr;
  744. X                }
  745. X            }
  746. X            ps.want_blank = false;
  747. X            break;
  748. X
  749. X        case binary_op:        /* any binary operation */
  750. X
  751. X            if (ps.want_blank)
  752. X                *e_code++ = ' ';
  753. X            {
  754. X                char *res = token;
  755. X
  756. X                if (troff)
  757. X                    switch (token[0])
  758. X                    {
  759. X                    case '<':
  760. X                        if (token[1] == '=')
  761. X                            res = "\\(<=";
  762. X                        break;
  763. X                    case '>':
  764. X                        if (token[1] == '=')
  765. X                            res = "\\(>=";
  766. X                        break;
  767. X                    case '!':
  768. X                        if (token[1] == '=')
  769. X                            res = "\\(!=";
  770. X                        break;
  771. X                    case '|':
  772. X                        if (token[1] == '|')
  773. X                            res = "\\(br\\(br";
  774. X                        else if (token[1] == 0)
  775. X                            res = "\\(br";
  776. X                        break;
  777. X                    }
  778. X                for (t_ptr = res; *t_ptr; ++t_ptr)
  779. X                {
  780. X                    check_size(code);
  781. X                    *e_code++ = *t_ptr; /* move the operator */
  782. X                }
  783. X            }
  784. X            ps.want_blank = true;
  785. X            break;
  786. X
  787. X        case postop:           /* got a trailing ++ or -- */
  788. X            *e_code++ = token[0];
  789. X            *e_code++ = token[1];
  790. X            ps.want_blank = true;
  791. X            break;
  792. X
  793. X        case question:         /* got a ? */
  794. X            squest++;           /* this will be used when a later colon appears
  795. X                                   so we can distinguish the <c>?<n>:<n>
  796. X                                   construct */
  797. X            if (ps.want_blank)
  798. X                *e_code++ = ' ';
  799. X            *e_code++ = '?';
  800. X            ps.want_blank = true;
  801. X            break;
  802. X
  803. X        case casestmt:         /* got word 'case' or 'default' */
  804. X            scase = true;       /* so we can process the later colon properly */
  805. X            goto copy_id;
  806. X
  807. X        case privpub:          /* got public, private or protected */
  808. X            strcpy(s_lab, token);
  809. X            e_lab = s_lab + strlen(token);
  810. X            *e_lab++ = ':';
  811. X            *e_lab++ = ' ';
  812. X            *e_lab = '\0';
  813. X            force_nl = true;
  814. X            break;
  815. X
  816. X        case colon:            /* got a ':' */
  817. X            if (squest > 0)
  818. X            {                   /* it is part of the <c>?<n>: <n> construct */
  819. X                --squest;
  820. X                if (ps.want_blank)
  821. X                    *e_code++ = ' ';
  822. X                *e_code++ = ':';
  823. X                ps.want_blank = true;
  824. X                break;
  825. X            }
  826. X            if (ps.in_decl)
  827. X            {
  828. X                if (cplus)      /* assume public, private, or protected */
  829. X                {
  830. X                    for (t_ptr = s_code; *t_ptr; ++t_ptr)
  831. X                        *e_lab++ = *t_ptr;  /* turn everything so far into a
  832. X                                               label */
  833. X                    e_code = s_code;
  834. X                    *e_lab++ = ':';
  835. X                    *e_lab++ = ' ';
  836. X                    *e_lab = '\0';
  837. X                    force_nl = true;
  838. X                    scase = false;
  839. X                    ps.pcase = true;
  840. X                    break;
  841. X                }
  842. X                *e_code++ = ':';
  843. X                ps.want_blank = false;
  844. X                break;
  845. X            }
  846. X            ps.in_stmt = false; /* seeing a label does not imply we are in a
  847. X                                   stmt */
  848. X            for (t_ptr = s_code; *t_ptr; ++t_ptr)
  849. X                *e_lab++ = *t_ptr;  /* turn everything so far into a label */
  850. X            e_code = s_code;
  851. X            *e_lab++ = ':';
  852. X            *e_lab++ = ' ';
  853. X            *e_lab = '\0';
  854. X
  855. X            force_nl = ps.pcase = scase;  /* ps.pcase will be used by dump_line
  856. X                                             to decide how to indent the label.
  857. X                                             force_nl will force a case n: to
  858. X                                             be on a line by itself */
  859. X            scase = false;
  860. X            ps.want_blank = false;
  861. X            break;
  862. X
  863. X        case semicolon:        /* got a ';' */
  864. X            ps.in_or_st = false;/* we are not in an initialization or structure
  865. X                                   declaration */
  866. X            scase = false;      /* these will only need resetting in a error */
  867. X            squest = 0;
  868. X            if (ps.last_token == rparen)
  869. X                ps.in_parameter_declaration = 0;
  870. X            ps.cast_mask = 0;
  871. X            ps.sizeof_mask = 0;
  872. X            ps.block_init = 0;
  873. X            ps.block_init_level = 0;
  874. X            ps.just_saw_decl--;
  875. X
  876. X            if (ps.in_decl && s_code == e_code && !ps.block_init)
  877. X                while ((e_code - s_code) < (dec_ind - 1))
  878. X                {
  879. X                    check_size(code);
  880. X                    *e_code++ = ' ';
  881. X                }
  882. X
  883. X            ps.in_decl = (ps.dec_nest > 0); /* if we were in a first level
  884. X                                               structure declaration, we arent
  885. X                                               any more */
  886. X
  887. X            if ((!sp_sw || hd_type != forstmt) && ps.p_l_follow > 0)
  888. X            {
  889. X
  890. X                /*
  891. X                   This should be true iff there were unbalanced parens in the
  892. X                   stmt.  It is a bit complicated, because the semicolon might
  893. X                   be in a for stmt
  894. X                */
  895. X                diag(1, "Unbalanced parens");
  896. X                ps.p_l_follow = 0;
  897. X                if (sp_sw)
  898. X                {               /* this is a check for a if, while, etc. with
  899. X                                   unbalanced parens */
  900. X                    sp_sw = false;
  901. X                    parse(hd_type); /* dont lose the if, or whatever */
  902. X                }
  903. X            }
  904. X            *e_code++ = ';';
  905. X            ps.want_blank = true;
  906. X            ps.in_stmt = (ps.p_l_follow > 0); /* we are no longer in the middle
  907. X                                                 of a stmt */
  908. X
  909. X            if (!sp_sw)
  910. X            {                   /* if not if for (;;) */
  911. X                parse(semicolon); /* let parser know about end of stmt */
  912. X                force_nl = true;/* force newline after a end of stmt */
  913. X            }
  914. X            break;
  915. X
  916. X        case lbrace:           /* got a '{' */
  917. X            ps.in_stmt = false; /* dont indent the {} */
  918. X            if (!ps.block_init)
  919. X                force_nl = true;/* force other stuff on same line as '{' onto
  920. X                                   new line */
  921. X            else if (ps.block_init_level <= 0)
  922. X                ps.block_init_level = 1;
  923. X            else
  924. X                ps.block_init_level++;
  925. X
  926. X            if (s_code != e_code && !ps.block_init)
  927. X            {
  928. X                if (btype_3 || !btype_2)
  929. X                {
  930. X                    dump_line();
  931. X                    ps.want_blank = false;
  932. X                }
  933. X                else if (ps.in_parameter_declaration && !ps.in_or_st)
  934. X                {
  935. X                    ps.i_l_follow = 0;
  936. X                    dump_line();
  937. X                    ps.want_blank = false;
  938. X                }
  939. X            }
  940. X            if (ps.in_parameter_declaration)
  941. X                prefix_blankline_requested = 0;
  942. X
  943. X            if (ps.p_l_follow > 0)
  944. X            {                   /* check for preceeding unbalanced parens */
  945. X                diag(1, "Unbalanced parens");
  946. X                ps.p_l_follow = 0;
  947. X                if (sp_sw)
  948. X                {               /* check for unclosed if, for, etc. */
  949. X                    sp_sw = false;
  950. X                    parse(hd_type);
  951. X                    ps.ind_level = ps.i_l_follow;
  952. X                }
  953. X            }
  954. X            if (btype_3)
  955. X                ps.ind_stmt = true;
  956. X            else if (s_code == e_code)
  957. X                ps.ind_stmt = false;  /* dont put extra indentation on line
  958. X                                         with '{' */
  959. X            if (ps.in_decl && ps.in_or_st)
  960. X            {                   /* this is either a structure declaration or an
  961. X                                   init */
  962. X                di_stack[ps.dec_nest++] = dec_ind;
  963. X                /* ?        dec_ind = 0; */
  964. X            }
  965. X            else
  966. X            {
  967. X                ps.decl_on_line = false;  /* we cant be in the middle of a
  968. X                                             declaration, so dont do special
  969. X                                             indentation of comments */
  970. X                if (blanklines_after_declarations_at_proctop
  971. X                    && ps.in_parameter_declaration)
  972. X                    postfix_blankline_requested = 1;
  973. X                ps.in_parameter_declaration = 0;
  974. X            }
  975. X            dec_ind = 0;
  976. X            parse(lbrace);      /* let parser know about this */
  977. X            if (ps.want_blank)  /* put a blank before '{' if '{' is not at
  978. X                                   start of line */
  979. X                *e_code++ = ' ';
  980. X            ps.want_blank = false;
  981. X            *e_code++ = '{';
  982. X            ps.just_saw_decl = 0;
  983. X            break;
  984. X
  985. X        case rbrace:           /* got a '}' */
  986. X            if (ps.p_stack[ps.tos] == decl && !ps.block_init) /* semicolons can be
  987. X                                                                 omitted in
  988. X                                                                 declarations */
  989. X                parse(semicolon);
  990. X            if (ps.p_l_follow)
  991. X            {                   /* check for unclosed if, for, else. */
  992. X                diag(1, "Unbalanced parens");
  993. X                ps.p_l_follow = 0;
  994. X                sp_sw = false;
  995. X            }
  996. X            ps.just_saw_decl = 0;
  997. X            ps.block_init_level--;
  998. X            if (s_code != e_code && !ps.block_init)
  999. X            {                   /* '}' must be first on line */
  1000. X                if (verbose)
  1001. X                    diag(0, "Line broken");
  1002. X                dump_line();
  1003. X            }
  1004. X            *e_code++ = '}';
  1005. X            ps.want_blank = true;
  1006. X            ps.in_stmt = ps.ind_stmt = false;
  1007. X            if (ps.dec_nest > 0)
  1008. X            {                   /* we are in multi-level structure declaration */
  1009. X                dec_ind = di_stack[--ps.dec_nest];
  1010. X                if (ps.dec_nest == 0 && !ps.in_parameter_declaration)
  1011. X                    ps.just_saw_decl = 2;
  1012. X                ps.in_decl = true;
  1013. X            }
  1014. X            prefix_blankline_requested = 0;
  1015. X            parse(rbrace);      /* let parser know about this */
  1016. X            ps.search_brace = cuddle_else && ps.p_stack[ps.tos] == ifhead
  1017. X                && ps.il[ps.tos] >= ps.ind_level;
  1018. X            if (ps.tos <= 1 && blanklines_after_procs && ps.dec_nest <= 0)
  1019. X                postfix_blankline_requested = 1;
  1020. X            if (btype_3 && ps.p_stack[ps.tos] == dohead)
  1021. X            {
  1022. X                if (verbose)
  1023. X                    diag(0, "Line broken");
  1024. X                dump_line();
  1025. X                ps.want_blank = false;
  1026. X            }
  1027. X            break;
  1028. X
  1029. X        case swstmt:           /* got keyword "switch" */
  1030. X            sp_sw = true;
  1031. X            hd_type = swstmt;   /* keep this for when we have seen the
  1032. X                                   expression */
  1033. X            goto copy_id;       /* go move the token into buffer */
  1034. X
  1035. X        case sp_paren:         /* token is if, while, for */
  1036. X            sp_sw = true;       /* the interesting stuff is done after the
  1037. X                                   expression is scanned */
  1038. X            hd_type = (*token == 'i' ? ifstmt :
  1039. X                       (*token == 'w' ? whilestmt : forstmt));
  1040. X
  1041. X            /*
  1042. X               remember the type of header for later use by parser
  1043. X            */
  1044. X            goto copy_id;       /* copy the token into line */
  1045. X
  1046. X        case sp_nparen:        /* got else, do */
  1047. X            ps.in_stmt = false;
  1048. X            if (*token == 'e')
  1049. X            {
  1050. X                if (e_code != s_code && (!cuddle_else || e_code[-1] != '}'))
  1051. X                {
  1052. X                    if (verbose)
  1053. X                        diag(0, "Line broken");
  1054. X                    dump_line();/* make sure this starts a line */
  1055. X                    ps.want_blank = false;
  1056. X                }
  1057. X                force_nl = true;/* also, following stuff must go onto new line */
  1058. X                last_else = 1;
  1059. X                parse(elselit);
  1060. X            }
  1061. X            else
  1062. X            {
  1063. X                if (e_code != s_code)
  1064. X                {               /* make sure this starts a line */
  1065. X                    if (verbose)
  1066. X                        diag(0, "Line broken");
  1067. X                    dump_line();
  1068. X                    ps.want_blank = false;
  1069. X                }
  1070. X                force_nl = true;/* also, following stuff must go onto new line */
  1071. X                last_else = 0;
  1072. X                parse(dolit);
  1073. X            }
  1074. X            goto copy_id;       /* move the token into line */
  1075. X
  1076. X        case decl:             /* we have a declaration type (int, register,
  1077. X                                   etc.) */
  1078. X            parse(decl);        /* let parser worry about indentation */
  1079. X            if (ps.last_token == rparen && ps.tos <= 1)
  1080. X            {
  1081. X                ps.in_parameter_declaration = 1;
  1082. X                if (s_code != e_code)
  1083. X                {
  1084. X                    dump_line();
  1085. X                    ps.want_blank = 0;
  1086. X                }
  1087. X            }
  1088. X            if (ps.in_parameter_declaration && ps.indent_parameters && ps.dec_nest == 0)
  1089. X            {
  1090. X                ps.ind_level = ps.i_l_follow = 1;
  1091. X                ps.ind_stmt = 0;
  1092. X            }
  1093. X            ps.in_or_st = true; /* this might be a structure or initialization
  1094. X                                   declaration */
  1095. X            ps.in_decl = ps.decl_on_line = true;
  1096. X            if ( /* !ps.in_or_st && */ ps.dec_nest <= 0)
  1097. X                ps.just_saw_decl = 2;
  1098. X            prefix_blankline_requested = 0;
  1099. X            for (i = 0; token[i++];); /* get length of token */
  1100. X
  1101. X            /*
  1102. X               dec_ind = e_code - s_code + (ps.decl_indent>i ? ps.decl_indent :
  1103. X               i);
  1104. X            */
  1105. X            dec_ind = ps.decl_indent > 0 ? ps.decl_indent : i;
  1106. X            goto copy_id;
  1107. X
  1108. X        case ident:            /* got an identifier or constant */
  1109. X            if (ps.in_decl)
  1110. X            {                   /* if we are in a declaration, we must indent
  1111. X                                   identifier */
  1112. X                if (ps.want_blank)
  1113. X                    *e_code++ = ' ';
  1114. X                ps.want_blank = false;
  1115. X                if (is_procname == 0 || !procnames_start_line)
  1116. X                {
  1117. X                    if (!ps.block_init)
  1118. X                        if (troff && !ps.dumped_decl_indent)
  1119. X                        {
  1120. X                            sprintf(e_code, "\n.De %dp+\200p\n", dec_ind * 7);
  1121. X                            ps.dumped_decl_indent = 1;
  1122. X                            e_code += strlen(e_code);
  1123. X                        }
  1124. X                        else
  1125. X                            while ((e_code - s_code) < dec_ind)
  1126. X                            {
  1127. X                                check_size(code);
  1128. X                                *e_code++ = ' ';
  1129. X                            }
  1130. X                }
  1131. X                else
  1132. X                {
  1133. X                    if (dec_ind && s_code != e_code)
  1134. X                        dump_line();
  1135. X                    dec_ind = 0;
  1136. X                    ps.want_blank = false;
  1137. X                }
  1138. X            }
  1139. X            else if (sp_sw && ps.p_l_follow == 0)
  1140. X            {
  1141. X                sp_sw = false;
  1142. X                force_nl = true;
  1143. X                ps.last_u_d = true;
  1144. X                ps.in_stmt = false;
  1145. X                parse(hd_type);
  1146. X            }
  1147. X    copy_id:
  1148. X            if (ps.want_blank)
  1149. X                *e_code++ = ' ';
  1150. X            if (troff && ps.its_a_keyword)
  1151. X            {
  1152. X                e_code = chfont(&bodyf, &keywordf, e_code);
  1153. X                for (t_ptr = token; *t_ptr; ++t_ptr)
  1154. X                {
  1155. X                    check_size(code);
  1156. X                    *e_code++ = keywordf.allcaps && islower(*t_ptr)
  1157. X                        ? (char) toupper(*t_ptr) : *t_ptr;
  1158. X                }
  1159. X                e_code = chfont(&keywordf, &bodyf, e_code);
  1160. X            }
  1161. X            else
  1162. X                for (t_ptr = token; *t_ptr; ++t_ptr)
  1163. X                {
  1164. X                    check_size(code);
  1165. X                    *e_code++ = *t_ptr;
  1166. X                }
  1167. X            ps.want_blank = true;
  1168. X            break;
  1169. X
  1170. X        case period:           /* treat a period kind of like a binary
  1171. X                                   operation */
  1172. X            *e_code++ = '.';    /* move the period into line */
  1173. X            ps.want_blank = false;  /* dont put a blank after a period */
  1174. X            break;
  1175. X
  1176. X        case comma:
  1177. X            ps.want_blank = (s_code != e_code); /* only put blank after comma
  1178. X                                                   if comma does not start the
  1179. X                                                   line */
  1180. X            if (ps.in_decl && is_procname == 0 && !ps.block_init)
  1181. X                while ((e_code - s_code) < (dec_ind - 1))
  1182. X                {
  1183. X                    check_size(code);
  1184. X                    *e_code++ = ' ';
  1185. X                }
  1186. X
  1187. X            *e_code++ = ',';
  1188. X            if (ps.p_l_follow == 0)
  1189. X            {
  1190. X                if (ps.block_init_level <= 0)
  1191. X                    ps.block_init = 0;
  1192. X                if (break_comma && !ps.leave_comma)
  1193. X                    force_nl = true;
  1194. X            }
  1195. X            break;
  1196. X
  1197. X        case preesc:           /* got the character '#' */
  1198. X            if ((s_com != e_com) ||
  1199. X                (s_lab != e_lab) ||
  1200. X                (s_code != e_code))
  1201. X                dump_line();
  1202. X            *e_lab++ = '#';     /* move whole line to 'label' buffer */
  1203. X            {
  1204. X                int in_comment = 0;
  1205. X                int com_start = 0;
  1206. X                char quote = 0;
  1207. X                int com_end = 0;
  1208. X
  1209. X                while (*buf_ptr != '\n' || in_comment)
  1210. X                {
  1211. X                    check_size(lab);
  1212. X                    *e_lab = *buf_ptr++;
  1213. X                    if (buf_ptr >= buf_end)
  1214. X                        fill_buffer();
  1215. X                    switch (*e_lab++)
  1216. X                    {
  1217. X                    case BACKSLASH:
  1218. X                        if (troff)
  1219. X                            *e_lab++ = BACKSLASH;
  1220. X                        if (!in_comment)
  1221. X                        {
  1222. X                            *e_lab++ = *buf_ptr++;
  1223. X                            if (buf_ptr >= buf_end)
  1224. X                                fill_buffer();
  1225. X                        }
  1226. X                        break;
  1227. X                    case '/':
  1228. X                        if (*buf_ptr == '*' && !in_comment && !quote)
  1229. X                        {
  1230. X                            in_comment = 1;
  1231. X                            *e_lab++ = *buf_ptr++;
  1232. X                            com_start = e_lab - s_lab - 2;
  1233. X                        }
  1234. X                        else if (*buf_ptr == '/' && !in_comment && !quote)
  1235. X                        {
  1236. X                            in_comment = 2;
  1237. X                            *e_lab++ = *buf_ptr++;
  1238. X                            com_start = e_lab - s_lab - 2;
  1239. X                        }
  1240. X                        break;
  1241. X                    case '"':
  1242. X                        if (quote == '"')
  1243. X                            quote = 0;
  1244. X                        break;
  1245. X                    case '\'':
  1246. X                        if (quote == '\'')
  1247. X                            quote = 0;
  1248. X                        break;
  1249. X                    case '*':
  1250. X                        if (*buf_ptr == '/' && in_comment == 1)
  1251. X                        {
  1252. X                            in_comment = 0;
  1253. X                            *e_lab++ = *buf_ptr++;
  1254. X                            com_end = e_lab - s_lab;
  1255. X                        }
  1256. X                        break;
  1257. X                    case '\n':
  1258. X                        if (in_comment == 2)
  1259. X                        {
  1260. X                            in_comment = 0;
  1261. X                            --buf_ptr;  /* so while loop will exit */
  1262. X                            com_end = e_lab - s_lab;
  1263. X                        }
  1264. X                        break;
  1265. X                    }
  1266. X                }
  1267. X
  1268. X                while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t'))
  1269. X                    e_lab--;
  1270. X                if (e_lab - s_lab == com_end && bp_save == 0)
  1271. X                {               /* comment on preprocessor line */
  1272. X                    if (sc_end == 0)  /* if this is the first comment, we must
  1273. X                                         set up the buffer */
  1274. X                        sc_end = &(save_com[0]);
  1275. X                    else
  1276. X                    {
  1277. X                        *sc_end++ = '\n'; /* add newline between comments */
  1278. X                        *sc_end++ = ' ';
  1279. X                        --line_no;
  1280. X                    }
  1281. X#ifdef BSD                      /* gst 24 Mar 89 */
  1282. X                    bcopy(s_lab + com_start, sc_end, com_end - com_start);
  1283. X#else
  1284. X                    memcpy(sc_end, s_lab + com_start, com_end - com_start);
  1285. X#endif
  1286. X                    sc_end += com_end - com_start;
  1287. X                    if (sc_end >= &save_com[sc_size])
  1288. X                        abort();
  1289. X                    e_lab = s_lab + com_start;
  1290. X                    while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t'))
  1291. X                        e_lab--;
  1292. X                    bp_save = buf_ptr;  /* save current input buffer */
  1293. X                    be_save = buf_end;
  1294. X                    buf_ptr = save_com; /* fix so that subsequent calls to lexi
  1295. X                                           will take tokens out of save_com */
  1296. X                    *sc_end++ = ' ';  /* add trailing blank, just in case */
  1297. X                    buf_end = sc_end;
  1298. X                    sc_end = 0;
  1299. X                }
  1300. X                *e_lab = '\0';  /* null terminate line */
  1301. X                ps.pcase = false;
  1302. X            }
  1303. X
  1304. X            if (strncmp(s_lab, "#if", 3) == 0)
  1305. X            {
  1306. X                if (blanklines_around_conditional_compilation)
  1307. X                {
  1308. X                    register c;
  1309. X
  1310. X                    prefix_blankline_requested++;
  1311. X                    while ((c = getc(input)) == '\n');
  1312. X                    ungetc(c, input);
  1313. X                }
  1314. X                if (ifdef_level < sizeof state_stack / sizeof state_stack[0])
  1315. X                {
  1316. X                    match_state[ifdef_level].tos = -1;
  1317. X                    state_stack[ifdef_level++] = ps;
  1318. X                }
  1319. X                else
  1320. X                    diag(1, "#if stack overflow");
  1321. X            }
  1322. X            else if (strncmp(s_lab, "#else", 5) == 0)
  1323. X                if (ifdef_level <= 0)
  1324. X                    diag(1, "Unmatched #else");
  1325. X                else
  1326. X                {
  1327. X                    match_state[ifdef_level - 1] = ps;
  1328. X                    ps = state_stack[ifdef_level - 1];
  1329. X                }
  1330. X            else if (strncmp(s_lab, "#endif", 6) == 0)
  1331. X            {
  1332. X                if (ifdef_level <= 0)
  1333. X                    diag(1, "Unmatched #endif");
  1334. X                else
  1335. X                {
  1336. X                    ifdef_level--;
  1337. X
  1338. X#ifdef undef
  1339. X                    /*
  1340. X                       This match needs to be more intelligent before the
  1341. X                       message is useful
  1342. X                    */
  1343. X                    if (match_state[ifdef_level].tos >= 0
  1344. X                        && bcmp(&ps, &match_state[ifdef_level], sizeof ps))
  1345. X                        diag(0, "Syntactically inconsistent #ifdef alternatives.");
  1346. X#endif
  1347. X                }
  1348. X                if (blanklines_around_conditional_compilation)
  1349. X                {
  1350. X                    postfix_blankline_requested++;
  1351. X                    n_real_blanklines = 0;
  1352. X                }
  1353. X            }
  1354. X            break;              /* subsequent processing of the newline
  1355. X                                   character will cause the line to be printed */
  1356. X
  1357. X        case cc_commnt:        /* we have gotten a //  this is a biggie */
  1358. X        case comment:          /* we have gotten a /*  this is a biggie */
  1359. X
  1360. X            if (flushed_nl)
  1361. X            {                   /* we should force a broken line here */
  1362. X                flushed_nl = false;
  1363. X                dump_line();
  1364. X                ps.want_blank = false;  /* dont insert blank at line start */
  1365. X                force_nl = false;
  1366. X            }
  1367. X            pr_comment();
  1368. X            /*
  1369. X               pr_comment()'s parsing sequence for a C++ comment is quite
  1370. X               different from that for a standard comment.  Without the
  1371. X               following test a C++ comment causes the next line to be
  1372. X               formatted with an extra blank space before the code or to be
  1373. X               preceded by an extra blank line.       jrs 12 mar 92
  1374. X
  1375. X               (I haven't checked, but there's a good chance that fixing
  1376. X               the abovementioned bug introduced another one.  For a while,
  1377. X               indent would swallow the next statement after a sequence
  1378. X               such as } // this type of comment.  jrs 15jun92)
  1379. X            */
  1380. X            if (type_code == cc_commnt) /* jrs 12 Mar 92 */
  1381. X                force_nl = ps.want_blank = false; /* jrs 12 Mar 92 */
  1382. X            break;
  1383. X        }                       /* end of big switch stmt */
  1384. X
  1385. X        *e_code = '\0';         /* make sure code section is null terminated */
  1386. X        if (type_code != comment && type_code != newline && type_code != preesc && type_code != cc_commnt)
  1387. X            ps.last_token = type_code;
  1388. X    }                           /* end of main while (1) loop */
  1389. X}
  1390. X
  1391. X/*
  1392. X * copy input file to backup file if in_name is /blah/blah/blah/file, then
  1393. X * backup file will be ".Bfile" then make the backup file the input and
  1394. X * original input file the output
  1395. X */
  1396. X#ifdef ANSIC
  1397. Xstatic void bakcopy(void)
  1398. X#else
  1399. Xbakcopy()
  1400. X#endif
  1401. X{
  1402. X#ifdef OS2
  1403. X    int fat = 0;                /* File system type = FAT? */
  1404. X    char *q;
  1405. X
  1406. X#endif
  1407. X    int n, bakchn;
  1408. X
  1409. X/*  char        buff[8 * 1024];        Ouch!  Such a big stack!
  1410. X    Let's allocate a buffer from the heap instead .... jrs 12 Mar 92 */
  1411. X
  1412. X    char *buff;
  1413. X
  1414. X# define COPY_BUFFER_SIZE 8*1024
  1415. X    register char *p;
  1416. X
  1417. X    if ((buff = (char *) malloc(COPY_BUFFER_SIZE)) == NULL)
  1418. X    {
  1419. X        fprintf(stderr, "indent: no memory for backup file copy buffer");
  1420. X        exit(1);
  1421. X    }
  1422. X
  1423. X    /* construct file name .Bfile */
  1424. X
  1425. X#ifdef OS2                      /* or MSDOS */
  1426. X# ifndef __32BIT__              /* then must be OS/2 1.x or MSDOS */
  1427. X#   define DosQueryFSAttach(a,b,c,d,e) DosQFSAttach(a,b,c,(BYTE *)d,e,0L)
  1428. X#   define DosQueryCurrentDisk DosQCurDisk
  1429. X#   define PARAM_T USHORT
  1430. X
  1431. X    DosGetMachineMode(&buff[0]);
  1432. X    if (buff[0] == MODE_REAL)   /* DOS can only handle FAT */
  1433. X        fat = 1;
  1434. X# else
  1435. X#   define PARAM_T ULONG
  1436. X# endif
  1437. X
  1438. X    if (!fat)
  1439. X    {
  1440. X        PARAM_T DriveNumber, cbData;
  1441. X        ULONG DriveMap;
  1442. X        struct fsqb
  1443. X        {
  1444. X# ifdef __32BIT__
  1445. X            FSQBUFFER2 bData;
  1446. X# else
  1447. X            FSQBUFFER bData;
  1448. X# endif
  1449. X            BYTE filler[60];
  1450. X        }
  1451. X            fsq;
  1452. X
  1453. X        cbData = sizeof fsq;
  1454. X        if (isalpha(in_name[0]) && in_name[1] == ':')
  1455. X            DriveNumber = toupper(in_name[0]) - '@';
  1456. X        else
  1457. X            DosQueryCurrentDisk(&DriveNumber, &DriveMap);
  1458. X
  1459. X        if (DosQueryFSAttach(NULL, DriveNumber, FSAIL_DRVNUMBER,
  1460. X                             &fsq.bData, &cbData))
  1461. X            fat = 0;
  1462. X        else
  1463. X            fat = !strcmp(&fsq.bData.szFSDName[fsq.bData.cbName], "FAT");
  1464. X    }
  1465. X
  1466. X    for (p = strcpy(bakfile, in_name); *p; ++p);  /* skip to end of string */
  1467. X    while (p > bakfile && *p != '/' && *p != '\\')
  1468. X        p--;
  1469. X    if (*p == '/' || *p == '\\')
  1470. X        p++;
  1471. X    if (fat && (q = strchr(p, '.')) != NULL)
  1472. X        *q = '\0';
  1473. X    strcat(bakfile, ".BAK");
  1474. X
  1475. X#else                           /* it isn't MSDOS or OS/2 */
  1476. X
  1477. X    for (p = in_name; *p; p++); /* skip to end of string */
  1478. X    while (p > in_name && *p != '/')  /* find last '/' */
  1479. X        p--;
  1480. X    if (*p == '/')
  1481. X        p++;
  1482. X
  1483. X    sprintf(bakfile, "%s.BAK", p);
  1484. X
  1485. X#endif
  1486. X
  1487. X    /* copy in_name to backup file */
  1488. X    bakchn = creat(bakfile, 0600);
  1489. X    if (bakchn < 0)
  1490. X    {
  1491. X        fprintf(stderr, "indent: can't create backup file \"%s\"\n", bakfile);
  1492. X        exit(1);
  1493. X    }
  1494. X    while (n = read(fileno(input), buff, COPY_BUFFER_SIZE))
  1495. X        if (write(bakchn, buff, n) != n)
  1496. X        {
  1497. X            fprintf(stderr, "indent: error writing backup file \"%s\"\n",
  1498. X                    bakfile);
  1499. X            exit(1);
  1500. X        }
  1501. X    if (n < 0)
  1502. X    {
  1503. X        fprintf(stderr, "indent: error reading input file \"%s\"\n", in_name);
  1504. X        exit(1);
  1505. X    }
  1506. X    close(bakchn);
  1507. X    fclose(input);
  1508. X
  1509. X    free(buff);
  1510. X
  1511. X    /* re-open backup file as the input file */
  1512. X    input = fopen(bakfile, "r");
  1513. X    if (input == NULL)
  1514. X    {
  1515. X        fprintf(stderr, "indent: can't re-open backup file\n");
  1516. X        exit(1);
  1517. X    }
  1518. X    /* now the original input file will be the output */
  1519. X    output = fopen(in_name, "w");
  1520. X    if (output == NULL)
  1521. X    {
  1522. X        fprintf(stderr, "indent: can't create %s\n", in_name);
  1523. X        unlink(bakfile);
  1524. X        exit(1);
  1525. X    }
  1526. X}
  1527. END_OF_FILE
  1528.   if test 57244 -ne `wc -c <'indent.c'`; then
  1529.     echo shar: \"'indent.c'\" unpacked with wrong size!
  1530.   fi
  1531.   # end of 'indent.c'
  1532. fi
  1533. if test -f 'indent.def' -a "${1}" != "-c" ; then 
  1534.   echo shar: Will not clobber existing file \"'indent.def'\"
  1535. else
  1536.   echo shar: Extracting \"'indent.def'\" \(50 characters\)
  1537.   sed "s/^X//" >'indent.def' <<'END_OF_FILE'
  1538. XName Indent WindowCompat NewFiles
  1539. Xstacksize 12000
  1540. END_OF_FILE
  1541.   if test 50 -ne `wc -c <'indent.def'`; then
  1542.     echo shar: \"'indent.def'\" unpacked with wrong size!
  1543.   fi
  1544.   # end of 'indent.def'
  1545. fi
  1546. echo shar: End of archive 2 \(of 4\).
  1547. cp /dev/null ark2isdone
  1548. MISSING=""
  1549. for I in 1 2 3 4 ; do
  1550.     if test ! -f ark${I}isdone ; then
  1551.     MISSING="${MISSING} ${I}"
  1552.     fi
  1553. done
  1554. if test "${MISSING}" = "" ; then
  1555.     echo You have unpacked all 4 archives.
  1556.     rm -f ark[1-9]isdone
  1557. else
  1558.     echo You still must unpack the following archives:
  1559.     echo "        " ${MISSING}
  1560. fi
  1561. exit 0
  1562. exit 0 # Just in case...
  1563.