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

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