home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume21 / p2c / part12 < prev    next >
Text File  |  1990-04-05  |  38KB  |  1,586 lines

  1. Subject:  v21i057:  Pascal to C translator, Part12/32
  2. Newsgroups: comp.sources.unix
  3. Approved: rsalz@uunet.UU.NET
  4. X-Checksum-Snefru: 221b1911 cd936d81 1b93dae0 23f27efa
  5.  
  6. Submitted-by: Dave Gillespie <daveg@csvax.caltech.edu>
  7. Posting-number: Volume 21, Issue 57
  8. Archive-name: p2c/part12
  9.  
  10. #! /bin/sh
  11. # This is a shell archive.  Remove anything before this line, then unpack
  12. # it by saving it into a file and typing "sh file".  To overwrite existing
  13. # files, type "sh file -c".  You can also feed this as standard input via
  14. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  15. # will see the following message at the end:
  16. #        "End of archive 12 (of 32)."
  17. # Contents:  src/out.c
  18. # Wrapped by rsalz@litchi.bbn.com on Mon Mar 26 14:29:35 1990
  19. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  20. if test -f 'src/out.c' -a "${1}" != "-c" ; then 
  21.   echo shar: Will not clobber existing file \"'src/out.c'\"
  22. else
  23. echo shar: Extracting \"'src/out.c'\" \(34270 characters\)
  24. sed "s/^X//" >'src/out.c' <<'END_OF_FILE'
  25. X/* "p2c", a Pascal to C translator.
  26. X   Copyright (C) 1989 David Gillespie.
  27. X   Author's address: daveg@csvax.caltech.edu; 256-80 Caltech/Pasadena CA 91125.
  28. X
  29. XThis program is free software; you can redistribute it and/or modify
  30. Xit under the terms of the GNU General Public License as published by
  31. Xthe Free Software Foundation (any version).
  32. X
  33. XThis program is distributed in the hope that it will be useful,
  34. Xbut WITHOUT ANY WARRANTY; without even the implied warranty of
  35. XMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  36. XGNU General Public License for more details.
  37. X
  38. XYou should have received a copy of the GNU General Public License
  39. Xalong with this program; see the file COPYING.  If not, write to
  40. Xthe Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
  41. X
  42. X
  43. X
  44. X
  45. X/* This needs to go before trans.h (and thus p2c.proto) is read */
  46. X
  47. Xtypedef struct S_paren {
  48. X    struct S_paren *next;
  49. X    int pos, indent, qmindent, flags;
  50. X} Paren;
  51. X
  52. X
  53. X
  54. X#define PROTO_OUT_C
  55. X#include "trans.h"
  56. X
  57. X
  58. X#ifndef USETIME
  59. X# if defined(BSD) || defined(hpux)
  60. X#  define USETIME 1
  61. X# else
  62. X#  define USETIME 0
  63. X# endif
  64. X#endif
  65. X
  66. X#if USETIME
  67. X# include <sys/time.h>
  68. X#else
  69. X# include <time.h>
  70. X#endif
  71. X
  72. X
  73. X
  74. X
  75. X/* Output control characters:
  76. X
  77. X   \001  \B  Possible break point
  78. X   \002  \X  Break point in parentheses
  79. X   \003  \(  Invisible open paren
  80. X   \004  \)  Invisible close paren
  81. X   \005  \T  Set left margin
  82. X   \006  \F  Forced break point
  83. X   \007  \A  Preceding paren requires all-or-none breaking
  84. X   \010  \[  Invisible open paren, becomes visible if not all on one line
  85. X   \011  \S  Break point after last "special argument" of a function
  86. X   \012  \n  (newline)
  87. X   \013  \E  Preceding break has extra penalty
  88. X   \014  \f  (form-feed)
  89. X   \015  \H  Hang-indent the preceding operator
  90. X   \016  \.  (unused)
  91. X   \017  \C  Break point for last : of a ?: construct
  92. X
  93. X*/
  94. X
  95. Xchar spchars[] = ".BX()TFA[SnEfH.C................";
  96. X
  97. X
  98. X
  99. XStatic int testinglinebreaker = 0;
  100. X
  101. XStatic int deltaindent, thisindent, thisfutureindent;
  102. XStatic int sectionsize, blanklines, codesectsize, hdrsectsize;
  103. XStatic int codelnum, hdrlnum;
  104. X
  105. X#define MAXBREAKS  200
  106. XStatic int numbreaks, bestnumbreaks;
  107. XStatic double bestbadness;
  108. XStatic int breakpos[MAXBREAKS], breakindent[MAXBREAKS];
  109. XStatic int breakcount[MAXBREAKS], breakparen[MAXBREAKS];
  110. XStatic int bestbreakpos[MAXBREAKS], bestbreakindent[MAXBREAKS];
  111. XStatic int breakerrorflag;
  112. X
  113. X#define MAXEDITS  200
  114. XStatic int numedits, bestnumedits;
  115. XStatic int editpos[MAXEDITS], besteditpos[MAXEDITS];
  116. XStatic char editold[MAXEDITS], editnew[MAXEDITS];
  117. XStatic char besteditold[MAXEDITS], besteditnew[MAXEDITS];
  118. X
  119. XStatic Paren *parenlist;
  120. X
  121. XStatic long numalts, bestnumalts;
  122. XStatic int randombreaks;
  123. X
  124. XStatic char *outbuf;
  125. XStatic int outbufpos, outbufcount, outbufsize;
  126. XStatic int suppressnewline, lastlinelength;
  127. XStatic int eatblanks;
  128. XStatic int embeddedcode;
  129. XStatic int showingsourcecode = 0;
  130. X
  131. X#define BIGBADNESS  (1e20)
  132. X
  133. X
  134. X
  135. Xvoid setup_out()
  136. X{
  137. X    end_source();
  138. X    fprintf(outf, "/* From input file \"%s\" */\n", infname);
  139. X    outf_lnum++;
  140. X    hdrlnum = 1;
  141. X    outindent = 0;
  142. X    deltaindent = 0;
  143. X    thisindent = 0;
  144. X    thisfutureindent = -1;
  145. X    sectionsize = 2;
  146. X    blanklines = 0;
  147. X    dontbreaklines = 0;
  148. X    embeddedcode = 0;
  149. X    outputmode = 0;
  150. X    suppressnewline = 0;
  151. X    eatblanks = 0;
  152. X    outbufsize = 1000;
  153. X    outbuf = ALLOC(outbufsize, char, misc);
  154. X    outbufpos = 0;
  155. X    outbufcount = 0;
  156. X    srand(17);
  157. X}
  158. X
  159. X
  160. X
  161. Xvoid select_outfile(fp)
  162. XFILE *fp;
  163. X{
  164. X    if (outf == codef) {
  165. X        codesectsize = sectionsize;
  166. X    codelnum = outf_lnum;
  167. X    } else {
  168. X        hdrsectsize = sectionsize;
  169. X    hdrlnum = outf_lnum;
  170. X    }
  171. X    outf = fp;
  172. X    if (outf == codef) {
  173. X        sectionsize = codesectsize;
  174. X    outf_lnum = codelnum;
  175. X    } else {
  176. X        sectionsize = hdrsectsize;
  177. X    outf_lnum = hdrlnum;
  178. X    }
  179. X}
  180. X
  181. X
  182. X
  183. Xvoid start_source()
  184. X{
  185. X    if (!showingsourcecode) {
  186. X    fprintf(outf, "\n#ifdef Pascal\n");
  187. X    showingsourcecode = 1;
  188. X    }
  189. X}
  190. X
  191. Xvoid end_source()
  192. X{
  193. X    if (showingsourcecode) {
  194. X    fprintf(outf, "#endif /*Pascal*/\n\n");
  195. X    showingsourcecode = 0;
  196. X    }
  197. X}
  198. X
  199. X
  200. X
  201. Xint line_start()
  202. X{
  203. X    return (outbufcount == 0);
  204. X}
  205. X
  206. X
  207. Xint cur_column()
  208. X{
  209. X    if (outbufpos == 0)
  210. X    return outindent;
  211. X    else
  212. X    return thisindent + outbufcount;
  213. X}
  214. X
  215. X
  216. X
  217. Xint lookback(n)
  218. Xint n;
  219. X{
  220. X    if (n <= 0 || n > outbufpos)
  221. X    return 0;
  222. X    else
  223. X    return outbuf[outbufpos - n];
  224. X}
  225. X
  226. X
  227. Xint lookback_prn(n)
  228. Xint n;
  229. X{
  230. X    for (;;) {
  231. X    if (n <= 0 || n > outbufpos)
  232. X        return 0;
  233. X    else if (outbuf[outbufpos - n] >= ' ')
  234. X        return outbuf[outbufpos - n];
  235. X    else
  236. X        n++;
  237. X    }
  238. X}
  239. X
  240. X
  241. X
  242. X/* Combine two indentation adjustments */
  243. Xint adddeltas(d1, d2)
  244. Xint d1, d2;
  245. X{
  246. X    if (d2 >= 1000)
  247. X    return d2;
  248. X    else
  249. X    return d1 + d2;
  250. X}
  251. X
  252. X
  253. X/* Apply an indentation delta */
  254. Xint applydelta(i, d)
  255. Xint i, d;
  256. X{
  257. X    if (d >= 1000)
  258. X    return d - 1000;
  259. X    else
  260. X    return i + d;
  261. X}
  262. X
  263. X
  264. X/* Adjust the current indentation by delta */
  265. Xvoid moreindent(delta)
  266. Xint delta;
  267. X{
  268. X    outindent = applydelta(outindent, delta);
  269. X}
  270. X
  271. X
  272. X/* Adjust indentation for just this line */
  273. Xvoid singleindent(delta)
  274. Xint delta;
  275. X{
  276. X    deltaindent = adddeltas(deltaindent, delta);
  277. X}
  278. X
  279. X
  280. X/* Predict indentation for next line */
  281. Xvoid futureindent(num)
  282. Xint num;
  283. X{
  284. X    thisfutureindent = applydelta(applydelta(outindent, deltaindent), num);
  285. X}
  286. X
  287. X
  288. Xint parsedelta(cp, def)
  289. Xchar *cp;
  290. Xint def;
  291. X{
  292. X    if (!cp || !*cp)
  293. X    return def;
  294. X    if ((*cp == '+' || *cp == '-') && isdigit(cp[1]))
  295. X    return atoi(cp);
  296. X    if (*cp == '*' && isdigit(cp[1]))
  297. X    return 2000 + atoi(cp+1);
  298. X    else
  299. X    return 1000 + atoi(cp);
  300. X}
  301. X
  302. X
  303. X
  304. X
  305. XStatic void leading_tab(col)
  306. Xint col;
  307. X{
  308. X    if (col > maxlinewidth)
  309. X    return;    /* something wrong happened! */
  310. X    if (phystabsize > 0) {
  311. X    while (col >= phystabsize) {
  312. X        putc('\t', outf);
  313. X        col -= phystabsize;
  314. X    }
  315. X    }
  316. X    while (col > 0) {
  317. X    putc(' ', outf);
  318. X    col--;
  319. X    }
  320. X}
  321. X
  322. X
  323. X
  324. Xvoid eatblanklines()
  325. X{
  326. X    eatblanks = 1;
  327. X}
  328. X
  329. X
  330. X
  331. XStatic void flush_outbuf(numbreaks, breakpos, breakindent,
  332. X             numedits, editpos, editold, editnew)
  333. Xint numbreaks, *breakpos, *breakindent, numedits, *editpos;
  334. Xchar *editold, *editnew;
  335. X{
  336. X    unsigned char ch, ch2;
  337. X    char *cp;
  338. X    int i, j, linelen = 0, spaces, hashline;
  339. X    int editsaves[MAXEDITS];
  340. X
  341. X    end_source();
  342. X    if (outbufcount > 0) {
  343. X    for (i = 0; i < numedits; i++) {
  344. X        editsaves[i] = outbuf[editpos[i]];
  345. X        outbuf[editpos[i]] = editnew[i];
  346. X    }
  347. X    leading_tab(thisindent);
  348. X    cp = outbuf;
  349. X    hashline = (*cp == '#');    /* a preprocessor directive */
  350. X    spaces = 0;
  351. X    j = 1;
  352. X    for (i = 0; i < outbufpos; ) {
  353. X        if (j < numbreaks && i == breakpos[j]) {
  354. X        if (hashline)
  355. X            fprintf(outf, " \\");   /* trailing backslash required */
  356. X        putc('\n', outf);
  357. X        outf_lnum++;
  358. X        leading_tab(breakindent[j]);
  359. X        linelen = breakindent[j];
  360. X        j++;
  361. X        while (i < outbufpos && *cp == ' ')
  362. X            i++, cp++;   /* eat leading spaces */
  363. X        spaces = 0;      /* eat trailing spaces */
  364. X        } else {
  365. X        ch = *cp++;
  366. X        if (ch == ' ') {
  367. X            spaces++;
  368. X        } else if (ch > ' ') {
  369. X            linelen += spaces;
  370. X            while (spaces > 0)
  371. X            putc(' ', outf), spaces--;
  372. X            linelen++;
  373. X            if (ch == '\\' && embeddedcode) {
  374. X            if (*cp == '[') {
  375. X                putc('{', outf);
  376. X                cp++, i++;
  377. X            } else if (*cp == ']') {
  378. X                putc('}', outf);
  379. X                cp++, i++;
  380. X            } else
  381. X                putc(ch, outf);
  382. X            } else
  383. X            putc(ch, outf);
  384. X        } else if (testinglinebreaker >= 3) {
  385. X            linelen += spaces;
  386. X            while (spaces > 0)
  387. X            putc(' ', outf), spaces--;
  388. X            linelen++;
  389. X            putc('\\', outf);
  390. X            ch2 = spchars[ch];
  391. X            if (ch2 != '.')
  392. X            putc(ch2, outf);
  393. X            else {
  394. X            putc('0' + ((ch >> 6) & 7), outf);
  395. X            putc('0' + ((ch >> 3) & 7), outf);
  396. X            putc('0' + (ch & 7), outf);
  397. X            }
  398. X        }
  399. X        i++;
  400. X        }
  401. X    }
  402. X    for (i = 0; i < numedits; i++)
  403. X        outbuf[editpos[i]] = editsaves[i];
  404. X    eatblanks = 0;
  405. X    } else if (eatblanks) {
  406. X    return;
  407. X    }
  408. X    if (suppressnewline) {
  409. X    lastlinelength = linelen;
  410. X    } else
  411. X    putc('\n', outf);
  412. X    outf_lnum++;
  413. X}
  414. X
  415. X
  416. X
  417. X#define ISQUOTE(ch)  ((ch)=='"' || (ch)=='\'')
  418. X#define ISOPENP(ch)  ((ch)=='(' || (ch)=='[' || (ch)=='\003' || (ch)=='\010')
  419. X#define ISCLOSEP(ch) ((ch)==')' || (ch)==']' || (ch)=='\004')
  420. X#define ISBREAK(ch)  ((ch)=='\001' || (ch)=='\002' || (ch)=='\006' || (ch)=='\011' || (ch)=='\017')
  421. X
  422. XStatic int readquotes(posp, err)
  423. Xint *posp, err;
  424. X{
  425. X    int pos;
  426. X    char quote;
  427. X
  428. X    pos = *posp;
  429. X    quote = outbuf[pos++];
  430. X    while (pos < outbufpos && outbuf[pos] != quote) {
  431. X    if (outbuf[pos] == '\\')
  432. X        pos++;
  433. X    pos++;
  434. X    }
  435. X    if (pos >= outbufpos) {
  436. X    if (err && breakerrorflag) {
  437. X        intwarning("output", "Mismatched quotes [248]");
  438. X        breakerrorflag = 0;
  439. X    }
  440. X    return 0;
  441. X    } else {
  442. X    *posp = pos;
  443. X    return 1;
  444. X    }    
  445. X}
  446. X
  447. X
  448. XStatic int maxdepth;
  449. X
  450. XStatic int readparens(posp, err)
  451. Xint *posp, err;
  452. X{
  453. X    char ch, closing;
  454. X    int pos, level;
  455. X
  456. X    pos = *posp;
  457. X    switch (outbuf[pos]) {
  458. X      case '(':
  459. X    closing = ')';
  460. X    break;
  461. X      case '[':
  462. X    closing = ']';
  463. X    break;
  464. X      case '\003':
  465. X      case '\010':
  466. X    closing = '\004';
  467. X    break;
  468. X      default:
  469. X    closing = 0;
  470. X    break;
  471. X    }
  472. X    level = 0;
  473. X    for (;;) {
  474. X    pos++;
  475. X    if (pos >= outbufpos)
  476. X        break;
  477. X    ch = outbuf[pos];
  478. X    if (ISOPENP(ch)) {
  479. X        level++;
  480. X        if (level > maxdepth)
  481. X        maxdepth = level;
  482. X    } else if (ISCLOSEP(ch)) {
  483. X        level--;
  484. X        if (level < 0) {
  485. X        if (closing && outbuf[pos] != closing)
  486. X            break;
  487. X        *posp = pos;
  488. X        return 1;
  489. X        }
  490. X    } else if (ISQUOTE(ch)) {
  491. X        if (!readquotes(&pos, err))
  492. X        return 0;
  493. X    }
  494. X    }
  495. X    if (err && breakerrorflag) {
  496. X    switch (closing) {
  497. X      case ')':
  498. X        intwarning("output", "Mismatched parentheses [249]");
  499. X        break;
  500. X      case ']':
  501. X        intwarning("output", "Mismatched brackets [249]");
  502. X        break;
  503. X      default:
  504. X        intwarning("output", "Mismatched clauses [250]");
  505. X        break;
  506. X    }
  507. X    breakerrorflag = 0;
  508. X    }
  509. X    return 0;
  510. X}
  511. X
  512. X
  513. X
  514. XStatic int measurechars(first, last)
  515. Xint first, last;
  516. X{
  517. X    int count = 0;
  518. X
  519. X    while (first <= last) {
  520. X    if (outbuf[first] >= ' ')
  521. X        count++;
  522. X    first++;
  523. X    }
  524. X    return count;
  525. X}
  526. X
  527. X
  528. X
  529. XStatic void makeedit(pos, ch)
  530. Xint pos, ch;
  531. X{
  532. X    editpos[numedits] = pos;
  533. X    editold[numedits] = outbuf[pos];
  534. X    editnew[numedits] = ch;
  535. X    outbuf[pos] = ch;
  536. X    numedits++;
  537. X}
  538. X
  539. XStatic void unedit()
  540. X{
  541. X    numedits--;
  542. X    outbuf[editpos[numedits]] = editold[numedits];
  543. X}
  544. X
  545. X
  546. XStatic int parencount(par)
  547. XParen *par;
  548. X{
  549. X    int count = 0;
  550. X
  551. X    while (par) {
  552. X    count++;
  553. X    par = par->next;
  554. X    }
  555. X    return count;
  556. X}
  557. X
  558. X
  559. X
  560. X
  561. X/* The following routine explores the tree of all possible line breaks,
  562. X   pruning according to the fact that "badness" and "extra" are
  563. X   increasing functions.  The object is to find the set of breaks and
  564. X   indentation with the least total badness.
  565. X   (The basic idea was borrowed from Donald Knuth's "TeX".)
  566. X*/
  567. X
  568. X/* As an additional optimization, the concept of a "simple" line is used,
  569. X   i.e., a line with a structure such that the best break is sure to be
  570. X   the straightforward left-to-right fill used by a simple word processor.
  571. X   (For example, a long line with nothing but comma-breakpoints is simple.)
  572. X
  573. X   Also, if the line is very long a few initial random passes are made just
  574. X   to scope out an estimate of the eventual badness of the line.  This
  575. X   combined with the badness cull helps keep the breaker from using up its
  576. X   quota of tries before even considering a key break point!  Note that
  577. X   when randombreaks==1, each call to trybreakline is fast since only one
  578. X   branch is taken at each decision point.
  579. X*/
  580. X
  581. X
  582. X#define randtest(lim)  (!randombreaks ? -1    \
  583. X            : randombreaks > 0    \
  584. X                ? parencount(parens) < randombreaks-1   \
  585. X            : randombreaks == -2  \
  586. X                ? 0 \
  587. X            : (rand() & 0xfff) < (lim))
  588. X
  589. X#define TB_BRKCOUNT   0x0ff
  590. X#define TB_FORCEBRK   0x100
  591. X#define TB_NOBREAK    0x200
  592. X#define TB_ALREADYBRK 0x400
  593. X#define TB_ALLORNONE  0x800
  594. X#define TB_EXTRAIND   0x1000
  595. X#define TB_EXTRAIND2  0x2000
  596. X
  597. X#define TBR_ABORT     0x1
  598. X#define TBR_SIMPLE    0x2
  599. X#define TBR_REACHED   0x4
  600. X
  601. XStatic int trybreakline(pos, count, indent, badness, flags, parens)
  602. Xint pos, count, indent, flags;
  603. Xdouble badness;
  604. XParen *parens;
  605. X{
  606. X    int edited;
  607. X    int i, j, jmask, f, pos2, r;
  608. X    char ch, ch2, closing;
  609. X    double extra, penalty;
  610. X    Paren *pp;
  611. X
  612. X#if 0
  613. X    { static double save = -1;
  614. X      if (showbadlimit != save) printf("Showbadlimit = %g\n", showbadlimit);
  615. X      save = showbadlimit;
  616. X    }
  617. X#endif
  618. X
  619. X    if (numalts >= maxalts)
  620. X    return TBR_ABORT;
  621. X    jmask = -1;
  622. X    for (;;) {
  623. X    if (numbreaks >= MAXBREAKS) {   /* must leave rest of line alone */
  624. X        count += measurechars(pos, outbufpos-1);
  625. X        pos = outbufpos;
  626. X    }
  627. X    i = count - breakcount[numbreaks-1] +
  628. X        breakindent[numbreaks-1] - linewidth;
  629. X    if (i <= 0)
  630. X        extra = 0;
  631. X    else {
  632. X        if (i + linewidth >= maxlinewidth || randombreaks == -2)
  633. X        return 0;   /* absolutely too long! */
  634. X        extra = overwidepenalty + ((long)i*i)*overwideextrapenalty;
  635. X        jmask &= ~TBR_SIMPLE;
  636. X        if (extra < 0)
  637. X        extra = 0;
  638. X    }
  639. X    if ((testinglinebreaker > 1 && showbadlimit > 0) ?
  640. X        (badness + extra >= showbadlimit) :
  641. X        (badness + extra >= bestbadness)) {
  642. X        numalts++;
  643. X        return 0;   /* no point in going on, badness will only increase */
  644. X    }
  645. X    if (pos >= outbufpos)
  646. X        break;
  647. X    if (parens && pos >= parens->pos) {
  648. X        indent = parens->indent;
  649. X        flags = parens->flags;
  650. X        parens = parens->next;
  651. X    }
  652. X    ch = outbuf[pos++];
  653. X    if (ch >= ' ')
  654. X        count++;
  655. X    switch (ch) {
  656. X
  657. X      case '(':
  658. X      case '[':
  659. X      case '\003':     /* "invisible open paren" */
  660. X      case '\010':     /* "semi-invisible open paren" */
  661. X        pos2 = pos - 1;
  662. X        if (!readparens(&pos2, 1))
  663. X        break;
  664. X        i = measurechars(pos, pos2);
  665. X        if (count + i - breakcount[numbreaks-1] +
  666. X        breakindent[numbreaks-1] <= linewidth) {
  667. X        /* it fits, so leave it on one line */
  668. X#if 0  /* I don't think this is necessary */
  669. X        while (pos <= pos2) {
  670. X            if (outbuf[pos] == '\002') {
  671. X            jmask &= ~TBR_SIMPLE;
  672. X            pos = pos2 + 1;
  673. X            break;
  674. X            }
  675. X            pos++;
  676. X        }
  677. X#else
  678. X        pos = pos2 + 1;
  679. X#endif
  680. X        count += i;
  681. X        break;
  682. X        }
  683. X        pp = ALLOC(1, Paren, parens);   /* doesn't fit, try poss breaks */
  684. X        pp->next = parens;
  685. X        pp->pos = pos2;
  686. X        pp->indent = indent;
  687. X        pp->qmindent = indent;
  688. X        pp->flags = flags;
  689. X        parens = pp;
  690. X        flags = 0;
  691. X        if (ch == '\010' &&       /* change to real parens when broken */
  692. X        numedits+1 < MAXEDITS) {    /* (assume it will be broken!) */
  693. X        makeedit(pos-1, '(');
  694. X        makeedit(pos2, ')');
  695. X        count++;    /* count the new open paren */
  696. X        edited = 1;
  697. X        } else
  698. X        edited = 0;
  699. X        i = breakindent[numbreaks-1] + count - breakcount[numbreaks-1];
  700. X        if (i <= thisindent)
  701. X        r = 0;  /* e.g., don't break top-level assignments */
  702. X        else if (i == indent + extraindent)
  703. X        r = 1;  /* don't waste time on identical operations */
  704. X        else
  705. X        r = randtest(0xc00);
  706. X        if (r != 0) {
  707. X        j = trybreakline(pos, count, i,
  708. X                 badness + MAX(- extraindentpenalty,0),
  709. X                 flags, parens);
  710. X        } else
  711. X        j = 0;
  712. X        if (r != 1) {
  713. X        j &= trybreakline(pos, count, indent + extraindent,
  714. X                  badness + MAX(extraindentpenalty,0),
  715. X                  flags | TB_EXTRAIND, parens);
  716. X        }
  717. X        if (!randombreaks && bumpindent != 0) {
  718. X        if (i == thisfutureindent) {
  719. X            j &= trybreakline(pos, count, i + bumpindent,
  720. X                      badness + MAX(- extraindentpenalty,0)
  721. X                              + bumpindentpenalty,
  722. X                      flags, parens);
  723. X        } else if (indent + extraindent == thisfutureindent) {
  724. X            j &= trybreakline(pos, count,
  725. X                      indent + extraindent + bumpindent,
  726. X                      badness + MAX(extraindentpenalty,0)
  727. X                              + bumpindentpenalty,
  728. X                      flags | TB_EXTRAIND, parens);
  729. X        }
  730. X        }
  731. X        if (edited) {
  732. X        unedit();
  733. X        unedit();
  734. X        }
  735. X        FREE(pp);
  736. X        return j & jmask;
  737. X
  738. X      case '\005':   /* "set left margin" */
  739. X        indent = breakindent[numbreaks-1] +
  740. X             count - breakcount[numbreaks-1];
  741. X        break;
  742. X
  743. X      case '\007':   /* "all-or-none breaking" */
  744. X        flags |= TB_ALLORNONE;
  745. X        break;
  746. X
  747. X      case '\001':   /* "possible break point" */
  748. X      case '\002':   /* "break point in parens" */
  749. X      case '\006':   /* "forced break point" */
  750. X      case '\011':   /* "break point after special args" */
  751. X      case '\017':   /* "break point for final : operator" */
  752. X        /* first try the non-breaking case */
  753. X        if (ch != '\001' && ch != '\006')
  754. X        jmask &= ~TBR_SIMPLE;
  755. X        if ((flags & TB_BRKCOUNT) != TB_BRKCOUNT)
  756. X        flags++;   /* increment TB_BRKCOUNT field */
  757. X        if (outbuf[pos] == '?' && parens)
  758. X        parens->qmindent = breakindent[numbreaks-1] +
  759. X                           count - breakcount[numbreaks-1];
  760. X        j = TBR_REACHED;
  761. X        if (ch == '\006' || (flags & TB_FORCEBRK)) {
  762. X        /* don't try the non-breaking case */
  763. X        } else {
  764. X        if (ch == '\011') {
  765. X            i = breakindent[numbreaks-1] +
  766. X            count - breakcount[numbreaks-1] + 2;
  767. X        } else {
  768. X            i = indent;
  769. X        }
  770. X        f = flags;
  771. X        if (f & TB_ALLORNONE)
  772. X            f |= TB_NOBREAK;
  773. X        r = randtest(0x800);
  774. X        if (r != 1 || (flags & TB_NOBREAK)) {
  775. X            j = trybreakline(pos, count, i, badness, f, parens) &
  776. X            jmask;
  777. X            if (randombreaks == -2 && !(j & TBR_REACHED)) {
  778. X            r = -1;
  779. X            j |= TBR_REACHED;
  780. X            }
  781. X            if (r == 0 || (j & TBR_SIMPLE))
  782. X            flags |= TB_NOBREAK;
  783. X        }
  784. X        }
  785. X        if (flags & TB_NOBREAK)
  786. X        return j;
  787. X        if (flags & TB_ALLORNONE)
  788. X        flags |= TB_FORCEBRK;
  789. X        if (flags & TB_EXTRAIND) {
  790. X        flags &= ~TB_EXTRAIND;
  791. X        flags |= TB_EXTRAIND2;
  792. X        }
  793. X        /* now try breaking here */
  794. X        if (ch == '\017')
  795. X        indent = parens->qmindent;
  796. X        if (indent < 0)
  797. X        indent = 0;
  798. X        breakpos[numbreaks] = pos;
  799. X        breakcount[numbreaks] = count;
  800. X        breakindent[numbreaks] = indent;
  801. X        breakparen[numbreaks] = parens ? parens->pos : 0;
  802. X        numbreaks++;
  803. X        penalty = extra;
  804. X        if (indent == thisfutureindent) {
  805. X        i = pos;
  806. X        while (i < outbufpos-1 && outbuf[i] <= ' ')
  807. X            i++;
  808. X        ch2 = outbuf[i];   /* first character on next line */
  809. X        if (ch2 != '(' && ch2 != '!' && ch2 != '~' && ch2 != '-')
  810. X            penalty += nobumpindentpenalty;
  811. X        }
  812. X        switch (ch) {
  813. X          case '\001':
  814. X        penalty += commabreakpenalty;
  815. X        if (flags & TB_ALREADYBRK)
  816. X            penalty += morebreakpenalty;
  817. X        break;
  818. X          case '\011':
  819. X        i = parencount(parens);
  820. X        penalty += specialargbreakpenalty + commabreakextrapenalty*i;
  821. X        break;
  822. X          case '\002':
  823. X          case '\017':
  824. X        i = parencount(parens);
  825. X        if (outbuf[pos-2] == '(')
  826. X            penalty += parenbreakpenalty + parenbreakextrapenalty*i;
  827. X        else if (outbuf[pos-2] == ',')
  828. X            penalty += commabreakpenalty + commabreakextrapenalty*i;
  829. X        else if (outbuf[pos-2] == '=')
  830. X            penalty += assignbreakpenalty + assignbreakextrapenalty*i;
  831. X        else if (outbuf[pos] == '?') {
  832. X            penalty += qmarkbreakpenalty + qmarkbreakextrapenalty*i;
  833. X            if (parens)
  834. X            parens->qmindent = breakindent[numbreaks-1] +
  835. X                               count - breakcount[numbreaks-1];
  836. X        } else
  837. X            penalty += opbreakpenalty + opbreakextrapenalty*i;
  838. X        if (outbuf[pos-2] == '-')
  839. X            penalty += exhyphenpenalty;
  840. X        if (flags & TB_ALREADYBRK)
  841. X            penalty += morebreakpenalty + morebreakextrapenalty*i;
  842. X        break;
  843. X          default:
  844. X        break;
  845. X        }
  846. X        while (pos < outbufpos && outbuf[pos] == '\013') {
  847. X        penalty += wrongsidepenalty;
  848. X        pos++;
  849. X        }
  850. X        penalty -= earlybreakpenalty*(flags & TB_BRKCOUNT);
  851. X        /* the following test is not quite right, but it's not too bad. */
  852. X        if (breakindent[numbreaks-2] == breakindent[numbreaks-1] &&
  853. X        breakparen[numbreaks-2] != breakparen[numbreaks-1])
  854. X        penalty += sameindentpenalty;
  855. X#if 0
  856. X        else if (ch == '\002' && parens &&  /*don't think this is needed*/
  857. X             parens->indent == breakindent[numbreaks-1] &&
  858. X             parens->pos != breakparen[numbreaks-1])
  859. X        penalty += sameindentpenalty + 0.001;   /***/
  860. X#endif
  861. X        penalty += (breakindent[numbreaks-1] - thisindent) *
  862. X               indentamountpenalty;
  863. X        if (penalty < 1) penalty = 1;
  864. X        pos2 = pos;
  865. X        while (pos2 < outbufpos && outbuf[pos2] == ' ')
  866. X        pos2++;
  867. X        flags |= TB_ALREADYBRK;
  868. X        j = trybreakline(pos2, count, indent, badness + penalty,
  869. X                 flags, parens) & jmask;
  870. X        numbreaks--;
  871. X        return j;
  872. X        
  873. X      case '\015':    /* "hang-indent operator" */
  874. X        if (count <= breakcount[numbreaks-1] + 2 &&
  875. X        !(flags & TB_EXTRAIND2)) {
  876. X        breakindent[numbreaks-1] -= count - breakcount[numbreaks-1];
  877. X        pos2 = pos;
  878. X        while (pos2 < outbufpos && outbuf[pos2] <= ' ') {
  879. X            if (outbuf[pos2] == ' ')
  880. X            breakindent[numbreaks-1]--;
  881. X            pos2++;
  882. X        }
  883. X        }
  884. X        break;
  885. X
  886. X      case '"':
  887. X      case '\'':
  888. X        closing = ch;
  889. X        while (pos < outbufpos && outbuf[pos] != closing) {
  890. X        if (outbuf[pos] == '\\')
  891. X            pos++, count++;
  892. X        pos++;
  893. X        count++;
  894. X        }
  895. X        if (pos >= outbufpos) {
  896. X        intwarning("output", "Mismatched quotes [248]");
  897. X        continue;
  898. X        }
  899. X        pos++;
  900. X        count++;
  901. X        break;
  902. X
  903. X      case '/':
  904. X        if (pos < outbufpos && (outbuf[pos] == '*' ||
  905. X                    (outbuf[pos] == '/' && cplus > 0))) {
  906. X        count += measurechars(pos, outbufpos-1);
  907. X        pos = outbufpos;   /* assume comment is at end of line */
  908. X        }
  909. X        break;
  910. X
  911. X    }
  912. X    }
  913. X    numalts++;
  914. X    badness += extra;
  915. X    if (testinglinebreaker > 1) {
  916. X    if (badness >= bestbadness &&
  917. X        (badness < showbadlimit || showbadlimit == 0)) {
  918. X        fprintf(outf, "\n#if 0   /* rejected #%ld, badness = %g >= %g */\n", numalts, badness, bestbadness);
  919. X        flush_outbuf(numbreaks, breakpos, breakindent,
  920. X             numedits, editpos, editold, editnew);
  921. X        fprintf(outf, "#endif\n");
  922. X        return TBR_SIMPLE & jmask;
  923. X    } else if ((bestbadness < showbadlimit || showbadlimit == 0) &&
  924. X           bestnumalts > 0) {
  925. X        fprintf(outf, "\n#if 0   /* rejected #%ld, badness = %g > %g */\n", bestnumalts, bestbadness, badness);
  926. X        flush_outbuf(bestnumbreaks, bestbreakpos, bestbreakindent,
  927. X             bestnumedits, besteditpos,
  928. X             besteditold, besteditnew);
  929. X        fprintf(outf, "#endif\n");
  930. X    }
  931. X    }
  932. X    bestbadness = badness;
  933. X    bestnumbreaks = numbreaks;
  934. X    bestnumalts = numalts;
  935. X    for (i = 0; i < numbreaks; i++) {
  936. X    bestbreakpos[i] = breakpos[i];
  937. X    bestbreakindent[i] = breakindent[i];
  938. X    }
  939. X    bestnumedits = numedits;
  940. X    for (i = 0; i < numedits; i++) {
  941. X    besteditpos[i] = editpos[i];
  942. X    besteditold[i] = editold[i];
  943. X    besteditnew[i] = editnew[i];
  944. X    }
  945. X    return TBR_SIMPLE & jmask;
  946. X}
  947. X
  948. X
  949. X
  950. X
  951. Xint parse_breakstr(cp)
  952. Xchar *cp;
  953. X{
  954. X    short val = 0;
  955. X
  956. X    if (isdigit(*cp))
  957. X    return atoi(cp);
  958. X    while (*cp && !isspace(*cp) && *cp != '}') {
  959. X    switch (toupper(*cp++)) {
  960. X
  961. X      case 'N':
  962. X      case '=':
  963. X        break;
  964. X
  965. X      case 'L':
  966. X        val |= BRK_LEFT;
  967. X        break;
  968. X
  969. X      case 'R':
  970. X        val |= BRK_RIGHT;
  971. X        break;
  972. X
  973. X      case 'H':
  974. X        val |= BRK_HANG | BRK_LEFT;
  975. X        break;
  976. X
  977. X      case '>':
  978. X        if (val & BRK_LEFT)
  979. X        val |= BRK_LPREF;
  980. X        else if (val & BRK_RIGHT)
  981. X        val |= BRK_RPREF;
  982. X        else
  983. X        return -1;
  984. X        break;
  985. X
  986. X      case '<':
  987. X        if (val & BRK_LEFT)
  988. X        val |= BRK_RPREF;
  989. X        else if (val & BRK_RIGHT)
  990. X        val |= BRK_LPREF;
  991. X        else
  992. X        return -1;
  993. X        break;
  994. X
  995. X      case 'A':
  996. X        val |= BRK_ALLNONE;
  997. X        break;
  998. X
  999. X      default:
  1000. X        return -1;
  1001. X
  1002. X    }
  1003. X    }
  1004. X    return val;
  1005. X}
  1006. X
  1007. X
  1008. X
  1009. X
  1010. Xlong getcurtime()
  1011. X{
  1012. X#if USETIME
  1013. X    static unsigned long starttime = 0;
  1014. X    struct timeval t;
  1015. X    struct timezone tz;
  1016. X
  1017. X    gettimeofday(&t, &tz);
  1018. X    if (starttime == 0)
  1019. X    starttime = t.tv_sec;
  1020. X    t.tv_sec -= starttime;
  1021. X    return (t.tv_sec*1000 + t.tv_usec/1000);
  1022. X#else
  1023. X    static unsigned long starttime = 0;
  1024. X    if (!starttime) starttime = time(NULL);
  1025. X    return (time(NULL) - starttime) * 1000;
  1026. X#endif
  1027. X}
  1028. X
  1029. X
  1030. X
  1031. Xvoid output(msg)
  1032. Xregister char *msg;
  1033. X{
  1034. X    unsigned char ch;
  1035. X    double savelimit;
  1036. X    int i, savemaxlw, maxdp;
  1037. X    long alts;
  1038. X    long time0, time0a, time1;
  1039. X
  1040. X    debughook();
  1041. X    if (outputmode) {
  1042. X    end_source();
  1043. X    while ((ch = *msg++) != 0) {
  1044. X        if (ch >= ' ') {
  1045. X        putc(ch, outf);
  1046. X        } else if (ch == '\n') {
  1047. X        putc('\n', outf);
  1048. X        outf_lnum++;
  1049. X        }
  1050. X    }
  1051. X    return;
  1052. X    }
  1053. X    while ((ch = *msg++) != 0) {
  1054. X    if (ch == '\n') {
  1055. X        if (outbufpos == 0) {      /* blank line */
  1056. X        thisfutureindent = -1;
  1057. X        blanklines++;
  1058. X        continue;
  1059. X        }
  1060. X        if (sectionsize > blanklines)
  1061. X        blanklines = sectionsize;
  1062. X        sectionsize = 0;
  1063. X        if (eatblanks)
  1064. X        blanklines = 0;
  1065. X            while (blanklines > 0) {
  1066. X                blanklines--;
  1067. X        end_source();
  1068. X                putc('\n', outf);
  1069. X        outf_lnum++;
  1070. X            }
  1071. X        if (thisindent + outbufcount >= linewidth && !dontbreaklines) {
  1072. X        numbreaks = 1;
  1073. X        bestnumbreaks = 0;
  1074. X        bestbadness = BIGBADNESS;
  1075. X        breakpos[0] = 0;
  1076. X        breakindent[0] = thisindent;
  1077. X        breakcount[0] = 0;
  1078. X        breakerrorflag = 1;
  1079. X        numedits = 0;
  1080. X        bestnumedits = 0;
  1081. X        savelimit = showbadlimit;
  1082. X        numalts = 0;
  1083. X        bestnumalts = 0;
  1084. X        savemaxlw = maxlinewidth;
  1085. X        time0 = time0a = getcurtime();
  1086. X        if (regression)
  1087. X            srand(17);
  1088. X        if (thisindent + outbufcount > linewidth*3/2) {
  1089. X            i = 0;
  1090. X            maxdepth = 0;
  1091. X            readparens(&i, 0);
  1092. X            maxdp = maxdepth;
  1093. X            for (;;) {    /* try some simple fixed methods first... */
  1094. X            for (i = 1; i <= 20; i++) {
  1095. X                randombreaks = -1;
  1096. X                trybreakline(0, 0, thisindent, 0.0, 0, NULL);
  1097. X            }
  1098. X            randombreaks = -2;
  1099. X            trybreakline(0, 0, thisindent, 0.0, 0, NULL);
  1100. X            for (i = 0; i <= maxdp+1; i++) {
  1101. X                randombreaks = i+1;
  1102. X                trybreakline(0, 0, thisindent, 0.0, 0, NULL);
  1103. X            }
  1104. X            if (bestbadness == BIGBADNESS && maxlinewidth < 9999) {
  1105. X                maxlinewidth = 9999;   /* no choice but to relax */
  1106. X                numalts = 0;
  1107. X            } else
  1108. X                break;
  1109. X            }
  1110. X            time0a = getcurtime();
  1111. X        }
  1112. X        randombreaks = 0;
  1113. X        trybreakline(0, 0, thisindent, 0.0, 0, NULL);
  1114. X        if (bestbadness == BIGBADNESS && maxlinewidth < 9999) {
  1115. X            numalts = 0;
  1116. X            maxlinewidth = 9999;   /* no choice but to relax this */
  1117. X            trybreakline(0, 0, thisindent, 0.0, 0, NULL);
  1118. X        }
  1119. X        time1 = getcurtime() - time0;
  1120. X        alts = numalts;
  1121. X        if (testinglinebreaker) {
  1122. X            if (savelimit < 0 && testinglinebreaker > 1) {
  1123. X            showbadlimit = bestbadness * (-savelimit);
  1124. X            numalts = 0;
  1125. X            bestnumalts = 0;
  1126. X            trybreakline(0, 0, thisindent, 0.0, 0, NULL);
  1127. X            }
  1128. X            fprintf(outf, "\n#if 1   /* accepted #%ld, badness = %g, tried %ld in %.3f sec */\n", bestnumalts, bestbadness, alts, time1/1000.0);
  1129. X        }
  1130. X        showbadlimit = savelimit;
  1131. X        maxlinewidth = savemaxlw;
  1132. X        flush_outbuf(bestnumbreaks, bestbreakpos, bestbreakindent,
  1133. X                 bestnumedits, besteditpos,
  1134. X                 besteditold, besteditnew);
  1135. X        if (((USETIME && time1 > 1000) || alts >= maxalts) &&
  1136. X            !regression) {
  1137. X            sprintf(outbuf, "Line breaker spent %.1f",
  1138. X                (time1 + time0 - time0a) / 1000.0);
  1139. X            if (time0 != time0a)
  1140. X            sprintf(outbuf + strlen(outbuf),
  1141. X                "+%.2f", (time0a - time0) / 1000.0);
  1142. X            sprintf(outbuf + strlen(outbuf),
  1143. X                " seconds, %ld tries on line %d [251]", alts, outf_lnum);
  1144. X            note(outbuf);
  1145. X        } else if (verbose) {
  1146. X            fprintf(logf, "%s, %d/%d: Line breaker spent %ld tries\n",
  1147. X                infname, inf_lnum, outf_lnum, alts);
  1148. X        }
  1149. X        if (testinglinebreaker)
  1150. X            fprintf(outf, "#endif\n\n");
  1151. X        } else {
  1152. X        if (testinglinebreaker < 2)
  1153. X            flush_outbuf(0, NULL, NULL, 0, NULL, NULL, NULL);
  1154. X        }
  1155. X        thisfutureindent = -1;
  1156. X        outbufpos = 0;
  1157. X        outbufcount = 0;
  1158. X    } else {
  1159. X        if (outbufpos == 0) {
  1160. X        if (ch == ' ' && !dontbreaklines)    /* eat leading spaces */
  1161. X            continue;
  1162. X        thisindent = applydelta(outindent, deltaindent);
  1163. X        deltaindent = 0;
  1164. X        }
  1165. X        if (outbufpos == outbufsize) {
  1166. X        outbufsize *= 2;
  1167. X        outbuf = REALLOC(outbuf, outbufsize, char);
  1168. X        }
  1169. X        outbuf[outbufpos++] = ch;
  1170. X        if (ch >= ' ')
  1171. X        outbufcount++;
  1172. X    }
  1173. X    }
  1174. X}
  1175. X
  1176. X
  1177. X
  1178. Xvoid out_n_spaces(n)
  1179. Xint n;
  1180. X{
  1181. X    while (--n >= 0)
  1182. X    output(" ");
  1183. X}
  1184. X
  1185. X
  1186. X
  1187. Xvoid out_spaces(spc, over, len, delta)
  1188. Xint spc, over, len, delta;
  1189. X{
  1190. X    int n;
  1191. X
  1192. X    if (spc == -999)
  1193. X    spc = commentindent;
  1194. X    if (spc < 0) {               /* right-justify */
  1195. X    n = (-spc) - cur_column() - len;
  1196. X    if (n < minspcthresh)
  1197. X        n = minspacing;
  1198. X    else
  1199. X        over = 1000;
  1200. X    } else if (spc >= 2000) {    /* tab to multiple */
  1201. X    spc -= 2000;
  1202. X    n = (spc-1) - ((cur_column()+spc-1) % spc);
  1203. X    if (n < minspcthresh)
  1204. X        n += spc;
  1205. X    } else if (spc >= 1000) {    /* absolute column */
  1206. X    spc -= 1000;
  1207. X    n = spc - cur_column();
  1208. X    if (n < minspcthresh)
  1209. X        n = minspacing;
  1210. X    } else                       /* relative spacing */
  1211. X    n = spc;
  1212. X    if (line_start()) {
  1213. X    singleindent(n);
  1214. X    } else if (len > 0 && over != 1000 && cur_column() + n + len > linewidth) {
  1215. X    output("\n");
  1216. X    out_spaces(over, 1000, len, 0);
  1217. X    singleindent(delta);
  1218. X    } else {
  1219. X    out_n_spaces(n);
  1220. X    }
  1221. X}
  1222. X
  1223. X
  1224. X
  1225. X
  1226. Xvoid testlinebreaker(lev, fn)
  1227. Xint lev;
  1228. Xchar *fn;
  1229. X{
  1230. X    char buf[256], *bp, *cp;
  1231. X    int first, indent;
  1232. X
  1233. X    testinglinebreaker = lev;
  1234. X    if (!fn)
  1235. X    return;
  1236. X    inf = fopen(fn, "r");
  1237. X    if (!inf) {
  1238. X    perror(fn);
  1239. X    exit(1);
  1240. X    }
  1241. X    sprintf(buf, "%s.br", fn);
  1242. X    outf = fopen(buf, "w");
  1243. X    if (!outf) {
  1244. X    perror(buf);
  1245. X    exit(1);
  1246. X    }
  1247. X    setup_out();
  1248. X    outindent = 4;
  1249. X    first = 1;
  1250. X    while (fgets(buf, 256, inf)) {
  1251. X    cp = buf + strlen(buf) - 2;
  1252. X    if (cp >= buf) {
  1253. X        bp = buf;
  1254. X        indent = 0;
  1255. X        while (isspace(*bp))
  1256. X        if (*bp++ == '\t')
  1257. X            indent += 8;
  1258. X        else
  1259. X            indent++;
  1260. X        if (first) {
  1261. X        first = 0;
  1262. X        outindent = indent;
  1263. X        }
  1264. X        if (!(*cp == '{' ||
  1265. X          *cp == ')' ||
  1266. X          *cp == ';') ||
  1267. X          (*cp == '/' && cp[-1] == '*')) {
  1268. X        cp[1] = '\001';   /* eat the \n */
  1269. X        } else {
  1270. X        first = 1;
  1271. X        }
  1272. X        output(bp);
  1273. X    }
  1274. X    }
  1275. X    fclose(outf);
  1276. X    fclose(inf);
  1277. X}
  1278. X
  1279. X
  1280. X
  1281. X
  1282. X
  1283. Xvoid outsection(size)
  1284. Xint size;
  1285. X{
  1286. X    if (size > sectionsize)
  1287. X        sectionsize = size;
  1288. X}
  1289. X
  1290. X
  1291. X
  1292. XStrlist *outcomments(cmt)
  1293. XStrlist *cmt;
  1294. X{
  1295. X    char *cp;
  1296. X    int saveindent = outindent, savesingle = deltaindent, theindent;
  1297. X    int i = 0;
  1298. X
  1299. X    if (!cmt)
  1300. X    return NULL;
  1301. X    if (!commentvisible(cmt)) {
  1302. X    setcommentkind(cmt, CMT_DONE);
  1303. X    return cmt->next;
  1304. X    }
  1305. X    if (*cmt->s == '\001') {
  1306. X    if (cmtdebug)
  1307. X        output(format_sd("[]  [%s:%d]",
  1308. X                 CMT_NAMES[getcommentkind(cmt)],
  1309. X                 cmt->value & CMT_MASK));
  1310. X    for (cp = cmt->s; *cp; cp++) {
  1311. X        output("\n");
  1312. X        if (cmtdebug && cp[1])
  1313. X        output("[]");
  1314. X    }
  1315. X    setcommentkind(cmt, CMT_DONE);
  1316. X    return cmt->next;
  1317. X    }
  1318. X    dontbreaklines++;
  1319. X    if (!strcmp(cmt->s, embedcomment) && *embedcomment && cmt->next &&
  1320. X    (*cmt->next->s == '\002' || *cmt->next->s == '\003')) {
  1321. X    cmt = cmt->next;
  1322. X    embeddedcode = 1;
  1323. X    theindent = 0;
  1324. X    cp = cmt->next->s + 1;
  1325. X    while (*cp++ == ' ')
  1326. X        theindent++;
  1327. X    } else {
  1328. X    moreindent(deltaindent);
  1329. X    if (cmt->s[0] == '\004')
  1330. X        outindent = 0;
  1331. X    theindent = outindent;
  1332. X    deltaindent = 0;
  1333. X    output("/*");
  1334. X    }
  1335. X    cp = cmt->s;
  1336. X    for (;;) {
  1337. X    if (*cp == '\002' || *cp == '\003' || *cp == '\004')
  1338. X        cp++;
  1339. X    if (embeddedcode) {
  1340. X        for (i = 0; *cp == ' ' && i < theindent; i++)
  1341. X        cp++;
  1342. X        i = *cp;
  1343. X    }
  1344. X    output(cp);
  1345. X    if (cmtdebug)
  1346. X        output(format_sd(" [%s:%d] ",
  1347. X                 CMT_NAMES[getcommentkind(cmt)],
  1348. X                 cmt->value & CMT_MASK));
  1349. X    setcommentkind(cmt, CMT_DONE);
  1350. X    cmt = cmt->next;
  1351. X    if (!cmt || !commentvisible(cmt))
  1352. X        break;
  1353. X    cp = cmt->s;
  1354. X    if (*cp != '\002' && *cp != '\003')
  1355. X        break;
  1356. X    output("\n");
  1357. X    if (!embeddedcode) {
  1358. X        outindent = (*cp == '\002') ? theindent : 0;
  1359. X        deltaindent = 0;
  1360. X    }
  1361. X    }
  1362. X    if (embeddedcode) {
  1363. X    embeddedcode = 0;
  1364. X    if (i) {   /* eat final blank line */
  1365. X        output("\n");
  1366. X    }
  1367. X    } else {
  1368. X    outindent = saveindent;
  1369. X    deltaindent = savesingle;
  1370. X    output("*/\n");
  1371. X    }
  1372. X    dontbreaklines--;
  1373. X    return cmt;
  1374. X}
  1375. X
  1376. X
  1377. X
  1378. Xvoid outcomment(cmt)
  1379. XStrlist *cmt;
  1380. X{
  1381. X    Strlist *savenext;
  1382. X    
  1383. X    if (cmt) {
  1384. X    savenext = cmt->next;
  1385. X    cmt->next = NULL;
  1386. X    outcomments(cmt);
  1387. X    cmt->next = savenext;
  1388. X    }
  1389. X}
  1390. X
  1391. X
  1392. X
  1393. Xvoid outtrailcomment(cmt, serial, indent)
  1394. XStrlist *cmt;
  1395. Xint serial, indent;
  1396. X{
  1397. X    int savedelta = deltaindent;
  1398. X
  1399. X#if 0
  1400. X    suppressnewline = 1;
  1401. X    output("\n");
  1402. X    suppressnewline = 0;
  1403. X#endif
  1404. X    cmt = findcomment(cmt, CMT_TRAIL, serial);
  1405. X    if (commentvisible(cmt)) {
  1406. X    out_spaces(indent, commentoverindent, commentlen(cmt), 0);
  1407. X    outcomment(cmt);
  1408. X    deltaindent = savedelta;
  1409. X    } else
  1410. X    output("\n");
  1411. X}
  1412. X
  1413. X
  1414. X
  1415. Xvoid flushcomments(cmt, kind, serial)
  1416. XStrlist **cmt;
  1417. Xint kind, serial;
  1418. X{
  1419. X    Strlist *cmt2, *cmt3;
  1420. X    int saveindent, savesingle, saveeat;
  1421. X
  1422. X    if (!cmt)
  1423. X    cmt = &curcomments;
  1424. X    cmt2 = extractcomment(cmt, kind, serial);
  1425. X    saveindent = outindent;
  1426. X    savesingle = deltaindent;
  1427. X    moreindent(deltaindent);
  1428. X    deltaindent = 0;
  1429. X    saveeat = eatcomments;
  1430. X    if (eatcomments == 2)
  1431. X    eatcomments = 0;
  1432. X    cmt3 = cmt2;
  1433. X    while (cmt3)
  1434. X    cmt3 = outcomments(cmt3);
  1435. X    eatcomments = saveeat;
  1436. X    outindent = saveindent;
  1437. X    deltaindent = savesingle;
  1438. X    strlist_empty(&cmt2);
  1439. X}
  1440. X
  1441. X
  1442. X
  1443. X
  1444. X
  1445. Xchar *rawCstring(fmt, s, len, special)
  1446. Xchar *fmt;
  1447. Xregister char *s;
  1448. Xint len, special;
  1449. X{
  1450. X    char buf[500];
  1451. X    register char *cp;
  1452. X    register unsigned char ch;
  1453. X
  1454. X    cp = buf;
  1455. X    while (--len >= 0) {
  1456. X        ch = *((unsigned char *) s);
  1457. X        s++;
  1458. X        if (ch == 0 && (len == 0 || !isdigit(*s))) {
  1459. X            *cp++ = '\\';
  1460. X            *cp++ = '0';
  1461. X        } else if (ch == '\n') {
  1462. X            *cp++ = '\\';
  1463. X            *cp++ = 'n';
  1464. X        } else if (ch == '\b') {
  1465. X            *cp++ = '\\';
  1466. X            *cp++ = 'b';
  1467. X        } else if (ch == '\t') {
  1468. X            *cp++ = '\\';
  1469. X            *cp++ = 't';
  1470. X        } else if (ch == '\f') {
  1471. X            *cp++ = '\\';
  1472. X            *cp++ = 'f';
  1473. X#if 0
  1474. X        } else if (ch == '\r') {
  1475. X            *cp++ = '\\';
  1476. X            *cp++ = 'r';
  1477. X#endif
  1478. X        } else if (ch < ' ' || ch >= 127) {
  1479. X            *cp++ = '\\';
  1480. X            *cp++ = '0' + (ch>>6);
  1481. X            *cp++ = '0' + ((ch>>3) & 7);
  1482. X            *cp++ = '0' + (ch & 7);
  1483. X        } else if (ch == special) {
  1484. X            switch (ch) {
  1485. X                case '%':
  1486. X                    *cp++ = ch;
  1487. X                    *cp++ = ch;
  1488. X                    break;
  1489. X            }
  1490. X        } else {
  1491. X            if (ch == '"' || ch == '\\')
  1492. X                *cp++ = '\\';
  1493. X            *cp++ = ch;
  1494. X        }
  1495. X    }
  1496. X    *cp = 0;
  1497. X    return format_s(fmt, buf);
  1498. X}
  1499. X
  1500. X
  1501. Xchar *makeCstring(s, len)
  1502. Xregister char *s;
  1503. Xint len;
  1504. X{
  1505. X    return rawCstring("\"%s\"", s, len, 0);
  1506. X}
  1507. X
  1508. X
  1509. X
  1510. Xchar *makeCchar(ich)
  1511. Xint ich;
  1512. X{
  1513. X    char buf[500];
  1514. X    register char *cp;
  1515. X    register unsigned char ch = (ich & 0xff);
  1516. X
  1517. X    if (ich < 0 || ich > 255 || (ich == 0 && !nullcharconst))
  1518. X        return format_d("%d", ich);
  1519. X    cp = buf;
  1520. X    if (ch == 0) {
  1521. X        *cp++ = '\\';
  1522. X        *cp++ = '0';
  1523. X    } else if (ch == '\n') {
  1524. X        *cp++ = '\\';
  1525. X        *cp++ = 'n';
  1526. X    } else if (ch == '\b') {
  1527. X        *cp++ = '\\';
  1528. X        *cp++ = 'b';
  1529. X    } else if (ch == '\t') {
  1530. X        *cp++ = '\\';
  1531. X        *cp++ = 't';
  1532. X    } else if (ch == '\f') {
  1533. X        *cp++ = '\\';
  1534. X        *cp++ = 'f';
  1535. X#if 0
  1536. X    } else if (ch == '\r') {
  1537. X        *cp++ = '\\';
  1538. X        *cp++ = 'r';
  1539. X#endif
  1540. X    } else if (ch < ' ' || ch >= 127) {
  1541. X        *cp++ = '\\';
  1542. X        *cp++ = '0' + (ch>>6);
  1543. X        *cp++ = '0' + ((ch>>3) & 7);
  1544. X        *cp++ = '0' + (ch & 7);
  1545. X    } else {
  1546. X        if (ch == '\'' || ch == '\\')
  1547. X            *cp++ = '\\';
  1548. X        *cp++ = ch;
  1549. X    }
  1550. X    *cp = 0;
  1551. X    return format_s("'%s'", buf);
  1552. X}
  1553. X
  1554. X
  1555. X
  1556. X
  1557. X
  1558. X
  1559. X/* End. */
  1560. X
  1561. X
  1562. END_OF_FILE
  1563. if test 34270 -ne `wc -c <'src/out.c'`; then
  1564.     echo shar: \"'src/out.c'\" unpacked with wrong size!
  1565. fi
  1566. # end of 'src/out.c'
  1567. fi
  1568. echo shar: End of archive 12 \(of 32\).
  1569. cp /dev/null ark12isdone
  1570. MISSING=""
  1571. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 ; do
  1572.     if test ! -f ark${I}isdone ; then
  1573.     MISSING="${MISSING} ${I}"
  1574.     fi
  1575. done
  1576. if test "${MISSING}" = "" ; then
  1577.     echo You have unpacked all 32 archives.
  1578.     echo "Now see PACKNOTES and the README"
  1579.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1580. else
  1581.     echo You still need to unpack the following archives:
  1582.     echo "        " ${MISSING}
  1583. fi
  1584. ##  End of shell archive.
  1585. exit 0
  1586.