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

  1. #    This is a shell archive.
  2. #    Remove everything above and including the cut line.
  3. #    Then run the rest of the file through sh.
  4. #----cut here-----cut here-----cut here-----cut here----#
  5. #!/bin/sh
  6. # shar:    Shell Archiver
  7. #    Run the following text with /bin/sh to create:
  8. #    args.c
  9. #    comment.c
  10. #    lexi.c
  11. #    parse.c
  12. # This archive created: Fri Apr 10 20:51:38 1992
  13. echo shar: extracting args.c
  14. sed 's/^X//' << \SHAR_EOF > args.c
  15. X/*
  16. X * Copyright (c) 1985 Sun Microsystems, Inc.
  17. X * Copyright (c) 1980 The Regents of the University of California.
  18. X * Copyright (c) 1976 Board of Trustees of the University of Illinois.
  19. X * All rights reserved.
  20. X *
  21. X * Redistribution and use in source and binary forms are permitted
  22. X * provided that the above copyright notice and this paragraph are
  23. X * duplicated in all such forms and that any documentation,
  24. X * advertising materials, and other materials related to such
  25. X * distribution and use acknowledge that the software was developed
  26. X * by the University of California, Berkeley, the University of Illinois,
  27. X * Urbana, and Sun Microsystems, Inc.  The name of either University
  28. X * or Sun Microsystems may not be used to endorse or promote products
  29. X * derived from this software without specific prior written permission.
  30. X * THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
  31. X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  32. X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  33. X */
  34. X
  35. X#ifndef lint
  36. Xstatic char sccsid[] = "@(#)args.c    5.6 (Berkeley) 88/09/15";
  37. X
  38. X#endif                            /* not lint */
  39. X
  40. X/*
  41. X * Argument scanning and profile reading code.  Default parameters are set
  42. X * here as well.
  43. X */
  44. X
  45. X#include "globals.h"
  46. X#include <sys/types.h>
  47. X#include <ctype.h>
  48. X
  49. X#ifdef MSDOS                    /* or OS/2 */
  50. X#include <stdlib.h>
  51. X#include <string.h>
  52. X#include <malloc.h>
  53. X#define index(a,b) strchr(a,b)
  54. X#else
  55. Xchar *getenv(), *index();
  56. X
  57. X#endif
  58. X
  59. X#ifdef ANSIC
  60. Xvoid scan_profile(FILE *);
  61. X#endif
  62. X
  63. X/* profile types */
  64. X#define    PRO_SPECIAL    1            /* special case */
  65. X#define    PRO_BOOL    2            /* boolean */
  66. X#define    PRO_INT        3            /* integer */
  67. X#define PRO_FONT    4            /* troff font */
  68. X
  69. X/* profile specials for booleans */
  70. X#define    ON        1                /* turn it on */
  71. X#define    OFF        0                /* turn it off */
  72. X
  73. X/* profile specials for specials */
  74. X#define    IGN        1                /* ignore it */
  75. X#define    CLI        2                /* case label indent (float) */
  76. X#define    STDIN        3            /* use stdin */
  77. X#define    KEY        4                /* type (keyword) */
  78. X#define    CCI        5                /* case code indent (float) */
  79. X
  80. X/*
  81. X * N.B.: because of the way the table here is scanned, options whose names are
  82. X * substrings of other options must occur later; that is, with -lp vs -l, -lp
  83. X * must be first.  Also, while (most) booleans occur more than once, the last
  84. X * default value is the one actually assigned.
  85. X */
  86. Xstruct pro
  87. X{
  88. X    char *p_name;                /* name, eg -bl, -cli */
  89. X    int p_type;                    /* type (int, bool, special) */
  90. X    int p_default;                /* the default value (if int) */
  91. X    int p_special;                /* depends on type */
  92. X    int *p_obj;                    /* the associated variable */
  93. X}   pro[] =
  94. X
  95. X{
  96. X
  97. X    "T", PRO_SPECIAL, 0, KEY, 0,
  98. X    "bacc", PRO_BOOL, false, ON, &blanklines_around_conditional_compilation,
  99. X    "badp", PRO_BOOL, false, ON, &blanklines_after_declarations_at_proctop,
  100. X    "bad", PRO_BOOL, false, ON, &blanklines_after_declarations,
  101. X    "bap", PRO_BOOL, false, ON, &blanklines_after_procs,
  102. X    "bbb", PRO_BOOL, false, ON, &blanklines_before_blockcomments,
  103. X    "bc", PRO_BOOL, true, OFF, &ps.leave_comma,
  104. X    "bl", PRO_BOOL, false, OFF, &btype_2,
  105. X    "brr", PRO_BOOL, false, ON, &btype_3,
  106. X    "br", PRO_BOOL, true, ON, &btype_2,
  107. X    "bs", PRO_BOOL, false, ON, &Bill_Shannon,
  108. X    "cdb", PRO_BOOL, true, ON, &comment_delimiter_on_blankline,
  109. X    "cd", PRO_INT, 0, 0, &ps.decl_com_ind,
  110. X    "ce", PRO_BOOL, true, ON, &cuddle_else,
  111. X    "ci", PRO_INT, 0, 0, &continuation_indent,
  112. X    "cli", PRO_SPECIAL, 0, CLI, 0,
  113. X    "cci", PRO_SPECIAL, 0, CCI, 0,
  114. X    "c", PRO_INT, 33, 0, &ps.com_ind,
  115. X    "di", PRO_INT, 16, 0, &ps.decl_indent,
  116. X    "dj", PRO_BOOL, false, ON, &ps.ljust_decl,
  117. X    "d", PRO_INT, 0, 0, &ps.unindent_displace,
  118. X    "eei", PRO_BOOL, false, ON, &extra_expression_indent,
  119. X    "ei", PRO_BOOL, true, ON, &ps.else_if,
  120. X    "fbc", PRO_FONT, 0, 0, (int *) &blkcomf,
  121. X    "fbx", PRO_FONT, 0, 0, (int *) &boxcomf,
  122. X    "fb", PRO_FONT, 0, 0, (int *) &bodyf,
  123. X    "fc1", PRO_BOOL, true, ON, &format_col1_comments,
  124. X    "fc", PRO_FONT, 0, 0, (int *) &scomf,
  125. X    "fk", PRO_FONT, 0, 0, (int *) &keywordf,
  126. X    "fs", PRO_FONT, 0, 0, (int *) &stringf,
  127. X    "ip", PRO_BOOL, true, ON, &ps.indent_parameters,
  128. X    "i", PRO_INT, 8, 0, &ps.ind_size,
  129. X    "lc", PRO_INT, 0, 0, &block_comment_max_col,
  130. X    "lp", PRO_BOOL, true, ON, &lineup_to_parens,
  131. X    "l", PRO_INT, 78, 0, &max_col,
  132. X    "nbacc", PRO_BOOL, false, OFF, &blanklines_around_conditional_compilation,
  133. X    "nbadp", PRO_BOOL, false, OFF, &blanklines_after_declarations_at_proctop,
  134. X    "nbad", PRO_BOOL, false, OFF, &blanklines_after_declarations,
  135. X    "nbap", PRO_BOOL, false, OFF, &blanklines_after_procs,
  136. X    "nbbb", PRO_BOOL, false, OFF, &blanklines_before_blockcomments,
  137. X    "nbc", PRO_BOOL, true, ON, &ps.leave_comma,
  138. X    "nbs", PRO_BOOL, false, OFF, &Bill_Shannon,
  139. X    "ncdb", PRO_BOOL, true, OFF, &comment_delimiter_on_blankline,
  140. X    "nce", PRO_BOOL, true, OFF, &cuddle_else,
  141. X    "ndj", PRO_BOOL, false, OFF, &ps.ljust_decl,
  142. X    "neei", PRO_BOOL, false, OFF, &extra_expression_indent,
  143. X    "nei", PRO_BOOL, true, OFF, &ps.else_if,
  144. X    "nfc1", PRO_BOOL, true, OFF, &format_col1_comments,
  145. X    "nip", PRO_BOOL, true, OFF, &ps.indent_parameters,
  146. X    "nlp", PRO_BOOL, true, OFF, &lineup_to_parens,
  147. X    "npcs", PRO_BOOL, false, OFF, &proc_calls_space,
  148. X    "npro", PRO_SPECIAL, 0, IGN, 0,
  149. X    "nprs", PRO_BOOL, false, OFF, &parens_space,
  150. X    "npsl", PRO_BOOL, true, OFF, &procnames_start_line,
  151. X    "nps", PRO_BOOL, false, OFF, &pointer_as_binop,
  152. X    "nsc", PRO_BOOL, true, OFF, &star_comment_cont,
  153. X    "nsob", PRO_BOOL, false, OFF, &swallow_optional_blanklines,
  154. X    "nv", PRO_BOOL, false, OFF, &verbose,
  155. X    "pcs", PRO_BOOL, false, ON, &proc_calls_space,
  156. X    "prs", PRO_BOOL, false, ON, &parens_space,
  157. X    "psl", PRO_BOOL, true, ON, &procnames_start_line,
  158. X    "ps", PRO_BOOL, false, ON, &pointer_as_binop,
  159. X    "sc", PRO_BOOL, true, ON, &star_comment_cont,
  160. X    "sob", PRO_BOOL, false, ON, &swallow_optional_blanklines,
  161. X    "st", PRO_SPECIAL, 0, STDIN, 0,
  162. X    "tabs", PRO_INT, 8, 0, &tabsize,
  163. X    "troff", PRO_BOOL, false, ON, &troff,
  164. X    "v", PRO_BOOL, false, ON, &verbose,
  165. X    "+", PRO_BOOL, false, ON, &cplus,
  166. X    /* whew! */
  167. X    0, 0, 0, 0, 0
  168. X};
  169. X
  170. X/*
  171. X * set_profile reads $HOME/.indent.pro and ./.indent.pro and handles arguments
  172. X * given in these files.
  173. X */
  174. X#ifdef ANSIC
  175. Xvoid set_profile(void)
  176. X#else
  177. Xset_profile()
  178. X#endif
  179. X{
  180. X    FILE *f;
  181. X    char fname[BUFSIZ];
  182. X
  183. X#ifdef MSDOS                    /* or OS/2 */
  184. X    static char prof[] = "indent.pro";
  185. X
  186. X#else
  187. X    static char prof[] = ".indent.pro";
  188. X
  189. X#endif
  190. X    sprintf(fname, "%s/%s", getenv("HOME"), prof);
  191. X    if ((f = fopen(fname, "r")) != NULL)
  192. X    {
  193. X        scan_profile(f);
  194. X        (void) fclose(f);
  195. X    }
  196. X    if ((f = fopen(prof, "r")) != NULL)
  197. X    {
  198. X        scan_profile(f);
  199. X        (void) fclose(f);
  200. X    }
  201. X}
  202. X
  203. X#ifdef ANSIC
  204. Xvoid scan_profile(FILE *f)
  205. X#else
  206. Xscan_profile(f)
  207. X    FILE *f;
  208. X
  209. X#endif
  210. X{
  211. X    register int i;
  212. X    register char *p;
  213. X    char buf[BUFSIZ];
  214. X
  215. X    while (1)
  216. X    {
  217. X        for (p = buf; (i = getc(f)) != EOF && (*p = (char) i) > ' '; ++p);
  218. X        if (p != buf)
  219. X        {
  220. X            *p++ = 0;
  221. X            if (verbose)
  222. X                printf("profile: %s\n", buf);
  223. X            set_option(buf);
  224. X        }
  225. X        else if (i == EOF)
  226. X            return;
  227. X    }
  228. X}
  229. X
  230. Xstatic char *param_start;
  231. X
  232. X#ifdef ANSIC
  233. Xstatic int eqin(register char *s1, register char *s2)
  234. X#else
  235. Xeqin(s1, s2)
  236. X    register char *s1;
  237. X    register char *s2;
  238. X
  239. X#endif
  240. X{
  241. X    while (*s1)
  242. X    {
  243. X        if (*s1++ != *s2++)
  244. X            return (false);
  245. X    }
  246. X    param_start = s2;
  247. X    return (true);
  248. X}
  249. X
  250. X/*
  251. X * Set the defaults.
  252. X */
  253. X#ifdef ANSIC
  254. Xvoid set_defaults(void)
  255. X#else
  256. Xset_defaults()
  257. X#endif
  258. X{
  259. X    register struct pro *p;
  260. X
  261. X    /*
  262. X       Because ps.case_indent and ps.case_code_indent are floats, we can't
  263. X       initialize them from the table:
  264. X    */
  265. X    ps.case_indent = (float) 0;    /* -cli0.0 */
  266. X    ps.case_code_indent = (float) 1;    /* -cci1.0 */
  267. X    for (p = pro; p->p_name != NULL; p++)
  268. X        if (p->p_type != PRO_SPECIAL && p->p_type != PRO_FONT)
  269. X            *p->p_obj = p->p_default;
  270. X}
  271. X
  272. X#ifdef ANSIC
  273. Xvoid set_option(register char *arg)
  274. X#else
  275. Xset_option(arg)
  276. X    register char *arg;
  277. X
  278. X#endif
  279. X{
  280. X    register struct pro *p;
  281. X#ifndef ANSIC
  282. X    extern double atof();
  283. X#endif
  284. X    arg++;                        /* ignore leading "-" */
  285. X    for (p = pro; p->p_name; p++)
  286. X        if (*p->p_name == *arg && eqin(p->p_name, arg))
  287. X            goto found;
  288. X    fprintf(stderr, "indent: unknown parameter \"%s\"\n", arg - 1);
  289. X    exit(1);
  290. Xfound:
  291. X    switch (p->p_type)
  292. X    {
  293. X
  294. X    case PRO_SPECIAL:
  295. X        switch (p->p_special)
  296. X        {
  297. X
  298. X        case IGN:
  299. X            break;
  300. X
  301. X        case CLI:
  302. X            if (*param_start == 0)
  303. X                goto need_param;
  304. X            ps.case_indent = (float) atof(param_start);
  305. X            break;
  306. X
  307. X        case CCI:
  308. X            if (*param_start == 0)
  309. X                goto need_param;
  310. X            ps.case_code_indent = (float) atof(param_start);
  311. X            break;
  312. X
  313. X        case STDIN:
  314. X            if (input == NULL)
  315. X                input = stdin;
  316. X            if (output == NULL)
  317. X                output = stdout;
  318. X            break;
  319. X
  320. X        case KEY:
  321. X            if (*param_start == 0)
  322. X                goto need_param;
  323. X            {
  324. X                register char *str = (char *) malloc(strlen(param_start) + 1);
  325. X
  326. X                strcpy(str, param_start);
  327. X                addkey(str, 4);
  328. X            }
  329. X            break;
  330. X
  331. X        default:
  332. X            fprintf(stderr,
  333. X                    "indent: set_option: internal error: p_special %d\n",
  334. X                    p->p_special);
  335. X            exit(1);
  336. X        }
  337. X        break;
  338. X
  339. X    case PRO_BOOL:
  340. X        if (p->p_special == OFF)
  341. X            *p->p_obj = false;
  342. X        else
  343. X            *p->p_obj = true;
  344. X        break;
  345. X
  346. X    case PRO_INT:
  347. X        if (*param_start == 0)
  348. X        {
  349. X    need_param:
  350. X            fprintf(stderr, "indent: ``%s'' requires a parameter\n",
  351. X                    arg - 1);
  352. X            exit(1);
  353. X        }
  354. X        *p->p_obj = atoi(param_start);
  355. X        break;
  356. X
  357. X    case PRO_FONT:
  358. X        parsefont((struct fstate *) p->p_obj, param_start);
  359. X        break;
  360. X
  361. X    default:
  362. X        fprintf(stderr, "indent: set_option: internal error: p_type %d\n",
  363. X                p->p_type);
  364. X        exit(1);
  365. X    }
  366. X}
  367. SHAR_EOF
  368. if test 9142 -ne "`wc -c args.c`"
  369. then
  370. echo shar: error transmitting args.c '(should have been 9142 characters)'
  371. fi
  372. echo shar: extracting comment.c
  373. sed 's/^X//' << \SHAR_EOF > comment.c
  374. X/*
  375. X * Copyright (c) 1985 Sun Microsystems, Inc.
  376. X * Copyright (c) 1980 The Regents of the University of California.
  377. X * Copyright (c) 1976 Board of Trustees of the University of Illinois.
  378. X * All rights reserved.
  379. X *
  380. X * Redistribution and use in source and binary forms are permitted
  381. X * provided that the above copyright notice and this paragraph are
  382. X * duplicated in all such forms and that any documentation,
  383. X * advertising materials, and other materials related to such
  384. X * distribution and use acknowledge that the software was developed
  385. X * by the University of California, Berkeley, the University of Illinois,
  386. X * Urbana, and Sun Microsystems, Inc.  The name of either University
  387. X * or Sun Microsystems may not be used to endorse or promote products
  388. X * derived from this software without specific prior written permission.
  389. X * THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
  390. X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  391. X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  392. X */
  393. X
  394. X#ifndef lint
  395. Xstatic char sccsid[] = "@(#)comment.c    5.9 (Berkeley) 88/09/15";
  396. X
  397. X#endif                            /* not lint */
  398. X
  399. X/*
  400. X * NAME:
  401. X *    pr_comment
  402. X *
  403. X * FUNCTION:
  404. X *    This routine takes care of scanning and printing comments.
  405. X *
  406. X * ALGORITHM:
  407. X *    1) Decide where the comment should be aligned, and if lines should
  408. X *       be broken.
  409. X *    2) If lines should not be broken and filled, just copy up to end of
  410. X *       comment.
  411. X *    3) If lines should be filled, then scan thru input_buffer copying
  412. X *       characters to com_buf.  Remember where the last blank, tab, or
  413. X *       newline was.  When line is filled, print up to last blank and
  414. X *       continue copying.
  415. X *
  416. X * HISTORY:
  417. X *    November 1976    D A Willcox of CAC    Initial coding
  418. X *    12/6/76        D A Willcox of CAC    Modification to handle
  419. X *                        UNIX-style comments
  420. X *
  421. X */
  422. X
  423. X/*
  424. X * this routine processes comments.  It makes an attempt to keep comments from
  425. X * going over the max line length.  If a line is too long, it moves everything
  426. X * from the last blank to the next comment line.  Blanks and tabs from the
  427. X * beginning of the input line are removed
  428. X */
  429. X
  430. X
  431. X#include "globals.h"
  432. X
  433. X#ifdef MSDOS                    /* or OS/2 */
  434. X#include <malloc.h>
  435. X#endif
  436. X
  437. X#ifdef ANSIC
  438. Xvoid pr_comment(void)
  439. X#else
  440. Xpr_comment()
  441. X#endif
  442. X{
  443. X    int now_col;                /* column we are in now */
  444. X    int adj_max_col;            /* Adjusted max_col for when we decide to spill
  445. X                                   comments over the right margin */
  446. X    char *last_bl;                /* points to the last blank in the output
  447. X                                   buffer */
  448. X    char *t_ptr;                /* used for moving string */
  449. X    int unix_comment;            /* tri-state variable used to decide if it is a
  450. X                                   unix-style comment. 0 means only blanks
  451. X                                   since /*, 1 means regular style comment, 2
  452. X                                   means unix style comment */
  453. X    int break_delim = comment_delimiter_on_blankline;
  454. X    int l_just_saw_decl = ps.just_saw_decl;
  455. X
  456. X    /*
  457. X       int         ps.last_nl = 0;    /* true iff the last significant thing weve
  458. X       seen is a newline
  459. X    */
  460. X    int one_liner = 1;            /* true iff this comment is a one-liner */
  461. X
  462. X    adj_max_col = max_col;
  463. X    ps.just_saw_decl = 0;
  464. X    last_bl = 0;                /* no blanks found so far */
  465. X    ps.box_com = false;            /* at first, assume that we are not in a boxed
  466. X                                   comment or some other comment that should
  467. X                                   not be touched */
  468. X    ++ps.out_coms;                /* keep track of number of comments */
  469. X    unix_comment = 1;            /* set flag to let us figure out if there is a
  470. X                                   unix-style comment ** DISABLED: use 0 to
  471. X                                   reenable this hack! */
  472. X
  473. X    /* Figure where to align and how to treat the comment */
  474. X
  475. X    if (ps.col_1 && !format_col1_comments)
  476. X    {                            /* if comment starts in column 1 it should not
  477. X                                   be touched */
  478. X        ps.box_com = true;
  479. X        ps.com_col = 1;
  480. X    }
  481. X    else
  482. X    {
  483. X        if (*buf_ptr == '-' || *buf_ptr == '*')
  484. X        {
  485. X            ps.box_com = true;    /* a comment with a '-' or '*' immediately
  486. X                                   after the /* is assumed to be a boxed
  487. X                                   comment */
  488. X            break_delim = 0;
  489. X        }
  490. X        if ( /* ps.bl_line && */ (s_lab == e_lab) && (s_code == e_code))
  491. X        {
  492. X            /* klg: check only if this line is blank */
  493. X            /*
  494. X               If this (*and previous lines are*) blank, dont put comment way
  495. X               out at left
  496. X            */
  497. X            ps.com_col = (ps.ind_level - ps.unindent_displace) * ps.ind_size + 1;
  498. X            adj_max_col = block_comment_max_col;
  499. X            if (ps.com_col <= 1)
  500. X                ps.com_col = 1 + !format_col1_comments;
  501. X        }
  502. X        else
  503. X        {
  504. X            register target_col;
  505. X
  506. X            break_delim = 0;
  507. X            if (s_code != e_code)
  508. X                target_col = count_spaces(compute_code_target(), s_code);
  509. X            else
  510. X            {
  511. X                target_col = 1;
  512. X                if (s_lab != e_lab)
  513. X                    target_col = count_spaces(compute_label_target(), s_lab);
  514. X            }
  515. X            ps.com_col = ps.decl_on_line || ps.ind_level == 0 ? ps.decl_com_ind : ps.com_ind;
  516. X            if (ps.com_col < target_col)
  517. X                ps.com_col = target_col +
  518. X                    (tabsize - ((target_col - 1) % tabsize));    /* JHT 22oct89 */
  519. X            if (ps.com_col + 24 > adj_max_col)
  520. X                adj_max_col = ps.com_col + 24;
  521. X        }
  522. X    }
  523. X    if (ps.box_com)
  524. X    {
  525. X        buf_ptr[-2] = 0;
  526. X        ps.n_comment_delta = 1 - count_spaces(1, in_buffer);
  527. X        buf_ptr[-2] = '/';
  528. X    }
  529. X    else
  530. X    {
  531. X        ps.n_comment_delta = 0;
  532. X        while (*buf_ptr == ' ' || *buf_ptr == '\t')
  533. X            buf_ptr++;
  534. X    }
  535. X    ps.comment_delta = 0;
  536. X    *e_com++ = '/';                /* put '/*' into buffer */
  537. X    if (ps.cc_comment)            /* (or '//') */
  538. X        *e_com++ = '/';
  539. X    else
  540. X        *e_com++ = '*';
  541. X    if (*buf_ptr != ' ' && !ps.box_com)
  542. X        *e_com++ = ' ';
  543. X
  544. X    *e_com = '\0';
  545. X    if (troff)
  546. X    {
  547. X        now_col = 1;
  548. X        adj_max_col = 80;
  549. X    }
  550. X    else
  551. X        now_col = count_spaces(ps.com_col, s_com);    /* figure what column we
  552. X                                                       would be in if we
  553. X                                                       printed the comment now */
  554. X
  555. X    /* Start to copy the comment */
  556. X
  557. X    while (1)
  558. X    {                            /* this loop will go until the comment is
  559. X                                   copied */
  560. X        if (*buf_ptr >= 040 && *buf_ptr != '*')
  561. X            ps.last_nl = 0;
  562. X        check_size(com);
  563. X        switch (*buf_ptr)
  564. X        {                        /* this checks for various spcl cases */
  565. X        case 014:                /* check for a form feed */
  566. X            if (!ps.box_com)
  567. X            {                    /* in a text comment, break the line here */
  568. X                ps.use_ff = true;
  569. X                /* fix so dump_line uses a form feed */
  570. X                dump_line();
  571. X                last_bl = 0;
  572. X                *e_com++ = ' ';
  573. X                *e_com++ = '*';
  574. X                *e_com++ = ' ';
  575. X                while (*++buf_ptr == ' ' || *buf_ptr == '\t');
  576. X            }
  577. X            else
  578. X            {
  579. X                if (++buf_ptr >= buf_end)
  580. X                    fill_buffer();
  581. X                *e_com++ = 014;
  582. X            }
  583. X            break;
  584. X
  585. X        case '\n':
  586. X            if (ps.cc_comment)
  587. X            {
  588. X                *e_com = '\0';
  589. X                dump_line();
  590. X                ps.cc_comment = 0;
  591. X                ps.just_saw_decl = l_just_saw_decl;    /* ?? */
  592. X                if (++buf_ptr >= buf_end)    /* eat '\n' */
  593. X                    fill_buffer();
  594. X                ps.last_nl = 1;    /* jrs 12 Mar 92 */
  595. X                return;
  596. X            }
  597. X            if (had_eof)
  598. X            {                    /* check for unexpected eof */
  599. X                printf("Unterminated comment\n");
  600. X                *e_com = '\0';
  601. X                dump_line();
  602. X                return;
  603. X            }
  604. X            one_liner = 0;
  605. X            if (ps.box_com || ps.last_nl)
  606. X            {                    /* if this is a boxed comment, we dont ignore
  607. X                                   the newline */
  608. X                if (s_com == e_com)
  609. X                {
  610. X                    *e_com++ = ' ';
  611. X                    *e_com++ = ' ';
  612. X                }
  613. X                *e_com = '\0';
  614. X                if (!ps.box_com && e_com - s_com > 3)
  615. X                {
  616. X                    if (break_delim == 1 && s_com[0] == '/'
  617. X                        && s_com[1] == '*' && s_com[2] == ' ')
  618. X                    {
  619. X                        char *t = e_com;
  620. X
  621. X                        break_delim = 2;
  622. X                        e_com = s_com + 2;
  623. X                        *e_com = 0;
  624. X                        if (blanklines_before_blockcomments)
  625. X                            prefix_blankline_requested = 1;
  626. X                        dump_line();
  627. X                        e_com = t;
  628. X                        s_com[0] = s_com[1] = s_com[2] = ' ';
  629. X                    }
  630. X                    dump_line();
  631. X                    check_size(com);
  632. X                    *e_com++ = ' ';
  633. X                    *e_com++ = ' ';
  634. X                }
  635. X                dump_line();
  636. X                now_col = ps.com_col;
  637. X            }
  638. X            else
  639. X            {
  640. X                ps.last_nl = 1;
  641. X                if (unix_comment != 1)
  642. X                {                /* we are not in unix_style comment */
  643. X                    if (unix_comment == 0 && s_code == e_code)
  644. X                    {
  645. X                        /*
  646. X                           if it is a UNIX-style comment, ignore the
  647. X                           requirement that previous line be blank for
  648. X                           unindention
  649. X                        */
  650. X                        ps.com_col = (ps.ind_level - ps.unindent_displace) * ps.ind_size + 1;
  651. X                        if (ps.com_col <= 1)
  652. X                            ps.com_col = 2;
  653. X                    }
  654. X                    unix_comment = 2;    /* permanently remember that we are in
  655. X                                           this type of comment */
  656. X                    dump_line();
  657. X                    ++line_no;
  658. X                    now_col = ps.com_col;
  659. X                    *e_com++ = ' ';
  660. X                    /*
  661. X                       fix so that the star at the start of the line will line
  662. X                       up
  663. X                    */
  664. X                    do            /* flush leading white space */
  665. X                        if (++buf_ptr >= buf_end)
  666. X                            fill_buffer();
  667. X                    while (*buf_ptr == ' ' || *buf_ptr == '\t');
  668. X                    break;
  669. X                }
  670. X                if (*(e_com - 1) == ' ' || *(e_com - 1) == '\t')
  671. X                    last_bl = e_com - 1;
  672. X                /*
  673. X                   if there was a space at the end of the last line, remember
  674. X                   where it was
  675. X                */
  676. X                else
  677. X                {                /* otherwise, insert one */
  678. X                    last_bl = e_com;
  679. X                    check_size(com);
  680. X                    *e_com++ = ' ';
  681. X                    ++now_col;
  682. X                }
  683. X            }
  684. X            ++line_no;            /* keep track of input line number */
  685. X            if (!ps.box_com)
  686. X            {
  687. X                int nstar = 1;
  688. X
  689. X                do
  690. X                {                /* flush any blanks and/or tabs at start of
  691. X                                   next line */
  692. X                    if (++buf_ptr >= buf_end)
  693. X                        fill_buffer();
  694. X                    if (*buf_ptr == '*' && --nstar >= 0)
  695. X                    {
  696. X                        if (++buf_ptr >= buf_end)
  697. X                            fill_buffer();
  698. X                        if (*buf_ptr == '/')
  699. X                            goto end_of_comment;
  700. X                    }
  701. X                } while (*buf_ptr == ' ' || *buf_ptr == '\t');
  702. X            }
  703. X            else if (++buf_ptr >= buf_end)
  704. X                fill_buffer();
  705. X            break;                /* end of case for newline */
  706. X
  707. X        case '*':                /* must check for possibility of being at end
  708. X                                   of comment */
  709. X            if (++buf_ptr >= buf_end)    /* get to next char after * */
  710. X                fill_buffer();
  711. X
  712. X            if (unix_comment == 0)    /* set flag to show we are not in
  713. X                                       unix-style comment */
  714. X                unix_comment = 1;
  715. X
  716. X            if (*buf_ptr == '/')
  717. X            {                    /* it is the end!!! */
  718. X        end_of_comment:
  719. X                if (++buf_ptr >= buf_end)
  720. X                    fill_buffer();
  721. X
  722. X                if (*(e_com - 1) != ' ' && !ps.box_com)
  723. X                {                /* ensure blank before end */
  724. X                    *e_com++ = ' ';
  725. X                    ++now_col;
  726. X                }
  727. X                if (break_delim == 1 && !one_liner && s_com[0] == '/'
  728. X                    && s_com[1] == '*' && s_com[2] == ' ')
  729. X                {
  730. X                    char *t = e_com;
  731. X
  732. X                    break_delim = 2;
  733. X                    e_com = s_com + 2;
  734. X                    *e_com = 0;
  735. X                    if (blanklines_before_blockcomments)
  736. X                        prefix_blankline_requested = 1;
  737. X                    dump_line();
  738. X                    e_com = t;
  739. X                    s_com[0] = s_com[1] = s_com[2] = ' ';
  740. X                }
  741. X                if (break_delim == 2 && e_com > s_com + 3
  742. X                     /* now_col > adj_max_col - 2 && !ps.box_com */ )
  743. X                {
  744. X                    *e_com = '\0';
  745. X                    dump_line();
  746. X                    now_col = ps.com_col;
  747. X                }
  748. X                check_size(com);
  749. X                *e_com++ = '*';
  750. X                *e_com++ = '/';
  751. X                *e_com = '\0';
  752. X                ps.just_saw_decl = l_just_saw_decl;
  753. X                return;
  754. X            }
  755. X            else
  756. X            {                    /* handle isolated '*' */
  757. X                *e_com++ = '*';
  758. X                ++now_col;
  759. X            }
  760. X            break;
  761. X        default:                /* we have a random char */
  762. X            if (unix_comment == 0 && *buf_ptr != ' ' && *buf_ptr != '\t')
  763. X                unix_comment = 1;    /* we are not in unix-style comment */
  764. X
  765. X            *e_com = *buf_ptr++;
  766. X            if (buf_ptr >= buf_end)
  767. X                fill_buffer();
  768. X
  769. X            if (*e_com == '\t')    /* keep track of column */
  770. X                now_col = now_col + (tabsize - ((now_col - 1) % tabsize));
  771. X            else if (*e_com == '\b')    /* this is a backspace */
  772. X                --now_col;
  773. X            else
  774. X                ++now_col;
  775. X
  776. X            if (*e_com == ' ' || *e_com == '\t')
  777. X                last_bl = e_com;
  778. X            /* remember we saw a blank */
  779. X
  780. X            ++e_com;
  781. X            if (now_col > adj_max_col && !ps.box_com && unix_comment == 1 && e_com[-1] > ' ')
  782. X            {
  783. X                /*
  784. X                   the comment is too long, it must be broken up
  785. X                */
  786. X                if (break_delim == 1 && s_com[0] == '/'
  787. X                    && s_com[1] == '*' && s_com[2] == ' ')
  788. X                {
  789. X                    char *t = e_com;
  790. X
  791. X                    break_delim = 2;
  792. X                    e_com = s_com + 2;
  793. X                    *e_com = 0;
  794. X                    if (blanklines_before_blockcomments)
  795. X                        prefix_blankline_requested = 1;
  796. X                    dump_line();
  797. X                    e_com = t;
  798. X                    s_com[0] = s_com[1] = s_com[2] = ' ';
  799. X                }
  800. X                if (last_bl == 0)
  801. X                {                /* we have seen no blanks */
  802. X                    last_bl = e_com;    /* fake it */
  803. X                    *e_com++ = ' ';
  804. X                }
  805. X                *e_com = '\0';    /* print what we have */
  806. X                *last_bl = '\0';
  807. X                while (last_bl > s_com && last_bl[-1] < 040)
  808. X                    *--last_bl = 0;
  809. X                e_com = last_bl;
  810. X                dump_line();
  811. X
  812. X                *e_com++ = ps.cc_comment ? '/' : ' ';    /* blanks or slashes */
  813. X                *e_com++ = ps.cc_comment ? '/' : ' ';    /* for continuation */
  814. X                *e_com++ = ' ';
  815. X
  816. X                t_ptr = last_bl + 1;
  817. X                last_bl = 0;
  818. X                if (t_ptr >= e_com)
  819. X                {
  820. X                    while (*t_ptr == ' ' || *t_ptr == '\t')
  821. X                        t_ptr++;
  822. X                    while (*t_ptr != '\0')
  823. X                    {            /* move unprinted part of comment down in
  824. X                                   buffer */
  825. X                        if (*t_ptr == ' ' || *t_ptr == '\t')
  826. X                            last_bl = e_com;
  827. X                        *e_com++ = *t_ptr++;
  828. X                    }
  829. X                }
  830. X                *e_com = '\0';
  831. X                now_col = count_spaces(ps.com_col, s_com);    /* recompute current
  832. X                                                               position */
  833. X            }
  834. X            break;
  835. X        }
  836. X    }
  837. X}
  838. SHAR_EOF
  839. if test 12422 -ne "`wc -c comment.c`"
  840. then
  841. echo shar: error transmitting comment.c '(should have been 12422 characters)'
  842. fi
  843. echo shar: extracting lexi.c
  844. sed 's/^X//' << \SHAR_EOF > lexi.c
  845. X/*
  846. X * Copyright (c) 1985 Sun Microsystems, Inc.
  847. X * Copyright (c) 1980 The Regents of the University of California.
  848. X * Copyright (c) 1976 Board of Trustees of the University of Illinois.
  849. X * All rights reserved.
  850. X *
  851. X * Redistribution and use in source and binary forms are permitted
  852. X * provided that the above copyright notice and this paragraph are
  853. X * duplicated in all such forms and that any documentation,
  854. X * advertising materials, and other materials related to such
  855. X * distribution and use acknowledge that the software was developed
  856. X * by the University of California, Berkeley, the University of Illinois,
  857. X * Urbana, and Sun Microsystems, Inc.  The name of either University
  858. X * or Sun Microsystems may not be used to endorse or promote products
  859. X * derived from this software without specific prior written permission.
  860. X * THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
  861. X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  862. X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  863. X */
  864. X
  865. X#ifndef lint
  866. Xstatic char sccsid[] = "@(#)lexi.c    5.11 (Berkeley) 88/09/15";
  867. X
  868. X#endif                            /* not lint */
  869. X
  870. X/*
  871. X * Here we have the token scanner for indent.  It scans off one token and puts
  872. X * it in the global variable "token".  It returns a code, indicating the type
  873. X * of token scanned.
  874. X */
  875. X
  876. X#include "globals.h"
  877. X#include "codes.h"
  878. X#include <ctype.h>
  879. X
  880. X#ifdef MSDOS                    /* or OS/2 */
  881. X#include <string.h>
  882. X#endif
  883. X
  884. Xtypedef enum char_type
  885. X{
  886. X    alphanum = 1,
  887. X    opchar = 3,
  888. X    colonchar = 4
  889. X} char_type;
  890. X
  891. Xstruct templ
  892. X{
  893. X    char *rwd;
  894. X    int rwcode;
  895. X    cplus_flag cplus;
  896. X};
  897. X
  898. Xstruct templ specials[100] =
  899. X{
  900. X    "switch", 1, c_and_cplus,
  901. X    "case", 2, c_and_cplus,
  902. X    "break", 0, c_and_cplus,
  903. X    "struct", 3, c_and_cplus,
  904. X    "union", 3, c_and_cplus,
  905. X    "enum", 3, c_and_cplus,
  906. X    "default", 2, c_and_cplus,
  907. X    "int", 4, c_and_cplus,
  908. X    "char", 4, c_and_cplus,
  909. X    "float", 4, c_and_cplus,
  910. X    "double", 4, c_and_cplus,
  911. X    "long", 4, c_and_cplus,
  912. X    "short", 4, c_and_cplus,
  913. X    "typedef", 8, c_and_cplus,
  914. X    "unsigned", 4, c_and_cplus,
  915. X    "register", 4, c_and_cplus,
  916. X    "static", 4, c_and_cplus,
  917. X    "global", 4, c_and_cplus,
  918. X    "extern", 4, c_and_cplus,
  919. X    "void", 4, c_and_cplus,
  920. X    "goto", 0, c_and_cplus,
  921. X    "return", 0, c_and_cplus,
  922. X    "if", 5, c_and_cplus,
  923. X    "while", 5, c_and_cplus,
  924. X    "for", 5, c_and_cplus,
  925. X    "else", 6, c_and_cplus,
  926. X    "do", 6, c_and_cplus,
  927. X    "sizeof", 7, c_and_cplus,
  928. X    "class", 3, cplus_only,
  929. X    "public", 2, cplus_only,
  930. X    "private", 2, cplus_only,
  931. X    "protected", 2, cplus_only,
  932. X    "volatile", 4, c_and_cplus,
  933. X
  934. X    0, 0
  935. X};
  936. X
  937. Xchar chartype[128] =
  938. X{                                /* this is used to facilitate the decision of
  939. X                                   what type (alphanumeric, operator) each
  940. X                                   character is */
  941. X    0, 0, 0, 0, 0, 0, 0, 0,
  942. X    0, 0, 0, 0, 0, 0, 0, 0,
  943. X    0, 0, 0, 0, 0, 0, 0, 0,
  944. X    0, 0, 0, 0, 0, 0, 0, 0,
  945. X    0, 3, 0, 0, 1, 3, 3, 0,
  946. X    0, 0, 3, 3, 0, 3, 0, 3,
  947. X    1, 1, 1, 1, 1, 1, 1, 1,
  948. X    1, 1, 4, 0, 3, 3, 3, 3,
  949. X    0, 1, 1, 1, 1, 1, 1, 1,
  950. X    1, 1, 1, 1, 1, 1, 1, 1,
  951. X    1, 1, 1, 1, 1, 1, 1, 1,
  952. X    1, 1, 1, 0, 0, 0, 3, 1,
  953. X    0, 1, 1, 1, 1, 1, 1, 1,
  954. X    1, 1, 1, 1, 1, 1, 1, 1,
  955. X    1, 1, 1, 1, 1, 1, 1, 1,
  956. X    1, 1, 1, 0, 3, 0, 3, 0
  957. X};
  958. X
  959. X
  960. X
  961. X#ifdef ANSIC
  962. Xint lexi(void)
  963. X#else
  964. Xint lexi()
  965. X#endif
  966. X{
  967. X    register char *tok;            /* local pointer to next char in token */
  968. X    int unary_delim;            /* this is set to 1 if the current token
  969. X                                
  970. X                                forces a following operator to be unary */
  971. X    static int last_code;        /* the last token type returned */
  972. X    static int l_struct;        /* set to 1 if the last token was 'struct' */
  973. X    static int l_struct_start;    /* set at struct, cleared at { or ; */
  974. X    static int l_class;            /* in c++, class name coming next. */
  975. X    int code;                    /* internal code to be returned */
  976. X    char qchar;                    /* the delimiter character for a string */
  977. X
  978. X    tok = token;                /* point to start of place to save token */
  979. X    unary_delim = false;
  980. X    ps.col_1 = ps.last_nl;        /* tell world that this token started in column
  981. X                                   1 iff the last thing scanned was nl */
  982. X    ps.last_nl = false;
  983. X
  984. X    while (*buf_ptr == ' ' || *buf_ptr == '\t')
  985. X    {                            /* get rid of blanks */
  986. X        ps.col_1 = false;        /* leading blanks imply token is not in column
  987. X                                   1 */
  988. X        if (++buf_ptr >= buf_end)
  989. X            fill_buffer();
  990. X    }
  991. X
  992. X    /* Scan an alphanumeric token */
  993. X    /* In c++, :: starting token is aok, as is ~ sometimes */
  994. X    /* well, int x = ~y; will work oddly here */
  995. X    if (((char_type) chartype[*buf_ptr] == alphanum || buf_ptr[0] == '.' && isdigit(buf_ptr[1])) ||
  996. X        (cplus && buf_ptr[0] == ':' && buf_ptr[1] == ':') ||
  997. X        (cplus && ps.in_decl && *buf_ptr == '~'
  998. X         && (char_type) chartype[buf_ptr[1]] == alphanum)    /* destructors in
  999. X                                                               classdefs */
  1000. X        )
  1001. X    {
  1002. X        /*
  1003. X           we have a character or number
  1004. X        */
  1005. X        register char *j;        /* used for searching thru list of
  1006. X                                
  1007. X                                reserved words */
  1008. X        register struct templ *p;
  1009. X
  1010. X        if (isdigit(*buf_ptr) || buf_ptr[0] == '.' && isdigit(buf_ptr[1]))
  1011. X        {
  1012. X            int seendot = 0, seenexp = 0;
  1013. X
  1014. X            if (*buf_ptr == '0' &&
  1015. X                (buf_ptr[1] == 'x' || buf_ptr[1] == 'X'))
  1016. X            {
  1017. X                *tok++ = *buf_ptr++;
  1018. X                *tok++ = *buf_ptr++;
  1019. X                while (isxdigit(*buf_ptr))
  1020. X                    *tok++ = *buf_ptr++;
  1021. X            }
  1022. X            else
  1023. X                while (1)
  1024. X                {
  1025. X                    if (*buf_ptr == '.')
  1026. X                        if (seendot)
  1027. X                            break;
  1028. X                        else
  1029. X                            seendot++;
  1030. X                    *tok++ = *buf_ptr++;
  1031. X                    if (!isdigit(*buf_ptr) && *buf_ptr != '.')
  1032. X                        if ((*buf_ptr != 'E' && *buf_ptr != 'e') || seenexp)
  1033. X                            break;
  1034. X                        else
  1035. X                        {
  1036. X                            seenexp++;
  1037. X                            seendot++;
  1038. X                            *tok++ = *buf_ptr++;
  1039. X                            if (*buf_ptr == '+' || *buf_ptr == '-')
  1040. X                                *tok++ = *buf_ptr++;
  1041. X                        }
  1042. X                }
  1043. X            if (*buf_ptr == 'L' || *buf_ptr == 'l')
  1044. X                *tok++ = *buf_ptr++;
  1045. X        }
  1046. X        else
  1047. X        {
  1048. X            int first;
  1049. X
  1050. X            first = 1;
  1051. X            while ((char_type) chartype[*buf_ptr] == alphanum ||
  1052. X                   (buf_ptr[0] == ':' && buf_ptr[1] == ':' && cplus) ||
  1053. X                   (cplus && first && buf_ptr[0] == '~'))
  1054. X            {                    /* copy it over */
  1055. X                int colonp;
  1056. X
  1057. X                first = 0;
  1058. X                colonp = *buf_ptr == ':';
  1059. X                *tok++ = *buf_ptr++;
  1060. X                if (colonp)
  1061. X                {
  1062. X                    *tok++ = *buf_ptr++;
  1063. X                    /* foo::~foo */
  1064. X                    if (*buf_ptr == '~')
  1065. X                        *tok++ = *buf_ptr++;
  1066. X                    colonp = 0;
  1067. X                }
  1068. X                if (buf_ptr >= buf_end)
  1069. X                    fill_buffer();
  1070. X            }
  1071. X        }
  1072. X        *tok++ = '\0';
  1073. X        while (*buf_ptr == ' ' || *buf_ptr == '\t')
  1074. X        {                        /* get rid of blanks */
  1075. X            if (++buf_ptr >= buf_end)
  1076. X                fill_buffer();
  1077. X        }
  1078. X        ps.its_a_keyword = false;
  1079. X        ps.sizeof_keyword = false;
  1080. X        if (l_struct)
  1081. X        {                        /* if last token was 'struct', then this token
  1082. X                                   should be treated as a declaration */
  1083. X            if (l_class)
  1084. X                addkey(tok, 4);
  1085. X            l_class = false;
  1086. X            l_struct = false;
  1087. X            last_code = ident;
  1088. X            ps.last_u_d = true;
  1089. X            return (decl);
  1090. X        }
  1091. X        ps.last_u_d = false;    /* Operator after indentifier is binary */
  1092. X        last_code = ident;        /* Remember that this is the code we will
  1093. X                                   return */
  1094. X
  1095. X        /*
  1096. X           This loop will check if the token is a keyword.
  1097. X        */
  1098. X        for (p = specials; (j = p->rwd) != 0; p++)
  1099. X        {
  1100. X            tok = token;        /* point at scanned token */
  1101. X            if (*j++ != *tok++ || *j++ != *tok++)
  1102. X                continue;        /* This test depends on the fact that
  1103. X                                   identifiers are always at least 1 character
  1104. X                                   long (ie. the first two bytes of the
  1105. X                                   identifier are always meaningful) */
  1106. X            if (tok[-1] == 0)
  1107. X                break;            /* If its a one-character identifier */
  1108. X            while (*tok++ == *j)
  1109. X                if (*j++ == 0 &&
  1110. X                    (p->cplus == c_and_cplus ||
  1111. X                     (cplus && p->cplus == cplus_only) ||
  1112. X                     (!cplus && p->cplus == c_only)))
  1113. X                    goto found_keyword;    /* I wish that C had a multi-level
  1114. X                                           break... */
  1115. X        }
  1116. X        if (p->rwd)
  1117. X        {                        /* we have a keyword */
  1118. X    found_keyword:
  1119. X            ps.its_a_keyword = true;
  1120. X            ps.last_u_d = true;
  1121. X            switch (p->rwcode)
  1122. X            {
  1123. X            case 1:            /* it is a switch */
  1124. X                return (swstmt);
  1125. X            case 2:            /* a case or default */
  1126. X                return (casestmt);
  1127. X
  1128. X            case 3:            /* a "struct" */
  1129. X                if (ps.p_l_follow)
  1130. X                    break;        /* inside parens: cast */
  1131. X                l_struct = true;
  1132. X                if (cplus)
  1133. X                    l_struct_start = true;
  1134. X                /* automatically note keywords */
  1135. X                if (cplus && strcmp(tok, "class") == 0 ||
  1136. X                    strcmp(tok, "struct") == 0 ||
  1137. X                    strcmp(tok, "union") == 0 ||
  1138. X                    strcmp(tok, "enum") == 0)
  1139. X                    l_class = true;
  1140. X                /*
  1141. X                   Next time around, we will want to know that we have had a
  1142. X                   'struct'
  1143. X                */
  1144. X            case 4:            /* one of the declaration keywords */
  1145. X                if (ps.p_l_follow)
  1146. X                {
  1147. X                    ps.cast_mask |= 1 << ps.p_l_follow;
  1148. X                    break;        /* inside parens: cast */
  1149. X                }
  1150. X                last_code = decl;
  1151. X                return (decl);
  1152. X
  1153. X            case 5:            /* if, while, for */
  1154. X                return (sp_paren);
  1155. X
  1156. X            case 6:            /* do, else */
  1157. X                return (sp_nparen);
  1158. X
  1159. X            case 7:
  1160. X                ps.sizeof_keyword = true;
  1161. X                return (ident);
  1162. X
  1163. X            case 8:            /* typedef is a decl */
  1164. X                last_code = decl;
  1165. X                return (decl);
  1166. X
  1167. X            default:            /* all others are treated like any other
  1168. X                                   identifier */
  1169. X                return (ident);
  1170. X            }                    /* end of switch */
  1171. X        }                        /* end of if (found_it) */
  1172. X        if (*buf_ptr == '(' && ps.tos <= 1 && ps.ind_level == 0)
  1173. X        {
  1174. X            register char *tp = buf_ptr;
  1175. X
  1176. X            while (tp < buf_end)
  1177. X                if (*tp++ == ')' && *tp == ';')
  1178. X                    goto not_proc;
  1179. X            strncpy(ps.procname, token, sizeof ps.procname - 1);
  1180. X            ps.in_parameter_declaration = 1;
  1181. X    not_proc:;
  1182. X        }
  1183. X        /*
  1184. X           The following hack attempts to guess whether or not the current
  1185. X           token is in fact a declaration keyword -- one that has been typedefd
  1186. X        */
  1187. X        if (((*buf_ptr == '*' && buf_ptr[1] != '=') || isalpha(*buf_ptr) || *buf_ptr == '_')
  1188. X            && !ps.p_l_follow
  1189. X            && !ps.block_init
  1190. X            && (ps.last_token == rparen || ps.last_token == semicolon ||
  1191. X                ps.last_token == decl ||
  1192. X                ps.last_token == lbrace || ps.last_token == rbrace))
  1193. X        {
  1194. X            ps.its_a_keyword = true;
  1195. X            ps.last_u_d = true;
  1196. X            last_code = decl;
  1197. X            return decl;
  1198. X        }
  1199. X        if (last_code == decl)    /* if this is a declared variable, then
  1200. X                                   following sign is unary */
  1201. X            ps.last_u_d = true;    /* will make "int a -1" work */
  1202. X        last_code = ident;
  1203. X        return (ident);            /* the ident is not in the list */
  1204. X    }                            /* end of procesing for alpanum character */
  1205. X    /* l l l Scan a non-alphanumeric token */
  1206. X
  1207. X    l_class = false;            /* struct { ain't defining a class. */
  1208. X    *tok++ = *buf_ptr;            /* if it is only a one-character token, it is
  1209. X                                   moved here */
  1210. X    *tok = '\0';
  1211. X    if (++buf_ptr >= buf_end)
  1212. X        fill_buffer();
  1213. X
  1214. X    switch (*token)
  1215. X    {
  1216. X    case '\n':
  1217. X        unary_delim = ps.last_u_d;
  1218. X        ps.last_nl = true;        /* remember that we just had a newline */
  1219. X        code = (had_eof ? 0 : newline);
  1220. X
  1221. X        /*
  1222. X           if data has been exausted, the newline is a dummy, and we should
  1223. X           return code to stop
  1224. X        */
  1225. X        break;
  1226. X
  1227. X    case '\'':                    /* start of quoted character */
  1228. X    case '"':                    /* start of string */
  1229. X        qchar = *token;
  1230. X        if (troff)
  1231. X        {
  1232. X            tok[-1] = '`';
  1233. X            if (qchar == '"')
  1234. X                *tok++ = '`';
  1235. X            tok = chfont(&bodyf, &stringf, tok);
  1236. X        }
  1237. X        do
  1238. X        {                        /* copy the string */
  1239. X            while (1)
  1240. X            {                    /* move one character or [/<char>]<char> */
  1241. X                if (*buf_ptr == '\n')
  1242. X                {
  1243. X                    printf("%d: Unterminated literal\n", line_no);
  1244. X                    goto stop_lit;
  1245. X                }
  1246. X                *tok = *buf_ptr++;
  1247. X                if (buf_ptr >= buf_end)
  1248. X                    fill_buffer();
  1249. X                if (had_eof || ((tok - token) > (bufsize - 2)))
  1250. X                {
  1251. X                    printf("Unterminated literal\n");
  1252. X                    ++tok;
  1253. X                    goto stop_lit;
  1254. X                    /* get outof literal copying loop */
  1255. X                }
  1256. X                if (*tok == BACKSLASH)
  1257. X                {                /* if escape, copy extra char */
  1258. X                    if (*buf_ptr == '\n')    /* check for escaped newline */
  1259. X                        ++line_no;
  1260. X                    if (troff)
  1261. X                    {
  1262. X                        *++tok = BACKSLASH;
  1263. X                        if (*buf_ptr == BACKSLASH)
  1264. X                            *++tok = BACKSLASH;
  1265. X                    }
  1266. X                    *++tok = *buf_ptr++;
  1267. X                    ++tok;        /* we must increment this again because we
  1268. X                                   copied two chars */
  1269. X                    if (buf_ptr >= buf_end)
  1270. X                        fill_buffer();
  1271. X                }
  1272. X                else
  1273. X                    break;        /* we copied one character */
  1274. X            }                    /* end of while (1) */
  1275. X        } while (*tok++ != qchar);
  1276. X        if (troff)
  1277. X        {
  1278. X            tok = chfont(&stringf, &bodyf, tok - 1);
  1279. X            if (qchar == '"')
  1280. X                *tok++ = '\'';
  1281. X        }
  1282. Xstop_lit:
  1283. X        code = ident;
  1284. X        break;
  1285. X
  1286. X    case ('('):
  1287. X    case ('['):
  1288. X        unary_delim = true;
  1289. X        code = lparen;
  1290. X        break;
  1291. X
  1292. X    case (')'):
  1293. X    case (']'):
  1294. X        code = rparen;
  1295. X        break;
  1296. X
  1297. X    case '#':
  1298. X        unary_delim = ps.last_u_d;
  1299. X        code = preesc;
  1300. X        break;
  1301. X
  1302. X    case '?':
  1303. X        unary_delim = true;
  1304. X        code = question;
  1305. X        break;
  1306. X
  1307. X    case (':'):
  1308. X        if (l_struct_start)
  1309. X            code = ident;
  1310. X        else
  1311. X            code = colon;
  1312. X        unary_delim = true;
  1313. X        break;
  1314. X
  1315. X    case (';'):
  1316. X        l_struct_start = false;
  1317. X        unary_delim = true;
  1318. X        code = semicolon;
  1319. X        break;
  1320. X
  1321. X    case ('{'):
  1322. X        l_struct_start = false;
  1323. X        unary_delim = true;
  1324. X
  1325. X        /*
  1326. X           if (ps.in_or_st) ps.block_init = 1;
  1327. X        */
  1328. X        /* ?    code = ps.block_init ? lparen : lbrace; */
  1329. X        code = lbrace;
  1330. X        break;
  1331. X
  1332. X    case ('}'):
  1333. X        unary_delim = true;
  1334. X        /* ?    code = ps.block_init ? rparen : rbrace; */
  1335. X        code = rbrace;
  1336. X        break;
  1337. X
  1338. X    case 014:                    /* a form feed */
  1339. X        unary_delim = ps.last_u_d;
  1340. X        ps.last_nl = true;        /* remember this so we can set 'ps.col_1' right */
  1341. X        code = form_feed;
  1342. X        break;
  1343. X
  1344. X    case (','):
  1345. X        unary_delim = true;
  1346. X        code = comma;
  1347. X        break;
  1348. X
  1349. X    case '.':
  1350. X        unary_delim = false;
  1351. X        code = period;
  1352. X        break;
  1353. X
  1354. X    case '-':
  1355. X    case '+':                    /* check for -, +, --, ++ */
  1356. X        code = (ps.last_u_d ? unary_op : binary_op);
  1357. X        unary_delim = true;
  1358. X
  1359. X        if (*buf_ptr == token[0])
  1360. X        {
  1361. X            /* check for doubled character */
  1362. X            *tok++ = *buf_ptr++;
  1363. X            /* buffer overflow will be checked at end of loop */
  1364. X            if (last_code == ident || last_code == rparen)
  1365. X            {
  1366. X                code = (ps.last_u_d ? unary_op : postop);
  1367. X                /* check for following ++ or -- */
  1368. X                unary_delim = false;
  1369. X            }
  1370. X        }
  1371. X        else if (*buf_ptr == '=')
  1372. X            /* check for operator += */
  1373. X            *tok++ = *buf_ptr++;
  1374. X        else if (*buf_ptr == '>')
  1375. X        {
  1376. X            /* check for operator -> */
  1377. X            *tok++ = *buf_ptr++;
  1378. X            if (!pointer_as_binop)
  1379. X            {
  1380. X                unary_delim = false;
  1381. X                code = unary_op;
  1382. X                ps.want_blank = false;
  1383. X            }
  1384. X        }
  1385. X        break;                    /* buffer overflow will be checked at end of
  1386. X                                   switch */
  1387. X
  1388. X    case '=':
  1389. X        if (ps.in_or_st)
  1390. X            ps.block_init = 1;
  1391. X#ifdef undef
  1392. X        if (chartype[*buf_ptr] == opchar)
  1393. X        {                        /* we have two char assignment */
  1394. X            tok[-1] = *buf_ptr++;
  1395. X            if ((tok[-1] == '<' || tok[-1] == '>') && tok[-1] == *buf_ptr)
  1396. X                *tok++ = *buf_ptr++;
  1397. X            *tok++ = '=';        /* Flip =+ to += */
  1398. X            *tok = 0;
  1399. X        }
  1400. X#else
  1401. X        if (*buf_ptr == '=')
  1402. X        {                        /* == */
  1403. X            *tok++ = '=';        /* Flip =+ to += */
  1404. X            buf_ptr++;
  1405. X            *tok = 0;
  1406. X        }
  1407. X#endif
  1408. X        code = binary_op;
  1409. X        unary_delim = true;
  1410. X        break;
  1411. X        /* can drop thru!!! */
  1412. X
  1413. X    case '>':
  1414. X    case '<':
  1415. X    case '!':                    /* ops like <, <<, <=, !=, etc */
  1416. X        if (*buf_ptr == '>' || *buf_ptr == '<' || *buf_ptr == '=')
  1417. X        {
  1418. X            *tok++ = *buf_ptr;
  1419. X            if (++buf_ptr >= buf_end)
  1420. X                fill_buffer();
  1421. X        }
  1422. X        if (*buf_ptr == '=')
  1423. X            *tok++ = *buf_ptr++;
  1424. X        code = (ps.last_u_d ? unary_op : binary_op);
  1425. X        unary_delim = true;
  1426. X        break;
  1427. X
  1428. X    default:
  1429. X        if (token[0] == '/' && *buf_ptr == '*')
  1430. X        {
  1431. X            /* it is start of a C comment */
  1432. X            *tok++ = '*';
  1433. X
  1434. X            if (++buf_ptr >= buf_end)
  1435. X                fill_buffer();
  1436. X
  1437. X            code = comment;
  1438. X            unary_delim = ps.last_u_d;
  1439. X            break;
  1440. X        }
  1441. X        if (token[0] == '/' && *buf_ptr == '/')
  1442. X        {
  1443. X            /* it is start of a C++ comment */
  1444. X            *tok++ = '/';
  1445. X
  1446. X            if (++buf_ptr >= buf_end)
  1447. X                fill_buffer();
  1448. X
  1449. X            code = cc_commnt;
  1450. X            ps.cc_comment++;
  1451. X            unary_delim = ps.last_u_d;
  1452. X            break;
  1453. X        }
  1454. X        while (*(tok - 1) == *buf_ptr || *buf_ptr == '=')
  1455. X        {
  1456. X            /*
  1457. X               handle ||, &&, etc, and also things as in int *****i
  1458. X            */
  1459. X            *tok++ = *buf_ptr;
  1460. X            if (++buf_ptr >= buf_end)
  1461. X                fill_buffer();
  1462. X        }
  1463. X        code = (ps.last_u_d ? unary_op : binary_op);
  1464. X        unary_delim = true;
  1465. X
  1466. X
  1467. X    }                            /* end of switch */
  1468. X    if (code != newline)
  1469. X    {
  1470. X        l_struct = false;
  1471. X        last_code = code;
  1472. X    }
  1473. X    if (buf_ptr >= buf_end)        /* check for input buffer empty */
  1474. X        fill_buffer();
  1475. X    ps.last_u_d = unary_delim;
  1476. X    *tok = '\0';                /* null terminate the token */
  1477. X    return (code);
  1478. X};
  1479. X
  1480. X/*
  1481. X * Add the given keyword to the keyword table, using val as the keyword type
  1482. X */
  1483. X#ifdef ANSIC
  1484. Xvoid addkey(char *key, int val)
  1485. X#else
  1486. Xaddkey(key, val)
  1487. X    char *key;
  1488. X
  1489. X#endif
  1490. X{
  1491. X    register struct templ *p = specials;
  1492. X
  1493. X    while (p->rwd)
  1494. X        if (p->rwd[0] == key[0] && strcmp(p->rwd, key) == 0)
  1495. X            return;
  1496. X        else
  1497. X            p++;
  1498. X    if (p >= specials + sizeof specials / sizeof specials[0])
  1499. X        return;                    /* For now, table overflows are silently
  1500. X                                   ignored */
  1501. X    p->rwd = key;
  1502. X    p->rwcode = val;
  1503. X    p[1].rwd = 0;
  1504. X    p[1].rwcode = 0;
  1505. X    return;
  1506. X}
  1507. SHAR_EOF
  1508. if test 15938 -ne "`wc -c lexi.c`"
  1509. then
  1510. echo shar: error transmitting lexi.c '(should have been 15938 characters)'
  1511. fi
  1512. echo shar: extracting parse.c
  1513. sed 's/^X//' << \SHAR_EOF > parse.c
  1514. X/*
  1515. X * Copyright (c) 1985 Sun Microsystems, Inc.
  1516. X * Copyright (c) 1980 The Regents of the University of California.
  1517. X * Copyright (c) 1976 Board of Trustees of the University of Illinois.
  1518. X * All rights reserved.
  1519. X *
  1520. X * Redistribution and use in source and binary forms are permitted
  1521. X * provided that the above copyright notice and this paragraph are
  1522. X * duplicated in all such forms and that any documentation,
  1523. X * advertising materials, and other materials related to such
  1524. X * distribution and use acknowledge that the software was developed
  1525. X * by the University of California, Berkeley, the University of Illinois,
  1526. X * Urbana, and Sun Microsystems, Inc.  The name of either University
  1527. X * or Sun Microsystems may not be used to endorse or promote products
  1528. X * derived from this software without specific prior written permission.
  1529. X * THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
  1530. X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  1531. X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  1532. X */
  1533. X
  1534. X#ifndef lint
  1535. Xstatic char sccsid[] = "@(#)parse.c    5.8 (Berkeley) 88/09/15";
  1536. X
  1537. X#endif                            /* not lint */
  1538. X
  1539. X#include "globals.h"
  1540. X#include "codes.h"
  1541. X
  1542. X#ifdef ANSIC
  1543. Xstatic void reduce(void);
  1544. X
  1545. Xvoid parse(int tk)
  1546. X#else
  1547. Xparse(tk)
  1548. X    int tk;                        /* the code for the construct scanned */
  1549. X
  1550. X#endif
  1551. X{
  1552. X    int i;
  1553. X
  1554. X#ifdef debug
  1555. X    printf("%2d - %s\n", tk, token);
  1556. X#endif
  1557. X
  1558. X    while (ps.p_stack[ps.tos] == ifhead && tk != elselit)
  1559. X    {
  1560. X        /* true if we have an if without an else */
  1561. X        ps.p_stack[ps.tos] = stmt;    /* apply the if(..) stmt ::= stmt reduction */
  1562. X        reduce();                /* see if this allows any reduction */
  1563. X    }
  1564. X
  1565. X
  1566. X    switch (tk)
  1567. X    {                            /* go on and figure out what to do with the
  1568. X                                   input */
  1569. X
  1570. X    case decl:                    /* scanned a declaration word */
  1571. X        ps.search_brace = btype_2 && !btype_3;
  1572. X        /* indicate that following brace should be on same line */
  1573. X        if (ps.p_stack[ps.tos] != decl)
  1574. X        {                        /* only put one declaration onto stack */
  1575. X            break_comma = true;    /* while in declaration, newline should be
  1576. X                                   forced after comma */
  1577. X            ps.p_stack[++ps.tos] = decl;
  1578. X            ps.il[ps.tos] = ps.i_l_follow;
  1579. X
  1580. X            if (ps.ljust_decl)
  1581. X            {                    /* only do if we want left justified
  1582. X                                   declarations */
  1583. X                ps.ind_level = 0;
  1584. X                for (i = ps.tos - 1; i > 0; --i)
  1585. X                    if (ps.p_stack[i] == decl)
  1586. X                        ++ps.ind_level;    /* indentation is number of declaration
  1587. X                                           levels deep we are */
  1588. X                ps.i_l_follow = ps.ind_level;
  1589. X            }
  1590. X        }
  1591. X        break;
  1592. X
  1593. X    case ifstmt:                /* scanned if (...) */
  1594. X        if (ps.p_stack[ps.tos] == elsehead && ps.else_if)    /* "else if ..." */
  1595. X            ps.i_l_follow = ps.il[ps.tos];
  1596. X    case dolit:                /* 'do' */
  1597. X    case forstmt:                /* for (...) */
  1598. X        ps.p_stack[++ps.tos] = tk;
  1599. X        ps.il[ps.tos] = ps.ind_level = ps.i_l_follow;
  1600. X        ++ps.i_l_follow;        /* subsequent statements should be indented 1 */
  1601. X        ps.search_brace = btype_2 && !btype_3;
  1602. X        break;
  1603. X
  1604. X    case lbrace:                /* scanned { */
  1605. X        break_comma = false;    /* don't break comma in an initial list */
  1606. X        if (ps.p_stack[ps.tos] == stmt || ps.p_stack[ps.tos] == decl
  1607. X            || ps.p_stack[ps.tos] == stmtl)
  1608. X            ++ps.i_l_follow;    /* it is a random, isolated stmt group or a
  1609. X                                   declaration */
  1610. X        else
  1611. X        {
  1612. X            if (s_code == e_code)
  1613. X            {
  1614. X                /*
  1615. X                   only do this if there is nothing on the line
  1616. X                */
  1617. X                --ps.ind_level;
  1618. X                /*
  1619. X                   it is a group as part of a while, for, etc.
  1620. X                */
  1621. X                if (ps.p_stack[ps.tos] == swstmt && ps.case_indent >= (float) 1 &&
  1622. X                    ps.case_code_indent >= (float) 1)
  1623. X                    --ps.ind_level;
  1624. X                /*
  1625. X                   for a switch, brace should be two levels out from the code
  1626. X                */
  1627. X            }
  1628. X        }
  1629. X
  1630. X        ps.p_stack[++ps.tos] = lbrace;
  1631. X        ps.il[ps.tos] = ps.ind_level;
  1632. X        ps.p_stack[++ps.tos] = stmt;
  1633. X        /* allow null stmt between braces */
  1634. X        ps.il[ps.tos] = ps.i_l_follow;
  1635. X        break;
  1636. X
  1637. X    case whilestmt:            /* scanned while (...) */
  1638. X        if (ps.p_stack[ps.tos] == dohead)
  1639. X        {
  1640. X            /* it is matched with do stmt */
  1641. X            ps.ind_level = ps.i_l_follow = ps.il[ps.tos];
  1642. X            ps.p_stack[++ps.tos] = whilestmt;
  1643. X            ps.il[ps.tos] = ps.ind_level = ps.i_l_follow;
  1644. X        }
  1645. X        else
  1646. X        {                        /* it is a while loop */
  1647. X            ps.p_stack[++ps.tos] = whilestmt;
  1648. X            ps.il[ps.tos] = ps.i_l_follow;
  1649. X            ++ps.i_l_follow;
  1650. X            ps.search_brace = btype_2 && !btype_3;
  1651. X        }
  1652. X
  1653. X        break;
  1654. X
  1655. X    case elselit:                /* scanned an else */
  1656. X
  1657. X        if (ps.p_stack[ps.tos] != ifhead)
  1658. X            diag(1, "Unmatched 'else'");
  1659. X        else
  1660. X        {
  1661. X            ps.ind_level = ps.il[ps.tos];    /* indentation for else should be
  1662. X                                               same as for if */
  1663. X            ps.i_l_follow = ps.ind_level + 1;    /* everything following should
  1664. X                                                   be in 1 level */
  1665. X            ps.p_stack[ps.tos] = elsehead;
  1666. X            /* remember if with else */
  1667. X            ps.search_brace = (btype_2 && !btype_3) | ps.else_if;
  1668. X        }
  1669. X        break;
  1670. X
  1671. X    case rbrace:                /* scanned a } */
  1672. X        /* stack should have <lbrace> <stmt> or <lbrace> <stmtl> */
  1673. X        if (ps.p_stack[ps.tos - 1] == lbrace)
  1674. X        {
  1675. X            if (btype_3)
  1676. X                ps.i_l_follow = ps.il[--ps.tos];
  1677. X            else
  1678. X                ps.ind_level = ps.i_l_follow = ps.il[--ps.tos];
  1679. X            ps.p_stack[ps.tos] = stmt;
  1680. X        }
  1681. X        else
  1682. X            diag(1, "Stmt nesting error.");
  1683. X        break;
  1684. X
  1685. X    case swstmt:                /* had switch (...) */
  1686. X        ps.p_stack[++ps.tos] = swstmt;
  1687. X        ps.cstk[ps.tos] = case_ind;
  1688. X        /* save current case indent level */
  1689. X        ps.il[ps.tos] = ps.i_l_follow;
  1690. X        case_ind = ps.i_l_follow + ps.case_indent;
  1691. X        /*
  1692. X           cases should be one level down from switch
  1693. X        */
  1694. X        ps.i_l_follow += ps.case_indent + ps.case_code_indent;
  1695. X        /*
  1696. X           statements should be two levels in
  1697. X        */
  1698. X        ps.search_brace = btype_2 && !btype_3;
  1699. X        break;
  1700. X
  1701. X    case semicolon:            /* this indicates a simple stmt */
  1702. X        break_comma = false;    /* turn off flag to break after commas in a
  1703. X                                   declaration */
  1704. X        ps.p_stack[++ps.tos] = stmt;
  1705. X        ps.il[ps.tos] = ps.ind_level;
  1706. X        break;
  1707. X
  1708. X    default:                    /* this is an error */
  1709. X        diag(1, "Unknown code to parser");
  1710. X        return;
  1711. X
  1712. X
  1713. X    }                            /* end of switch */
  1714. X
  1715. X    reduce();                    /* see if any reduction can be done */
  1716. X
  1717. X#ifdef debug
  1718. X    for (i = 1; i <= ps.tos; ++i)
  1719. X        printf("(%d %d)", ps.p_stack[i], ps.il[i]);
  1720. X    printf("\n");
  1721. X#endif
  1722. X
  1723. X    return;
  1724. X}
  1725. X
  1726. X/*
  1727. X * Copyright (C) 1976 by the Board of Trustees of the University of Illinois
  1728. X *
  1729. X * All rights reserved
  1730. X *
  1731. X *
  1732. X * NAME: reduce
  1733. X *
  1734. X * FUNCTION: Implements the reduce part of the parsing algorithm
  1735. X *
  1736. X * ALGORITHM: The following reductions are done.  Reductions are repeated until
  1737. X * no more are possible.
  1738. X *
  1739. X * Old TOS        New TOS <stmt> <stmt>    <stmtl> <stmtl> <stmt>    <stmtl> do
  1740. X * <stmt>    "dostmt" if <stmt>    "ifstmt" switch <stmt>    <stmt> decl
  1741. X * <stmt>    <stmt> "ifelse" <stmt>    <stmt> for <stmt>    <stmt> while
  1742. X * <stmt>    <stmt> "dostmt" while    <stmt>
  1743. X *
  1744. X * On each reduction, ps.i_l_follow (the indentation for the following line) is
  1745. X * set to the indentation level associated with the old TOS.
  1746. X *
  1747. X * PARAMETERS: None
  1748. X *
  1749. X * RETURNS: Nothing
  1750. X *
  1751. X * GLOBALS: ps.cstk ps.i_l_follow = ps.il ps.p_stack = ps.tos =
  1752. X *
  1753. X * CALLS: None
  1754. X *
  1755. X * CALLED BY: parse
  1756. X *
  1757. X * HISTORY: initial coding     November 1976    D A Willcox of CAC
  1758. X *
  1759. X */
  1760. X/*----------------------------------------------*\
  1761. X|   REDUCTION PHASE                    |
  1762. X\*----------------------------------------------*/
  1763. X#ifdef ANSIC
  1764. Xstatic void reduce(void)
  1765. X#else
  1766. Xreduce()
  1767. X#endif
  1768. X{
  1769. X
  1770. X    register int i;
  1771. X
  1772. X    for (;;)
  1773. X    {                            /* keep looping until there is nothing left to
  1774. X                                   reduce */
  1775. X
  1776. X        switch (ps.p_stack[ps.tos])
  1777. X        {
  1778. X
  1779. X        case stmt:
  1780. X            switch (ps.p_stack[ps.tos - 1])
  1781. X            {
  1782. X
  1783. X            case stmt:
  1784. X            case stmtl:
  1785. X                /* stmtl stmt or stmt stmt */
  1786. X                ps.p_stack[--ps.tos] = stmtl;
  1787. X                break;
  1788. X
  1789. X            case dolit:        /* <do> <stmt> */
  1790. X                ps.p_stack[--ps.tos] = dohead;
  1791. X                ps.i_l_follow = ps.il[ps.tos];
  1792. X                break;
  1793. X
  1794. X            case ifstmt:
  1795. X                /* <if> <stmt> */
  1796. X                ps.p_stack[--ps.tos] = ifhead;
  1797. X                for (i = ps.tos - 1;
  1798. X                     (
  1799. X                      ps.p_stack[i] != stmt
  1800. X                      &&
  1801. X                      ps.p_stack[i] != stmtl
  1802. X                      &&
  1803. X                      ps.p_stack[i] != lbrace
  1804. X                      );
  1805. X                     --i);
  1806. X                ps.i_l_follow = ps.il[i];
  1807. X                /*
  1808. X                   for the time being, we will assume that there is no else on
  1809. X                   this if, and set the indentation level accordingly. If an
  1810. X                   else is scanned, it will be fixed up later
  1811. X                */
  1812. X                break;
  1813. X
  1814. X            case swstmt:
  1815. X                /* <switch> <stmt> */
  1816. X                case_ind = ps.cstk[ps.tos - 1];
  1817. X
  1818. X            case decl:            /* finish of a declaration */
  1819. X            case elsehead:
  1820. X                /* <<if> <stmt> else> <stmt> */
  1821. X            case forstmt:
  1822. X                /* <for> <stmt> */
  1823. X            case whilestmt:
  1824. X                /* <while> <stmt> */
  1825. X                ps.p_stack[--ps.tos] = stmt;
  1826. X                ps.i_l_follow = ps.il[ps.tos];
  1827. X                break;
  1828. X
  1829. X            default:            /* <anything else> <stmt> */
  1830. X                return;
  1831. X
  1832. X            }                    /* end of section for <stmt> on top of stack */
  1833. X            break;
  1834. X
  1835. X        case whilestmt:        /* while (...) on top */
  1836. X            if (ps.p_stack[ps.tos - 1] == dohead)
  1837. X            {
  1838. X                /* it is termination of a do while */
  1839. X                ps.p_stack[--ps.tos] = stmt;
  1840. X                break;
  1841. X            }
  1842. X            else
  1843. X                return;
  1844. X
  1845. X        default:                /* anything else on top */
  1846. X            return;
  1847. X
  1848. X        }
  1849. X    }
  1850. X}
  1851. SHAR_EOF
  1852. if test 8654 -ne "`wc -c parse.c`"
  1853. then
  1854. echo shar: error transmitting parse.c '(should have been 8654 characters)'
  1855. fi
  1856. #    End of shell archive
  1857. exit 0
  1858.