home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume18 / indent / part03 < prev    next >
Encoding:
Internet Message Format  |  1989-03-20  |  36.3 KB

  1. Subject:  v18i051:  Indent, C reformatting program, Part03/03
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: Ozan Yigit <oz@nexus.yorku.ca>
  7. Posting-number: Volume 18, Issue 51
  8. Archive-name: indent/part03
  9.  
  10. [  In case it's not clear, this program contains the original version,
  11.    plus the changes UCB and Sun have made.  Thanks to them for putting
  12.    their work into the freely-redistributable category.  If you have
  13.    indent on your systems, replace it with this version.  --r$  ]
  14.  
  15. #! /bin/sh
  16. # This is a shell archive.  Remove anything before this line, then unpack
  17. # it by saving it into a file and typing "sh file".  To overwrite existing
  18. # files, type "sh file -c".  You can also feed this as standard input via
  19. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  20. # will see the following message at the end:
  21. #        "End of archive 3 (of 3)."
  22. # Contents:  indent/indent.c
  23. # Wrapped by oz@yunexus on Thu Mar  9 18:11:06 1989
  24. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  25. if test -f 'indent/indent.c' -a "${1}" != "-c" ; then 
  26.   echo shar: Will not clobber existing file \"'indent/indent.c'\"
  27. else
  28. echo shar: Extracting \"'indent/indent.c'\" \(34171 characters\)
  29. sed "s/^X//" >'indent/indent.c' <<'END_OF_FILE'
  30. X/*
  31. X * Copyright (c) 1985 Sun Microsystems, Inc.
  32. X * Copyright (c) 1980 The Regents of the University of California.
  33. X * Copyright (c) 1976 Board of Trustees of the University of Illinois.
  34. X * All rights reserved.
  35. X *
  36. X * Redistribution and use in source and binary forms are permitted
  37. X * provided that the above copyright notice and this paragraph are
  38. X * duplicated in all such forms and that any documentation,
  39. X * advertising materials, and other materials related to such
  40. X * distribution and use acknowledge that the software was developed
  41. X * by the University of California, Berkeley, the University of Illinois,
  42. X * Urbana, and Sun Microsystems, Inc.  The name of either University
  43. X * or Sun Microsystems may not be used to endorse or promote products
  44. X * derived from this software without specific prior written permission.
  45. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  46. X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  47. X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  48. X */
  49. X
  50. X#ifndef lint
  51. Xchar copyright[] =
  52. X"@(#) Copyright (c) 1985 Sun Microsystems, Inc.\n\
  53. X @(#) Copyright (c) 1980 The Regents of the University of California.\n\
  54. X @(#) Copyright (c) 1976 Board of Trustees of the University of Illinois.\n\
  55. X All rights reserved.\n";
  56. X#endif /* not lint */
  57. X
  58. X#ifndef lint
  59. Xstatic char sccsid[] = "@(#)indent.c    5.11 (Berkeley) 9/15/88";
  60. X#endif /* not lint */
  61. X
  62. X#include "indent_globs.h"
  63. X#include "indent_codes.h"
  64. X#include <sys/param.h>
  65. X#include <ctype.h>
  66. X
  67. Xchar       *in_name = "Standard Input";    /* will always point to name of input
  68. X                     * file */
  69. Xchar       *out_name = "Standard Output";    /* will always point to name
  70. X                         * of output file */
  71. Xchar        bakfile[MAXPATHLEN] = "";
  72. X
  73. Xmain(argc, argv)
  74. X    int         argc;
  75. X    char      **argv;
  76. X{
  77. X
  78. X    extern int  found_err;    /* flag set in diag() on error */
  79. X    int         dec_ind;    /* current indentation for declarations */
  80. X    int         di_stack[20];    /* a stack of structure indentation levels */
  81. X    int         flushed_nl;    /* used when buffering up comments to remember
  82. X                 * that a newline was passed over */
  83. X    int         force_nl;    /* when true, code must be broken */
  84. X    int         hd_type;    /* used to store type of stmt for if (...),
  85. X                 * for (...), etc */
  86. X    register int i;        /* local loop counter */
  87. X    int         scase;        /* set to true when we see a case, so we will
  88. X                 * know what to do with the following colon */
  89. X    int         sp_sw;        /* when true, we are in the expressin of
  90. X                 * if(...), while(...), etc. */
  91. X    int         squest;        /* when this is positive, we have seen a ?
  92. X                 * without the matching : in a <c>?<s>:<s>
  93. X                 * construct */
  94. X    register char *t_ptr;    /* used for copying tokens */
  95. X    int         type_code;    /* the type of token, returned by lexi */
  96. X
  97. X    int         last_else = 0;    /* true iff last keyword was an else */
  98. X
  99. X
  100. X    /*-----------------------------------------------*\
  101. X    |              INITIALIZATION              |
  102. X    \*-----------------------------------------------*/
  103. X
  104. X
  105. X    ps.p_stack[0] = stmt;    /* this is the parser's stack */
  106. X    ps.last_nl = true;        /* this is true if the last thing scanned was
  107. X                 * a newline */
  108. X    ps.last_token = semicolon;
  109. X    combuf = (char *) malloc(bufsize);
  110. X    labbuf = (char *) malloc(bufsize);
  111. X    codebuf = (char *) malloc(bufsize);
  112. X    l_com = combuf + bufsize - 5;
  113. X    l_lab = labbuf + bufsize - 5;
  114. X    l_code = codebuf + bufsize - 5;
  115. X    combuf[0] = codebuf[0] = labbuf[0] = ' ';    /* set up code, label, and
  116. X                         * comment buffers */
  117. X    combuf[1] = codebuf[1] = labbuf[1] = '\0';
  118. X    ps.else_if = 1;        /* Default else-if special processing to on */
  119. X    s_lab = e_lab = labbuf + 1;
  120. X    s_code = e_code = codebuf + 1;
  121. X    s_com = e_com = combuf + 1;
  122. X
  123. X    buf_ptr = buf_end = in_buffer;
  124. X    line_no = 1;
  125. X    had_eof = ps.in_decl = ps.decl_on_line = break_comma = false;
  126. X    sp_sw = force_nl = false;
  127. X    ps.in_or_st = false;
  128. X    ps.bl_line = true;
  129. X    dec_ind = 0;
  130. X    di_stack[ps.dec_nest = 0] = 0;
  131. X    ps.want_blank = ps.in_stmt = ps.ind_stmt = false;
  132. X
  133. X
  134. X    scase = ps.pcase = false;
  135. X    squest = 0;
  136. X    sc_end = 0;
  137. X    bp_save = 0;
  138. X    be_save = 0;
  139. X
  140. X    output = 0;
  141. X
  142. X
  143. X
  144. X    /*--------------------------------------------------*\
  145. X    |           COMMAND LINE SCAN         |
  146. X    \*--------------------------------------------------*/
  147. X
  148. X#ifdef undef
  149. X    max_col = 78;        /* -l78 */
  150. X    lineup_to_parens = 1;    /* -lp */
  151. X    ps.ljust_decl = 0;        /* -ndj */
  152. X    ps.com_ind = 33;        /* -c33 */
  153. X    star_comment_cont = 1;    /* -sc */
  154. X    ps.ind_size = 8;        /* -i8 */
  155. X    verbose = 0;
  156. X    ps.decl_indent = 16;    /* -di16 */
  157. X    ps.indent_parameters = 1;    /* -ip */
  158. X    ps.decl_com_ind = 0;    /* if this is not set to some positive value
  159. X                 * by an arg, we will set this equal to
  160. X                 * ps.com_ind */
  161. X    btype_2 = 1;        /* -br */
  162. X    cuddle_else = 1;        /* -ce */
  163. X    ps.unindent_displace = 0;    /* -d0 */
  164. X    ps.case_indent = 0;        /* -cli0 */
  165. X    format_col1_comments = 1;    /* -fc1 */
  166. X    procnames_start_line = 1;    /* -psl */
  167. X    proc_calls_space = 0;    /* -npcs */
  168. X    comment_delimiter_on_blankline = 1;    /* -cdb */
  169. X    ps.leave_comma = 1;        /* -nbc */
  170. X#endif
  171. X
  172. X    for (i = 1; i < argc; ++i)
  173. X    if (strcmp(argv[i], "-npro") == 0)
  174. X        break;
  175. X    set_defaults();
  176. X    if (i >= argc)
  177. X    set_profile();
  178. X
  179. X    for (i = 1; i < argc; ++i) {
  180. X
  181. X    /*
  182. X     * look thru args (if any) for changes to defaults
  183. X     */
  184. X    if (argv[i][0] != '-') {/* no flag on parameter */
  185. X        if (input == 0) {    /* we must have the input file */
  186. X        in_name = argv[i];    /* remember name of input file */
  187. X        input = fopen(in_name, "r");
  188. X        if (input == 0) {    /* check for open error */
  189. X            fprintf(stderr, "indent: can't open %s\n", argv[i]);
  190. X            exit(1);
  191. X        }
  192. X        continue;
  193. X        }
  194. X        else if (output == 0) {    /* we have the output file */
  195. X        out_name = argv[i];    /* remember name of output file */
  196. X        if (strcmp(in_name, out_name) == 0) {    /* attempt to overwrite
  197. X                             * the file */
  198. X            fprintf(stderr, "indent: input and output files must be different\n");
  199. X            exit(1);
  200. X        }
  201. X        output = fopen(out_name, "w");
  202. X        if (output == 0) {    /* check for create error */
  203. X            fprintf(stderr, "indent: can't create %s\n", argv[i]);
  204. X            exit(1);
  205. X        }
  206. X        continue;
  207. X        }
  208. X        fprintf(stderr, "indent: unknown parameter: %s\n", argv[i]);
  209. X        exit(1);
  210. X    }
  211. X    else
  212. X        set_option(argv[i]);
  213. X    }                /* end of for */
  214. X    if (input == 0) {
  215. X    fprintf(stderr, "indent: usage: indent file [ outfile ] [ options ]\n");
  216. X    exit(1);
  217. X    }
  218. X    if (output == 0)
  219. X    if (troff)
  220. X        output = stdout;
  221. X    else {
  222. X        out_name = in_name;
  223. X        bakcopy();
  224. X    }
  225. X    if (ps.com_ind <= 1)
  226. X    ps.com_ind = 2;        /* dont put normal comments before column 2 */
  227. X    if (troff) {
  228. X    if (bodyf.font[0] == 0)
  229. X        parsefont(&bodyf, "R");
  230. X    if (scomf.font[0] == 0)
  231. X        parsefont(&scomf, "I");
  232. X    if (blkcomf.font[0] == 0)
  233. X        blkcomf = scomf, blkcomf.size += 2;
  234. X    if (boxcomf.font[0] == 0)
  235. X        boxcomf = blkcomf;
  236. X    if (stringf.font[0] == 0)
  237. X        parsefont(&stringf, "L");
  238. X    if (keywordf.font[0] == 0)
  239. X        parsefont(&keywordf, "B");
  240. X    writefdef(&bodyf, 'B');
  241. X    writefdef(&scomf, 'C');
  242. X    writefdef(&blkcomf, 'L');
  243. X    writefdef(&boxcomf, 'X');
  244. X    writefdef(&stringf, 'S');
  245. X    writefdef(&keywordf, 'K');
  246. X    }
  247. X    if (block_comment_max_col <= 0)
  248. X    block_comment_max_col = max_col;
  249. X    if (ps.decl_com_ind <= 0)    /* if not specified by user, set this */
  250. X    ps.decl_com_ind = ps.ljust_decl ? (ps.com_ind <= 10 ? 2 : ps.com_ind - 8) : ps.com_ind;
  251. X    if (continuation_indent == 0)
  252. X    continuation_indent = ps.ind_size;
  253. X    fill_buffer();        /* get first batch of stuff into input buffer */
  254. X
  255. X    parse(semicolon);
  256. X    {
  257. X    register char *p = buf_ptr;
  258. X    register    col = 1;
  259. X
  260. X    while (1) {
  261. X        if (*p == ' ')
  262. X        col++;
  263. X        else if (*p == '\t')
  264. X        col = ((col - 1) & ~7) + 9;
  265. X        else
  266. X        break;
  267. X        p++;
  268. X    };
  269. X    if (col > ps.ind_size)
  270. X        ps.ind_level = ps.i_l_follow = col / ps.ind_size;
  271. X    }
  272. X    if (troff) {
  273. X    register char *p = in_name,
  274. X               *beg = in_name;
  275. X
  276. X    while (*p)
  277. X        if (*p++ == '/')
  278. X        beg = p;
  279. X    fprintf(output, ".Fn \"%s\"\n", beg);
  280. X    }
  281. X    /*
  282. X     * START OF MAIN LOOP
  283. X     */
  284. X
  285. X    while (1) {            /* this is the main loop.  it will go until we
  286. X                 * reach eof */
  287. X    int         is_procname;
  288. X
  289. X    type_code = lexi();    /* lexi reads one token.  The actual
  290. X                 * characters read are stored in "token". lexi
  291. X                 * returns a code indicating the type of token */
  292. X    is_procname = ps.procname[0];
  293. X
  294. X    /*
  295. X     * The following code moves everything following an if (), while (),
  296. X     * else, etc. up to the start of the following stmt to a buffer. This
  297. X     * allows proper handling of both kinds of brace placement.
  298. X     */
  299. X
  300. X    flushed_nl = false;
  301. X    while (ps.search_brace) {    /* if we scanned an if(), while(),
  302. X                     * etc., we might need to copy stuff
  303. X                     * into a buffer we must loop, copying
  304. X                     * stuff into save_com, until we find
  305. X                     * the start of the stmt which follows
  306. X                     * the if, or whatever */
  307. X        switch (type_code) {
  308. X        case newline:
  309. X        ++line_no;
  310. X        flushed_nl = true;
  311. X        case form_feed:
  312. X        break;        /* form feeds and newlines found here will be
  313. X                 * ignored */
  314. X
  315. X        case lbrace:    /* this is a brace that starts the compound
  316. X                 * stmt */
  317. X        if (sc_end == 0) {    /* ignore buffering if a comment wasnt
  318. X                     * stored up */
  319. X            ps.search_brace = false;
  320. X            goto check_type;
  321. X        }
  322. X        if (btype_2) {
  323. X            save_com[0] = '{';    /* we either want to put the brace
  324. X                     * right after the if */
  325. X            goto sw_buffer;    /* go to common code to get out of
  326. X                     * this loop */
  327. X        }
  328. X        case comment:    /* we have a comment, so we must copy it into
  329. X                 * the buffer */
  330. X        if (!flushed_nl || sc_end != 0) {
  331. X            if (sc_end == 0) {    /* if this is the first comment, we
  332. X                     * must set up the buffer */
  333. X            save_com[0] = save_com[1] = ' ';
  334. X            sc_end = &(save_com[2]);
  335. X            }
  336. X            else {
  337. X            *sc_end++ = '\n';    /* add newline between
  338. X                         * comments */
  339. X            *sc_end++ = ' ';
  340. X            --line_no;
  341. X            }
  342. X            *sc_end++ = '/';    /* copy in start of comment */
  343. X            *sc_end++ = '*';
  344. X
  345. X            for (;;) {    /* loop until we get to the end of the comment */
  346. X            *sc_end = *buf_ptr++;
  347. X            if (buf_ptr >= buf_end)
  348. X                fill_buffer();
  349. X
  350. X            if (*sc_end++ == '*' && *buf_ptr == '/')
  351. X                break;    /* we are at end of comment */
  352. X
  353. X            if (sc_end >= &(save_com[sc_size])) {    /* check for temp buffer
  354. X                                 * overflow */
  355. X                diag(1, "Internal buffer overflow - Move big comment from right after if, while, or whatever.");
  356. X                fflush(output);
  357. X                exit(1);
  358. X            }
  359. X            }
  360. X            *sc_end++ = '/';    /* add ending slash */
  361. X            if (++buf_ptr >= buf_end)    /* get past / in buffer */
  362. X            fill_buffer();
  363. X            break;
  364. X        }
  365. X        default:        /* it is the start of a normal statment */
  366. X        if (flushed_nl)    /* if we flushed a newline, make sure it is
  367. X                 * put back */
  368. X            force_nl = true;
  369. X        if (type_code == sp_paren && *token == 'i'
  370. X            && last_else && ps.else_if
  371. X            || type_code == sp_nparen && *token == 'e'
  372. X            && e_code != s_code && e_code[-1] == '}')
  373. X            force_nl = false;
  374. X
  375. X        if (sc_end == 0) {    /* ignore buffering if comment wasnt
  376. X                     * saved up */
  377. X            ps.search_brace = false;
  378. X            goto check_type;
  379. X        }
  380. X        if (force_nl) {    /* if we should insert a nl here, put it into
  381. X                 * the buffer */
  382. X            force_nl = false;
  383. X            --line_no;    /* this will be re-increased when the nl is
  384. X                 * read from the buffer */
  385. X            *sc_end++ = '\n';
  386. X            *sc_end++ = ' ';
  387. X            if (verbose && !flushed_nl)    /* print error msg if the line
  388. X                         * was not already broken */
  389. X            diag(0, "Line broken");
  390. X            flushed_nl = false;
  391. X        }
  392. X        for (t_ptr = token; *t_ptr; ++t_ptr)
  393. X            *sc_end++ = *t_ptr;    /* copy token into temp buffer */
  394. X        ps.procname[0] = 0;
  395. X
  396. X    sw_buffer:
  397. X        ps.search_brace = false;    /* stop looking for start of
  398. X                         * stmt */
  399. X        bp_save = buf_ptr;    /* save current input buffer */
  400. X        be_save = buf_end;
  401. X        buf_ptr = save_com;    /* fix so that subsequent calls to
  402. X                     * lexi will take tokens out of
  403. X                     * save_com */
  404. X        *sc_end++ = ' ';/* add trailing blank, just in case */
  405. X        buf_end = sc_end;
  406. X        sc_end = 0;
  407. X        break;
  408. X        }            /* end of switch */
  409. X        if (type_code != 0)    /* we must make this check, just in case there
  410. X                 * was an unexpected EOF */
  411. X        type_code = lexi();    /* read another token */
  412. X        /* if (ps.search_brace) ps.procname[0] = 0; */
  413. X        if ((is_procname = ps.procname[0]) && flushed_nl
  414. X            && !procnames_start_line && ps.in_decl
  415. X            && type_code == ident)
  416. X        flushed_nl = 0;
  417. X    }            /* end of while (search_brace) */
  418. X    last_else = 0;
  419. Xcheck_type:
  420. X    if (type_code == 0) {    /* we got eof */
  421. X        if (s_lab != e_lab || s_code != e_code
  422. X            || s_com != e_com)    /* must dump end of line */
  423. X        dump_line();
  424. X        if (ps.tos > 1)    /* check for balanced braces */
  425. X        diag(1, "Stuff missing from end of file.");
  426. X
  427. X        if (verbose) {
  428. X        printf("There were %d output lines and %d comments\n",
  429. X               ps.out_lines, ps.out_coms);
  430. X        printf("(Lines with comments)/(Lines with code): %6.3f\n",
  431. X               (1.0 * ps.com_lines) / code_lines);
  432. X        }
  433. X        fflush(output);
  434. X        exit(found_err);
  435. X    }
  436. X    if (
  437. X        (type_code != comment) &&
  438. X        (type_code != newline) &&
  439. X        (type_code != preesc) &&
  440. X        (type_code != form_feed)) {
  441. X        if (force_nl &&
  442. X            (type_code != semicolon) &&
  443. X            (type_code != lbrace || !btype_2)) {
  444. X        /* we should force a broken line here */
  445. X        if (verbose && !flushed_nl)
  446. X            diag(0, "Line broken");
  447. X        flushed_nl = false;
  448. X        dump_line();
  449. X        ps.want_blank = false;    /* dont insert blank at line start */
  450. X        force_nl = false;
  451. X        }
  452. X        ps.in_stmt = true;    /* turn on flag which causes an extra level of
  453. X                 * indentation. this is turned off by a ; or
  454. X                 * '}' */
  455. X        if (s_com != e_com) {    /* the turkey has embedded a comment
  456. X                     * in a line. fix it */
  457. X        *e_code++ = ' ';
  458. X        for (t_ptr = s_com; *t_ptr; ++t_ptr) {
  459. X            check_size(code);
  460. X            *e_code++ = *t_ptr;
  461. X        }
  462. X        *e_code++ = ' ';
  463. X        *e_code = '\0';    /* null terminate code sect */
  464. X        ps.want_blank = false;
  465. X        e_com = s_com;
  466. X        }
  467. X    }
  468. X    else if (type_code != comment)    /* preserve force_nl thru a comment */
  469. X        force_nl = false;    /* cancel forced newline after newline, form
  470. X                 * feed, etc */
  471. X
  472. X
  473. X
  474. X    /*-----------------------------------------------------*\
  475. X    |       do switch on type of token scanned        |
  476. X    \*-----------------------------------------------------*/
  477. X    check_size(code);
  478. X    switch (type_code) {    /* now, decide what to do with the token */
  479. X
  480. X    case form_feed:    /* found a form feed in line */
  481. X        ps.use_ff = true;    /* a form feed is treated much like a newline */
  482. X        dump_line();
  483. X        ps.want_blank = false;
  484. X        break;
  485. X
  486. X    case newline:
  487. X        if (ps.last_token != comma || ps.p_l_follow > 0
  488. X            || !ps.leave_comma || ps.block_init || !break_comma || s_com != e_com) {
  489. X        dump_line();
  490. X        ps.want_blank = false;
  491. X        }
  492. X        ++line_no;        /* keep track of input line number */
  493. X        break;
  494. X
  495. X    case lparen:        /* got a '(' or '[' */
  496. X        ++ps.p_l_follow;    /* count parens to make Healy happy */
  497. X        if (ps.want_blank && *token != '[' &&
  498. X            (ps.last_token != ident || proc_calls_space
  499. X          || (ps.its_a_keyword && (!ps.sizeof_keyword || Bill_Shannon))))
  500. X        *e_code++ = ' ';
  501. X        if (ps.in_decl && !ps.block_init)
  502. X        if (troff && !ps.dumped_decl_indent && !is_procname && ps.last_token == decl) {
  503. X            ps.dumped_decl_indent = 1;
  504. X            sprintf(e_code, "\n.Du %dp+\200p \"%s\"\n", dec_ind * 7, token);
  505. X            e_code += strlen(e_code);
  506. X        }
  507. X        else {
  508. X            while ((e_code - s_code) < dec_ind) {
  509. X            check_size(code);
  510. X            *e_code++ = ' ';
  511. X            }
  512. X            *e_code++ = token[0];
  513. X        }
  514. X        else
  515. X        *e_code++ = token[0];
  516. X        ps.paren_indents[ps.p_l_follow - 1] = e_code - s_code;
  517. X        if (sp_sw && ps.p_l_follow == 1 && extra_expression_indent
  518. X            && ps.paren_indents[0] < 2 * ps.ind_size)
  519. X        ps.paren_indents[0] = 2 * ps.ind_size;
  520. X        ps.want_blank = false;
  521. X        if (ps.in_or_st && *token == '(' && ps.tos <= 2) {
  522. X        /*
  523. X         * this is a kluge to make sure that declarations will be
  524. X         * aligned right if proc decl has an explicit type on it, i.e.
  525. X         * "int a(x) {..."
  526. X         */
  527. X        parse(semicolon);    /* I said this was a kluge... */
  528. X        ps.in_or_st = false;    /* turn off flag for structure decl or
  529. X                     * initialization */
  530. X        }
  531. X        if (ps.sizeof_keyword)
  532. X        ps.sizeof_mask |= 1 << ps.p_l_follow;
  533. X        break;
  534. X
  535. X    case rparen:        /* got a ')' or ']' */
  536. X        if (ps.cast_mask & (1 << ps.p_l_follow) & ~ps.sizeof_mask) {
  537. X        ps.last_u_d = true;
  538. X        ps.cast_mask &= (1 << ps.p_l_follow) - 1;
  539. X        }
  540. X        ps.sizeof_mask &= (1 << ps.p_l_follow) - 1;
  541. X        if (--ps.p_l_follow < 0) {
  542. X        ps.p_l_follow = 0;
  543. X        diag(0, "Extra %c", *token);
  544. X        }
  545. X        if (e_code == s_code)    /* if the paren starts the line */
  546. X        ps.paren_level = ps.p_l_follow;    /* then indent it */
  547. X
  548. X        *e_code++ = token[0];
  549. X        ps.want_blank = true;
  550. X
  551. X        if (sp_sw && (ps.p_l_follow == 0)) {    /* check for end of if
  552. X                             * (...), or some such */
  553. X        sp_sw = false;
  554. X        force_nl = true;/* must force newline after if */
  555. X        ps.last_u_d = true;    /* inform lexi that a following
  556. X                     * operator is unary */
  557. X        ps.in_stmt = false;    /* dont use stmt continuation
  558. X                     * indentation */
  559. X
  560. X        parse(hd_type);    /* let parser worry about if, or whatever */
  561. X        }
  562. X        ps.search_brace = btype_2;    /* this should insure that constructs
  563. X                     * such as main(){...} and int[]{...}
  564. X                     * have their braces put in the right
  565. X                     * place */
  566. X        break;
  567. X
  568. X    case unary_op:        /* this could be any unary operation */
  569. X        if (ps.want_blank)
  570. X        *e_code++ = ' ';
  571. X
  572. X        if (troff && !ps.dumped_decl_indent && ps.in_decl && !is_procname) {
  573. X        sprintf(e_code, "\n.Du %dp+\200p \"%s\"\n", dec_ind * 7, token);
  574. X        ps.dumped_decl_indent = 1;
  575. X        e_code += strlen(e_code);
  576. X        }
  577. X        else {
  578. X        char       *res = token;
  579. X
  580. X        if (ps.in_decl && !ps.block_init) {    /* if this is a unary op
  581. X                             * in a declaration, we
  582. X                             * should indent this
  583. X                             * token */
  584. X            for (i = 0; token[i]; ++i);    /* find length of token */
  585. X            while ((e_code - s_code) < (dec_ind - i)) {
  586. X            check_size(code);
  587. X            *e_code++ = ' ';    /* pad it */
  588. X            }
  589. X        }
  590. X        if (troff && token[0] == '-' && token[1] == '>')
  591. X            res = "\\(->";
  592. X        for (t_ptr = res; *t_ptr; ++t_ptr) {
  593. X            check_size(code);
  594. X            *e_code++ = *t_ptr;
  595. X        }
  596. X        }
  597. X        ps.want_blank = false;
  598. X        break;
  599. X
  600. X    case binary_op:    /* any binary operation */
  601. X    do_binary:
  602. X        if (ps.want_blank)
  603. X        *e_code++ = ' ';
  604. X        {
  605. X        char       *res = token;
  606. X
  607. X        if (troff)
  608. X            switch (token[0]) {
  609. X            case '<':
  610. X            if (token[1] == '=')
  611. X                res = "\\(<=";
  612. X            break;
  613. X            case '>':
  614. X            if (token[1] == '=')
  615. X                res = "\\(>=";
  616. X            break;
  617. X            case '!':
  618. X            if (token[1] == '=')
  619. X                res = "\\(!=";
  620. X            break;
  621. X            case '|':
  622. X            if (token[1] == '|')
  623. X                res = "\\(br\\(br";
  624. X            else if (token[1] == 0)
  625. X                res = "\\(br";
  626. X            break;
  627. X            }
  628. X        for (t_ptr = res; *t_ptr; ++t_ptr) {
  629. X            check_size(code);
  630. X            *e_code++ = *t_ptr;    /* move the operator */
  631. X        }
  632. X        }
  633. X        ps.want_blank = true;
  634. X        break;
  635. X
  636. X    case postop:        /* got a trailing ++ or -- */
  637. X        *e_code++ = token[0];
  638. X        *e_code++ = token[1];
  639. X        ps.want_blank = true;
  640. X        break;
  641. X
  642. X    case question:        /* got a ? */
  643. X        squest++;        /* this will be used when a later colon
  644. X                 * appears so we can distinguish the
  645. X                 * <c>?<n>:<n> construct */
  646. X        if (ps.want_blank)
  647. X        *e_code++ = ' ';
  648. X        *e_code++ = '?';
  649. X        ps.want_blank = true;
  650. X        break;
  651. X
  652. X    case casestmt:        /* got word 'case' or 'default' */
  653. X        scase = true;    /* so we can process the later colon properly */
  654. X        goto copy_id;
  655. X
  656. X    case colon:        /* got a ':' */
  657. X        if (squest > 0) {    /* it is part of the <c>?<n>: <n> construct */
  658. X        --squest;
  659. X        if (ps.want_blank)
  660. X            *e_code++ = ' ';
  661. X        *e_code++ = ':';
  662. X        ps.want_blank = true;
  663. X        break;
  664. X        }
  665. X        if (ps.in_decl) {
  666. X        *e_code++ = ':';
  667. X        ps.want_blank = false;
  668. X        break;
  669. X        }
  670. X        ps.in_stmt = false;    /* seeing a label does not imply we are in a
  671. X                 * stmt */
  672. X        for (t_ptr = s_code; *t_ptr; ++t_ptr)
  673. X        *e_lab++ = *t_ptr;    /* turn everything so far into a label */
  674. X        e_code = s_code;
  675. X        *e_lab++ = ':';
  676. X        *e_lab++ = ' ';
  677. X        *e_lab = '\0';
  678. X
  679. X        force_nl = ps.pcase = scase;    /* ps.pcase will be used by
  680. X                         * dump_line to decide how to
  681. X                         * indent the label. force_nl
  682. X                         * will force a case n: to be
  683. X                         * on a line by itself */
  684. X        scase = false;
  685. X        ps.want_blank = false;
  686. X        break;
  687. X
  688. X    case semicolon:    /* got a ';' */
  689. X        ps.in_or_st = false;/* we are not in an initialization or
  690. X                 * structure declaration */
  691. X        scase = false;    /* these will only need resetting in a error */
  692. X        squest = 0;
  693. X        if (ps.last_token == rparen)
  694. X        ps.in_parameter_declaration = 0;
  695. X        ps.cast_mask = 0;
  696. X        ps.sizeof_mask = 0;
  697. X        ps.block_init = 0;
  698. X        ps.block_init_level = 0;
  699. X        ps.just_saw_decl--;
  700. X
  701. X        if (ps.in_decl && s_code == e_code && !ps.block_init)
  702. X        while ((e_code - s_code) < (dec_ind - 1)) {
  703. X            check_size(code);
  704. X            *e_code++ = ' ';
  705. X        }
  706. X
  707. X        ps.in_decl = (ps.dec_nest > 0);    /* if we were in a first level
  708. X                         * structure declaration, we
  709. X                         * arent any more */
  710. X
  711. X        if ((!sp_sw || hd_type != forstmt) && ps.p_l_follow > 0) {
  712. X
  713. X        /*
  714. X         * This should be true iff there were unbalanced parens in the
  715. X         * stmt.  It is a bit complicated, because the semicolon might
  716. X         * be in a for stmt
  717. X         */
  718. X        diag(1, "Unbalanced parens");
  719. X        ps.p_l_follow = 0;
  720. X        if (sp_sw) {    /* this is a check for a if, while, etc. with
  721. X                 * unbalanced parens */
  722. X            sp_sw = false;
  723. X            parse(hd_type);    /* dont lose the if, or whatever */
  724. X        }
  725. X        }
  726. X        *e_code++ = ';';
  727. X        ps.want_blank = true;
  728. X        ps.in_stmt = (ps.p_l_follow > 0);    /* we are no longer in the
  729. X                         * middle of a stmt */
  730. X
  731. X        if (!sp_sw) {    /* if not if for (;;) */
  732. X        parse(semicolon);    /* let parser know about end of stmt */
  733. X        force_nl = true;/* force newline after a end of stmt */
  734. X        }
  735. X        break;
  736. X
  737. X    case lbrace:        /* got a '{' */
  738. X        ps.in_stmt = false;    /* dont indent the {} */
  739. X        if (!ps.block_init)
  740. X        force_nl = true;/* force other stuff on same line as '{' onto
  741. X                 * new line */
  742. X        else if (ps.block_init_level <= 0)
  743. X        ps.block_init_level = 1;
  744. X        else
  745. X        ps.block_init_level++;
  746. X
  747. X        if (s_code != e_code && !ps.block_init) {
  748. X        if (!btype_2) {
  749. X            dump_line();
  750. X            ps.want_blank = false;
  751. X        }
  752. X        else if (ps.in_parameter_declaration && !ps.in_or_st) {
  753. X            ps.i_l_follow = 0;
  754. X            dump_line();
  755. X            ps.want_blank = false;
  756. X        }
  757. X        }
  758. X        if (ps.in_parameter_declaration)
  759. X        prefix_blankline_requested = 0;
  760. X
  761. X        if (ps.p_l_follow > 0) {    /* check for preceeding unbalanced
  762. X                     * parens */
  763. X        diag(1, "Unbalanced parens");
  764. X        ps.p_l_follow = 0;
  765. X        if (sp_sw) {    /* check for unclosed if, for, etc. */
  766. X            sp_sw = false;
  767. X            parse(hd_type);
  768. X            ps.ind_level = ps.i_l_follow;
  769. X        }
  770. X        }
  771. X        if (s_code == e_code)
  772. X        ps.ind_stmt = false;    /* dont put extra indentation on line
  773. X                     * with '{' */
  774. X        if (ps.in_decl && ps.in_or_st) {    /* this is either a structure
  775. X                         * declaration or an init */
  776. X        di_stack[ps.dec_nest++] = dec_ind;
  777. X        /* ?        dec_ind = 0; */
  778. X        }
  779. X        else {
  780. X        ps.decl_on_line = false;    /* we cant be in the middle of
  781. X                         * a declaration, so dont do
  782. X                         * special indentation of
  783. X                         * comments */
  784. X        if (blanklines_after_declarations_at_proctop
  785. X            && ps.in_parameter_declaration)
  786. X            postfix_blankline_requested = 1;
  787. X        ps.in_parameter_declaration = 0;
  788. X        }
  789. X        dec_ind = 0;
  790. X        parse(lbrace);    /* let parser know about this */
  791. X        if (ps.want_blank)    /* put a blank before '{' if '{' is not at
  792. X                 * start of line */
  793. X        *e_code++ = ' ';
  794. X        ps.want_blank = false;
  795. X        *e_code++ = '{';
  796. X        ps.just_saw_decl = 0;
  797. X        break;
  798. X
  799. X    case rbrace:        /* got a '}' */
  800. X        if (ps.p_stack[ps.tos] == decl && !ps.block_init)    /* semicolons can be
  801. X                                 * omitted in
  802. X                                 * declarations */
  803. X        parse(semicolon);
  804. X        if (ps.p_l_follow) {/* check for unclosed if, for, else. */
  805. X        diag(1, "Unbalanced parens");
  806. X        ps.p_l_follow = 0;
  807. X        sp_sw = false;
  808. X        }
  809. X        ps.just_saw_decl = 0;
  810. X        ps.block_init_level--;
  811. X        if (s_code != e_code && !ps.block_init) {    /* '}' must be first on
  812. X                             * line */
  813. X        if (verbose)
  814. X            diag(0, "Line broken");
  815. X        dump_line();
  816. X        }
  817. X        *e_code++ = '}';
  818. X        ps.want_blank = true;
  819. X        ps.in_stmt = ps.ind_stmt = false;
  820. X        if (ps.dec_nest > 0) {    /* we are in multi-level structure
  821. X                     * declaration */
  822. X        dec_ind = di_stack[--ps.dec_nest];
  823. X        if (ps.dec_nest == 0 && !ps.in_parameter_declaration)
  824. X            ps.just_saw_decl = 2;
  825. X        ps.in_decl = true;
  826. X        }
  827. X        prefix_blankline_requested = 0;
  828. X        parse(rbrace);    /* let parser know about this */
  829. X        ps.search_brace = cuddle_else && ps.p_stack[ps.tos] == ifhead
  830. X        && ps.il[ps.tos] >= ps.ind_level;
  831. X        if (ps.tos <= 1 && blanklines_after_procs && ps.dec_nest <= 0)
  832. X        postfix_blankline_requested = 1;
  833. X        break;
  834. X
  835. X    case swstmt:        /* got keyword "switch" */
  836. X        sp_sw = true;
  837. X        hd_type = swstmt;    /* keep this for when we have seen the
  838. X                 * expression */
  839. X        goto copy_id;    /* go move the token into buffer */
  840. X
  841. X    case sp_paren:        /* token is if, while, for */
  842. X        sp_sw = true;    /* the interesting stuff is done after the
  843. X                 * expression is scanned */
  844. X        hd_type = (*token == 'i' ? ifstmt :
  845. X               (*token == 'w' ? whilestmt : forstmt));
  846. X
  847. X        /*
  848. X         * remember the type of header for later use by parser
  849. X         */
  850. X        goto copy_id;    /* copy the token into line */
  851. X
  852. X    case sp_nparen:    /* got else, do */
  853. X        ps.in_stmt = false;
  854. X        if (*token == 'e') {
  855. X        if (e_code != s_code && (!cuddle_else || e_code[-1] != '}')) {
  856. X            if (verbose)
  857. X            diag(0, "Line broken");
  858. X            dump_line();/* make sure this starts a line */
  859. X            ps.want_blank = false;
  860. X        }
  861. X        force_nl = true;/* also, following stuff must go onto new line */
  862. X        last_else = 1;
  863. X        parse(elselit);
  864. X        }
  865. X        else {
  866. X        if (e_code != s_code) {    /* make sure this starts a line */
  867. X            if (verbose)
  868. X            diag(0, "Line broken");
  869. X            dump_line();
  870. X            ps.want_blank = false;
  871. X        }
  872. X        force_nl = true;/* also, following stuff must go onto new line */
  873. X        last_else = 0;
  874. X        parse(dolit);
  875. X        }
  876. X        goto copy_id;    /* move the token into line */
  877. X
  878. X    case decl:        /* we have a declaration type (int, register,
  879. X                 * etc.) */
  880. X        parse(decl);    /* let parser worry about indentation */
  881. X        if (ps.last_token == rparen && ps.tos <= 1) {
  882. X        ps.in_parameter_declaration = 1;
  883. X        if (s_code != e_code) {
  884. X            dump_line();
  885. X            ps.want_blank = 0;
  886. X        }
  887. X        }
  888. X        if (ps.in_parameter_declaration && ps.indent_parameters && ps.dec_nest == 0) {
  889. X        ps.ind_level = ps.i_l_follow = 1;
  890. X        ps.ind_stmt = 0;
  891. X        }
  892. X        ps.in_or_st = true;    /* this might be a structure or initialization
  893. X                 * declaration */
  894. X        ps.in_decl = ps.decl_on_line = true;
  895. X        if ( /* !ps.in_or_st && */ ps.dec_nest <= 0)
  896. X        ps.just_saw_decl = 2;
  897. X        prefix_blankline_requested = 0;
  898. X        for (i = 0; token[i++];);    /* get length of token */
  899. X
  900. X        /*
  901. X         * dec_ind = e_code - s_code + (ps.decl_indent>i ? ps.decl_indent
  902. X         * : i);
  903. X         */
  904. X        dec_ind = ps.decl_indent > 0 ? ps.decl_indent : i;
  905. X        goto copy_id;
  906. X
  907. X    case ident:        /* got an identifier or constant */
  908. X        if (ps.in_decl) {    /* if we are in a declaration, we must indent
  909. X                 * identifier */
  910. X        if (ps.want_blank)
  911. X            *e_code++ = ' ';
  912. X        ps.want_blank = false;
  913. X        if (is_procname == 0 || !procnames_start_line) {
  914. X            if (!ps.block_init)
  915. X            if (troff && !ps.dumped_decl_indent) {
  916. X                sprintf(e_code, "\n.De %dp+\200p\n", dec_ind * 7);
  917. X                ps.dumped_decl_indent = 1;
  918. X                e_code += strlen(e_code);
  919. X            }
  920. X            else
  921. X                while ((e_code - s_code) < dec_ind) {
  922. X                check_size(code);
  923. X                *e_code++ = ' ';
  924. X                }
  925. X        }
  926. X        else {
  927. X            if (dec_ind && s_code != e_code)
  928. X            dump_line();
  929. X            dec_ind = 0;
  930. X            ps.want_blank = false;
  931. X        }
  932. X        }
  933. X        else if (sp_sw && ps.p_l_follow == 0) {
  934. X        sp_sw = false;
  935. X        force_nl = true;
  936. X        ps.last_u_d = true;
  937. X        ps.in_stmt = false;
  938. X        parse(hd_type);
  939. X        }
  940. X    copy_id:
  941. X        if (ps.want_blank)
  942. X        *e_code++ = ' ';
  943. X        if (troff && ps.its_a_keyword) {
  944. X        e_code = chfont(&bodyf, &keywordf, e_code);
  945. X        for (t_ptr = token; *t_ptr; ++t_ptr) {
  946. X            check_size(code);
  947. X            *e_code++ = keywordf.allcaps && islower(*t_ptr)
  948. X            ? toupper(*t_ptr) : *t_ptr;
  949. X        }
  950. X        e_code = chfont(&keywordf, &bodyf, e_code);
  951. X        }
  952. X        else
  953. X        for (t_ptr = token; *t_ptr; ++t_ptr) {
  954. X            check_size(code);
  955. X            *e_code++ = *t_ptr;
  956. X        }
  957. X        ps.want_blank = true;
  958. X        break;
  959. X
  960. X    case period:        /* treat a period kind of like a binary
  961. X                 * operation */
  962. X        *e_code++ = '.';    /* move the period into line */
  963. X        ps.want_blank = false;    /* dont put a blank after a period */
  964. X        break;
  965. X
  966. X    case comma:
  967. X        ps.want_blank = (s_code != e_code);    /* only put blank after comma
  968. X                         * if comma does not start the
  969. X                         * line */
  970. X        if (ps.in_decl && is_procname == 0 && !ps.block_init)
  971. X        while ((e_code - s_code) < (dec_ind - 1)) {
  972. X            check_size(code);
  973. X            *e_code++ = ' ';
  974. X        }
  975. X
  976. X        *e_code++ = ',';
  977. X        if (ps.p_l_follow == 0) {
  978. X        if (ps.block_init_level <= 0)
  979. X            ps.block_init = 0;
  980. X        if (break_comma && !ps.leave_comma)
  981. X            force_nl = true;
  982. X        }
  983. X        break;
  984. X
  985. X    case preesc:        /* got the character '#' */
  986. X        if ((s_com != e_com) ||
  987. X            (s_lab != e_lab) ||
  988. X            (s_code != e_code))
  989. X        dump_line();
  990. X        *e_lab++ = '#';    /* move whole line to 'label' buffer */
  991. X        {
  992. X        int         in_comment = 0;
  993. X        int         com_start = 0;
  994. X        char        quote = 0;
  995. X        int         com_end = 0;
  996. X
  997. X        while (*buf_ptr != '\n' || in_comment) {
  998. X            check_size(lab);
  999. X            *e_lab = *buf_ptr++;
  1000. X            if (buf_ptr >= buf_end)
  1001. X            fill_buffer();
  1002. X            switch (*e_lab++) {
  1003. X            case BACKSLASH:
  1004. X            if (troff)
  1005. X                *e_lab++ = BACKSLASH;
  1006. X            if (!in_comment) {
  1007. X                *e_lab++ = *buf_ptr++;
  1008. X                if (buf_ptr >= buf_end)
  1009. X                fill_buffer();
  1010. X            }
  1011. X            break;
  1012. X            case '/':
  1013. X            if (*buf_ptr == '*' && !in_comment && !quote) {
  1014. X                in_comment = 1;
  1015. X                *e_lab++ = *buf_ptr++;
  1016. X                com_start = e_lab - s_lab - 2;
  1017. X            }
  1018. X            break;
  1019. X            case '"':
  1020. X            if (quote == '"')
  1021. X                quote = 0;
  1022. X            break;
  1023. X            case '\'':
  1024. X            if (quote == '\'')
  1025. X                quote = 0;
  1026. X            break;
  1027. X            case '*':
  1028. X            if (*buf_ptr == '/' && in_comment) {
  1029. X                in_comment = 0;
  1030. X                *e_lab++ = *buf_ptr++;
  1031. X                com_end = e_lab - s_lab;
  1032. X            }
  1033. X            break;
  1034. X            }
  1035. X        }
  1036. X
  1037. X        while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t'))
  1038. X            e_lab--;
  1039. X        if (e_lab - s_lab == com_end && bp_save == 0) {    /* comment on
  1040. X                                 * preprocessor line */
  1041. X            if (sc_end == 0)    /* if this is the first comment, we
  1042. X                     * must set up the buffer */
  1043. X            sc_end = &(save_com[0]);
  1044. X            else {
  1045. X            *sc_end++ = '\n';    /* add newline between
  1046. X                         * comments */
  1047. X            *sc_end++ = ' ';
  1048. X            --line_no;
  1049. X            }
  1050. X            bcopy(s_lab + com_start, sc_end, com_end - com_start);
  1051. X            sc_end += com_end - com_start;
  1052. X            if (sc_end >= &save_com[sc_size])
  1053. X            abort();
  1054. X            e_lab = s_lab + com_start;
  1055. X            while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t'))
  1056. X            e_lab--;
  1057. X            bp_save = buf_ptr;    /* save current input buffer */
  1058. X            be_save = buf_end;
  1059. X            buf_ptr = save_com;    /* fix so that subsequent calls to
  1060. X                     * lexi will take tokens out of
  1061. X                     * save_com */
  1062. X            *sc_end++ = ' ';    /* add trailing blank, just in case */
  1063. X            buf_end = sc_end;
  1064. X            sc_end = 0;
  1065. X        }
  1066. X        *e_lab = '\0';    /* null terminate line */
  1067. X        ps.pcase = false;
  1068. X        }
  1069. X
  1070. X        if (strncmp(s_lab, "#if", 3) == 0) {
  1071. X        if (blanklines_around_conditional_compilation) {
  1072. X            register    c;
  1073. X            prefix_blankline_requested++;
  1074. X            while ((c = getc(input)) == '\n');
  1075. X            ungetc(c, input);
  1076. X        }
  1077. X        if (ifdef_level < sizeof state_stack / sizeof state_stack[0]) {
  1078. X            match_state[ifdef_level].tos = -1;
  1079. X            state_stack[ifdef_level++] = ps;
  1080. X        }
  1081. X        else
  1082. X            diag(1, "#if stack overflow");
  1083. X        }
  1084. X        else if (strncmp(s_lab, "#else", 5) == 0)
  1085. X        if (ifdef_level <= 0)
  1086. X            diag(1, "Unmatched #else");
  1087. X        else {
  1088. X            match_state[ifdef_level - 1] = ps;
  1089. X            ps = state_stack[ifdef_level - 1];
  1090. X        }
  1091. X        else if (strncmp(s_lab, "#endif", 6) == 0) {
  1092. X        if (ifdef_level <= 0)
  1093. X            diag(1, "Unmatched #endif");
  1094. X        else {
  1095. X            ifdef_level--;
  1096. X
  1097. X#ifdef undef
  1098. X            /*
  1099. X             * This match needs to be more intelligent before the
  1100. X             * message is useful
  1101. X             */
  1102. X            if (match_state[ifdef_level].tos >= 0
  1103. X              && bcmp(&ps, &match_state[ifdef_level], sizeof ps))
  1104. X            diag(0, "Syntactically inconsistant #ifdef alternatives.");
  1105. X#endif
  1106. X        }
  1107. X        if (blanklines_around_conditional_compilation) {
  1108. X            postfix_blankline_requested++;
  1109. X            n_real_blanklines = 0;
  1110. X        }
  1111. X        }
  1112. X        break;        /* subsequent processing of the newline
  1113. X                 * character will cause the line to be printed */
  1114. X
  1115. X    case comment:        /* we have gotten a /*  this is a biggie */
  1116. X    proc_comment:
  1117. X        if (flushed_nl) {    /* we should force a broken line here */
  1118. X        flushed_nl = false;
  1119. X        dump_line();
  1120. X        ps.want_blank = false;    /* dont insert blank at line start */
  1121. X        force_nl = false;
  1122. X        }
  1123. X        pr_comment();
  1124. X        break;
  1125. X    }            /* end of big switch stmt */
  1126. X
  1127. X    *e_code = '\0';        /* make sure code section is null terminated */
  1128. X    if (type_code != comment && type_code != newline && type_code != preesc)
  1129. X        ps.last_token = type_code;
  1130. X    }                /* end of main while (1) loop */
  1131. X};
  1132. X
  1133. X/*
  1134. X * copy input file to backup file if in_name is /blah/blah/blah/file, then
  1135. X * backup file will be ".Bfile" then make the backup file the input and
  1136. X * original input file the output
  1137. X */
  1138. Xbakcopy()
  1139. X{
  1140. X    int         n,
  1141. X                bakchn;
  1142. X    char        buff[8 * 1024];
  1143. X    register char *p;
  1144. X
  1145. X    /* construct file name .Bfile */
  1146. X    for (p = in_name; *p; p++);    /* skip to end of string */
  1147. X    while (p > in_name && *p != '/')    /* find last '/' */
  1148. X    p--;
  1149. X    if (*p == '/')
  1150. X    p++;
  1151. X    sprintf(bakfile, "%s.BAK", p);
  1152. X
  1153. X    /* copy in_name to backup file */
  1154. X    bakchn = creat(bakfile, 0600);
  1155. X    if (bakchn < 0) {
  1156. X    fprintf(stderr, "indent: can't create backup file \"%s\"\n", bakfile);
  1157. X    exit(1);
  1158. X    }
  1159. X    while (n = read(fileno(input), buff, sizeof buff))
  1160. X    if (write(bakchn, buff, n) != n) {
  1161. X        fprintf(stderr, "indent: error writing backup file \"%s\"\n",
  1162. X            bakfile);
  1163. X        exit(1);
  1164. X    }
  1165. X    if (n < 0) {
  1166. X    fprintf(stderr, "indent: error reading input file \"%s\"\n", in_name);
  1167. X    exit(1);
  1168. X    }
  1169. X    close(bakchn);
  1170. X    fclose(input);
  1171. X
  1172. X    /* re-open backup file as the input file */
  1173. X    input = fopen(bakfile, "r");
  1174. X    if (input == 0) {
  1175. X    fprintf(stderr, "indent: can't re-open backup file\n");
  1176. X    exit(1);
  1177. X    }
  1178. X    /* now the original input file will be the output */
  1179. X    output = fopen(in_name, "w");
  1180. X    if (output == 0) {
  1181. X    fprintf(stderr, "indent: can't create %s\n", in_name);
  1182. X    unlink(bakfile);
  1183. X    exit(1);
  1184. X    }
  1185. X}
  1186. END_OF_FILE
  1187. if test 34171 -ne `wc -c <'indent/indent.c'`; then
  1188.     echo shar: \"'indent/indent.c'\" unpacked with wrong size!
  1189. fi
  1190. # end of 'indent/indent.c'
  1191. fi
  1192. echo shar: End of archive 3 \(of 3\).
  1193. cp /dev/null ark3isdone
  1194. MISSING=""
  1195. for I in 1 2 3 ; do
  1196.     if test ! -f ark${I}isdone ; then
  1197.     MISSING="${MISSING} ${I}"
  1198.     fi
  1199. done
  1200. if test "${MISSING}" = "" ; then
  1201.     echo You have unpacked all 3 archives.
  1202.     rm -f ark[1-9]isdone
  1203. else
  1204.     echo You still need to unpack the following archives:
  1205.     echo "        " ${MISSING}
  1206. fi
  1207. ##  End of shell archive.
  1208. exit 0
  1209.  
  1210.