home *** CD-ROM | disk | FTP | other *** search
- Subject: v21i057: Pascal to C translator, Part12/32
- Newsgroups: comp.sources.unix
- Approved: rsalz@uunet.UU.NET
- X-Checksum-Snefru: 221b1911 cd936d81 1b93dae0 23f27efa
-
- Submitted-by: Dave Gillespie <daveg@csvax.caltech.edu>
- Posting-number: Volume 21, Issue 57
- Archive-name: p2c/part12
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 12 (of 32)."
- # Contents: src/out.c
- # Wrapped by rsalz@litchi.bbn.com on Mon Mar 26 14:29:35 1990
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'src/out.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'src/out.c'\"
- else
- echo shar: Extracting \"'src/out.c'\" \(34270 characters\)
- sed "s/^X//" >'src/out.c' <<'END_OF_FILE'
- X/* "p2c", a Pascal to C translator.
- X Copyright (C) 1989 David Gillespie.
- X Author's address: daveg@csvax.caltech.edu; 256-80 Caltech/Pasadena CA 91125.
- X
- XThis program is free software; you can redistribute it and/or modify
- Xit under the terms of the GNU General Public License as published by
- Xthe Free Software Foundation (any version).
- X
- XThis program is distributed in the hope that it will be useful,
- Xbut WITHOUT ANY WARRANTY; without even the implied warranty of
- XMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- XGNU General Public License for more details.
- X
- XYou should have received a copy of the GNU General Public License
- Xalong with this program; see the file COPYING. If not, write to
- Xthe Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
- X
- X
- X
- X
- X/* This needs to go before trans.h (and thus p2c.proto) is read */
- X
- Xtypedef struct S_paren {
- X struct S_paren *next;
- X int pos, indent, qmindent, flags;
- X} Paren;
- X
- X
- X
- X#define PROTO_OUT_C
- X#include "trans.h"
- X
- X
- X#ifndef USETIME
- X# if defined(BSD) || defined(hpux)
- X# define USETIME 1
- X# else
- X# define USETIME 0
- X# endif
- X#endif
- X
- X#if USETIME
- X# include <sys/time.h>
- X#else
- X# include <time.h>
- X#endif
- X
- X
- X
- X
- X/* Output control characters:
- X
- X \001 \B Possible break point
- X \002 \X Break point in parentheses
- X \003 \( Invisible open paren
- X \004 \) Invisible close paren
- X \005 \T Set left margin
- X \006 \F Forced break point
- X \007 \A Preceding paren requires all-or-none breaking
- X \010 \[ Invisible open paren, becomes visible if not all on one line
- X \011 \S Break point after last "special argument" of a function
- X \012 \n (newline)
- X \013 \E Preceding break has extra penalty
- X \014 \f (form-feed)
- X \015 \H Hang-indent the preceding operator
- X \016 \. (unused)
- X \017 \C Break point for last : of a ?: construct
- X
- X*/
- X
- Xchar spchars[] = ".BX()TFA[SnEfH.C................";
- X
- X
- X
- XStatic int testinglinebreaker = 0;
- X
- XStatic int deltaindent, thisindent, thisfutureindent;
- XStatic int sectionsize, blanklines, codesectsize, hdrsectsize;
- XStatic int codelnum, hdrlnum;
- X
- X#define MAXBREAKS 200
- XStatic int numbreaks, bestnumbreaks;
- XStatic double bestbadness;
- XStatic int breakpos[MAXBREAKS], breakindent[MAXBREAKS];
- XStatic int breakcount[MAXBREAKS], breakparen[MAXBREAKS];
- XStatic int bestbreakpos[MAXBREAKS], bestbreakindent[MAXBREAKS];
- XStatic int breakerrorflag;
- X
- X#define MAXEDITS 200
- XStatic int numedits, bestnumedits;
- XStatic int editpos[MAXEDITS], besteditpos[MAXEDITS];
- XStatic char editold[MAXEDITS], editnew[MAXEDITS];
- XStatic char besteditold[MAXEDITS], besteditnew[MAXEDITS];
- X
- XStatic Paren *parenlist;
- X
- XStatic long numalts, bestnumalts;
- XStatic int randombreaks;
- X
- XStatic char *outbuf;
- XStatic int outbufpos, outbufcount, outbufsize;
- XStatic int suppressnewline, lastlinelength;
- XStatic int eatblanks;
- XStatic int embeddedcode;
- XStatic int showingsourcecode = 0;
- X
- X#define BIGBADNESS (1e20)
- X
- X
- X
- Xvoid setup_out()
- X{
- X end_source();
- X fprintf(outf, "/* From input file \"%s\" */\n", infname);
- X outf_lnum++;
- X hdrlnum = 1;
- X outindent = 0;
- X deltaindent = 0;
- X thisindent = 0;
- X thisfutureindent = -1;
- X sectionsize = 2;
- X blanklines = 0;
- X dontbreaklines = 0;
- X embeddedcode = 0;
- X outputmode = 0;
- X suppressnewline = 0;
- X eatblanks = 0;
- X outbufsize = 1000;
- X outbuf = ALLOC(outbufsize, char, misc);
- X outbufpos = 0;
- X outbufcount = 0;
- X srand(17);
- X}
- X
- X
- X
- Xvoid select_outfile(fp)
- XFILE *fp;
- X{
- X if (outf == codef) {
- X codesectsize = sectionsize;
- X codelnum = outf_lnum;
- X } else {
- X hdrsectsize = sectionsize;
- X hdrlnum = outf_lnum;
- X }
- X outf = fp;
- X if (outf == codef) {
- X sectionsize = codesectsize;
- X outf_lnum = codelnum;
- X } else {
- X sectionsize = hdrsectsize;
- X outf_lnum = hdrlnum;
- X }
- X}
- X
- X
- X
- Xvoid start_source()
- X{
- X if (!showingsourcecode) {
- X fprintf(outf, "\n#ifdef Pascal\n");
- X showingsourcecode = 1;
- X }
- X}
- X
- Xvoid end_source()
- X{
- X if (showingsourcecode) {
- X fprintf(outf, "#endif /*Pascal*/\n\n");
- X showingsourcecode = 0;
- X }
- X}
- X
- X
- X
- Xint line_start()
- X{
- X return (outbufcount == 0);
- X}
- X
- X
- Xint cur_column()
- X{
- X if (outbufpos == 0)
- X return outindent;
- X else
- X return thisindent + outbufcount;
- X}
- X
- X
- X
- Xint lookback(n)
- Xint n;
- X{
- X if (n <= 0 || n > outbufpos)
- X return 0;
- X else
- X return outbuf[outbufpos - n];
- X}
- X
- X
- Xint lookback_prn(n)
- Xint n;
- X{
- X for (;;) {
- X if (n <= 0 || n > outbufpos)
- X return 0;
- X else if (outbuf[outbufpos - n] >= ' ')
- X return outbuf[outbufpos - n];
- X else
- X n++;
- X }
- X}
- X
- X
- X
- X/* Combine two indentation adjustments */
- Xint adddeltas(d1, d2)
- Xint d1, d2;
- X{
- X if (d2 >= 1000)
- X return d2;
- X else
- X return d1 + d2;
- X}
- X
- X
- X/* Apply an indentation delta */
- Xint applydelta(i, d)
- Xint i, d;
- X{
- X if (d >= 1000)
- X return d - 1000;
- X else
- X return i + d;
- X}
- X
- X
- X/* Adjust the current indentation by delta */
- Xvoid moreindent(delta)
- Xint delta;
- X{
- X outindent = applydelta(outindent, delta);
- X}
- X
- X
- X/* Adjust indentation for just this line */
- Xvoid singleindent(delta)
- Xint delta;
- X{
- X deltaindent = adddeltas(deltaindent, delta);
- X}
- X
- X
- X/* Predict indentation for next line */
- Xvoid futureindent(num)
- Xint num;
- X{
- X thisfutureindent = applydelta(applydelta(outindent, deltaindent), num);
- X}
- X
- X
- Xint parsedelta(cp, def)
- Xchar *cp;
- Xint def;
- X{
- X if (!cp || !*cp)
- X return def;
- X if ((*cp == '+' || *cp == '-') && isdigit(cp[1]))
- X return atoi(cp);
- X if (*cp == '*' && isdigit(cp[1]))
- X return 2000 + atoi(cp+1);
- X else
- X return 1000 + atoi(cp);
- X}
- X
- X
- X
- X
- XStatic void leading_tab(col)
- Xint col;
- X{
- X if (col > maxlinewidth)
- X return; /* something wrong happened! */
- X if (phystabsize > 0) {
- X while (col >= phystabsize) {
- X putc('\t', outf);
- X col -= phystabsize;
- X }
- X }
- X while (col > 0) {
- X putc(' ', outf);
- X col--;
- X }
- X}
- X
- X
- X
- Xvoid eatblanklines()
- X{
- X eatblanks = 1;
- X}
- X
- X
- X
- XStatic void flush_outbuf(numbreaks, breakpos, breakindent,
- X numedits, editpos, editold, editnew)
- Xint numbreaks, *breakpos, *breakindent, numedits, *editpos;
- Xchar *editold, *editnew;
- X{
- X unsigned char ch, ch2;
- X char *cp;
- X int i, j, linelen = 0, spaces, hashline;
- X int editsaves[MAXEDITS];
- X
- X end_source();
- X if (outbufcount > 0) {
- X for (i = 0; i < numedits; i++) {
- X editsaves[i] = outbuf[editpos[i]];
- X outbuf[editpos[i]] = editnew[i];
- X }
- X leading_tab(thisindent);
- X cp = outbuf;
- X hashline = (*cp == '#'); /* a preprocessor directive */
- X spaces = 0;
- X j = 1;
- X for (i = 0; i < outbufpos; ) {
- X if (j < numbreaks && i == breakpos[j]) {
- X if (hashline)
- X fprintf(outf, " \\"); /* trailing backslash required */
- X putc('\n', outf);
- X outf_lnum++;
- X leading_tab(breakindent[j]);
- X linelen = breakindent[j];
- X j++;
- X while (i < outbufpos && *cp == ' ')
- X i++, cp++; /* eat leading spaces */
- X spaces = 0; /* eat trailing spaces */
- X } else {
- X ch = *cp++;
- X if (ch == ' ') {
- X spaces++;
- X } else if (ch > ' ') {
- X linelen += spaces;
- X while (spaces > 0)
- X putc(' ', outf), spaces--;
- X linelen++;
- X if (ch == '\\' && embeddedcode) {
- X if (*cp == '[') {
- X putc('{', outf);
- X cp++, i++;
- X } else if (*cp == ']') {
- X putc('}', outf);
- X cp++, i++;
- X } else
- X putc(ch, outf);
- X } else
- X putc(ch, outf);
- X } else if (testinglinebreaker >= 3) {
- X linelen += spaces;
- X while (spaces > 0)
- X putc(' ', outf), spaces--;
- X linelen++;
- X putc('\\', outf);
- X ch2 = spchars[ch];
- X if (ch2 != '.')
- X putc(ch2, outf);
- X else {
- X putc('0' + ((ch >> 6) & 7), outf);
- X putc('0' + ((ch >> 3) & 7), outf);
- X putc('0' + (ch & 7), outf);
- X }
- X }
- X i++;
- X }
- X }
- X for (i = 0; i < numedits; i++)
- X outbuf[editpos[i]] = editsaves[i];
- X eatblanks = 0;
- X } else if (eatblanks) {
- X return;
- X }
- X if (suppressnewline) {
- X lastlinelength = linelen;
- X } else
- X putc('\n', outf);
- X outf_lnum++;
- X}
- X
- X
- X
- X#define ISQUOTE(ch) ((ch)=='"' || (ch)=='\'')
- X#define ISOPENP(ch) ((ch)=='(' || (ch)=='[' || (ch)=='\003' || (ch)=='\010')
- X#define ISCLOSEP(ch) ((ch)==')' || (ch)==']' || (ch)=='\004')
- X#define ISBREAK(ch) ((ch)=='\001' || (ch)=='\002' || (ch)=='\006' || (ch)=='\011' || (ch)=='\017')
- X
- XStatic int readquotes(posp, err)
- Xint *posp, err;
- X{
- X int pos;
- X char quote;
- X
- X pos = *posp;
- X quote = outbuf[pos++];
- X while (pos < outbufpos && outbuf[pos] != quote) {
- X if (outbuf[pos] == '\\')
- X pos++;
- X pos++;
- X }
- X if (pos >= outbufpos) {
- X if (err && breakerrorflag) {
- X intwarning("output", "Mismatched quotes [248]");
- X breakerrorflag = 0;
- X }
- X return 0;
- X } else {
- X *posp = pos;
- X return 1;
- X }
- X}
- X
- X
- XStatic int maxdepth;
- X
- XStatic int readparens(posp, err)
- Xint *posp, err;
- X{
- X char ch, closing;
- X int pos, level;
- X
- X pos = *posp;
- X switch (outbuf[pos]) {
- X case '(':
- X closing = ')';
- X break;
- X case '[':
- X closing = ']';
- X break;
- X case '\003':
- X case '\010':
- X closing = '\004';
- X break;
- X default:
- X closing = 0;
- X break;
- X }
- X level = 0;
- X for (;;) {
- X pos++;
- X if (pos >= outbufpos)
- X break;
- X ch = outbuf[pos];
- X if (ISOPENP(ch)) {
- X level++;
- X if (level > maxdepth)
- X maxdepth = level;
- X } else if (ISCLOSEP(ch)) {
- X level--;
- X if (level < 0) {
- X if (closing && outbuf[pos] != closing)
- X break;
- X *posp = pos;
- X return 1;
- X }
- X } else if (ISQUOTE(ch)) {
- X if (!readquotes(&pos, err))
- X return 0;
- X }
- X }
- X if (err && breakerrorflag) {
- X switch (closing) {
- X case ')':
- X intwarning("output", "Mismatched parentheses [249]");
- X break;
- X case ']':
- X intwarning("output", "Mismatched brackets [249]");
- X break;
- X default:
- X intwarning("output", "Mismatched clauses [250]");
- X break;
- X }
- X breakerrorflag = 0;
- X }
- X return 0;
- X}
- X
- X
- X
- XStatic int measurechars(first, last)
- Xint first, last;
- X{
- X int count = 0;
- X
- X while (first <= last) {
- X if (outbuf[first] >= ' ')
- X count++;
- X first++;
- X }
- X return count;
- X}
- X
- X
- X
- XStatic void makeedit(pos, ch)
- Xint pos, ch;
- X{
- X editpos[numedits] = pos;
- X editold[numedits] = outbuf[pos];
- X editnew[numedits] = ch;
- X outbuf[pos] = ch;
- X numedits++;
- X}
- X
- XStatic void unedit()
- X{
- X numedits--;
- X outbuf[editpos[numedits]] = editold[numedits];
- X}
- X
- X
- XStatic int parencount(par)
- XParen *par;
- X{
- X int count = 0;
- X
- X while (par) {
- X count++;
- X par = par->next;
- X }
- X return count;
- X}
- X
- X
- X
- X
- X/* The following routine explores the tree of all possible line breaks,
- X pruning according to the fact that "badness" and "extra" are
- X increasing functions. The object is to find the set of breaks and
- X indentation with the least total badness.
- X (The basic idea was borrowed from Donald Knuth's "TeX".)
- X*/
- X
- X/* As an additional optimization, the concept of a "simple" line is used,
- X i.e., a line with a structure such that the best break is sure to be
- X the straightforward left-to-right fill used by a simple word processor.
- X (For example, a long line with nothing but comma-breakpoints is simple.)
- X
- X Also, if the line is very long a few initial random passes are made just
- X to scope out an estimate of the eventual badness of the line. This
- X combined with the badness cull helps keep the breaker from using up its
- X quota of tries before even considering a key break point! Note that
- X when randombreaks==1, each call to trybreakline is fast since only one
- X branch is taken at each decision point.
- X*/
- X
- X
- X#define randtest(lim) (!randombreaks ? -1 \
- X : randombreaks > 0 \
- X ? parencount(parens) < randombreaks-1 \
- X : randombreaks == -2 \
- X ? 0 \
- X : (rand() & 0xfff) < (lim))
- X
- X#define TB_BRKCOUNT 0x0ff
- X#define TB_FORCEBRK 0x100
- X#define TB_NOBREAK 0x200
- X#define TB_ALREADYBRK 0x400
- X#define TB_ALLORNONE 0x800
- X#define TB_EXTRAIND 0x1000
- X#define TB_EXTRAIND2 0x2000
- X
- X#define TBR_ABORT 0x1
- X#define TBR_SIMPLE 0x2
- X#define TBR_REACHED 0x4
- X
- XStatic int trybreakline(pos, count, indent, badness, flags, parens)
- Xint pos, count, indent, flags;
- Xdouble badness;
- XParen *parens;
- X{
- X int edited;
- X int i, j, jmask, f, pos2, r;
- X char ch, ch2, closing;
- X double extra, penalty;
- X Paren *pp;
- X
- X#if 0
- X { static double save = -1;
- X if (showbadlimit != save) printf("Showbadlimit = %g\n", showbadlimit);
- X save = showbadlimit;
- X }
- X#endif
- X
- X if (numalts >= maxalts)
- X return TBR_ABORT;
- X jmask = -1;
- X for (;;) {
- X if (numbreaks >= MAXBREAKS) { /* must leave rest of line alone */
- X count += measurechars(pos, outbufpos-1);
- X pos = outbufpos;
- X }
- X i = count - breakcount[numbreaks-1] +
- X breakindent[numbreaks-1] - linewidth;
- X if (i <= 0)
- X extra = 0;
- X else {
- X if (i + linewidth >= maxlinewidth || randombreaks == -2)
- X return 0; /* absolutely too long! */
- X extra = overwidepenalty + ((long)i*i)*overwideextrapenalty;
- X jmask &= ~TBR_SIMPLE;
- X if (extra < 0)
- X extra = 0;
- X }
- X if ((testinglinebreaker > 1 && showbadlimit > 0) ?
- X (badness + extra >= showbadlimit) :
- X (badness + extra >= bestbadness)) {
- X numalts++;
- X return 0; /* no point in going on, badness will only increase */
- X }
- X if (pos >= outbufpos)
- X break;
- X if (parens && pos >= parens->pos) {
- X indent = parens->indent;
- X flags = parens->flags;
- X parens = parens->next;
- X }
- X ch = outbuf[pos++];
- X if (ch >= ' ')
- X count++;
- X switch (ch) {
- X
- X case '(':
- X case '[':
- X case '\003': /* "invisible open paren" */
- X case '\010': /* "semi-invisible open paren" */
- X pos2 = pos - 1;
- X if (!readparens(&pos2, 1))
- X break;
- X i = measurechars(pos, pos2);
- X if (count + i - breakcount[numbreaks-1] +
- X breakindent[numbreaks-1] <= linewidth) {
- X /* it fits, so leave it on one line */
- X#if 0 /* I don't think this is necessary */
- X while (pos <= pos2) {
- X if (outbuf[pos] == '\002') {
- X jmask &= ~TBR_SIMPLE;
- X pos = pos2 + 1;
- X break;
- X }
- X pos++;
- X }
- X#else
- X pos = pos2 + 1;
- X#endif
- X count += i;
- X break;
- X }
- X pp = ALLOC(1, Paren, parens); /* doesn't fit, try poss breaks */
- X pp->next = parens;
- X pp->pos = pos2;
- X pp->indent = indent;
- X pp->qmindent = indent;
- X pp->flags = flags;
- X parens = pp;
- X flags = 0;
- X if (ch == '\010' && /* change to real parens when broken */
- X numedits+1 < MAXEDITS) { /* (assume it will be broken!) */
- X makeedit(pos-1, '(');
- X makeedit(pos2, ')');
- X count++; /* count the new open paren */
- X edited = 1;
- X } else
- X edited = 0;
- X i = breakindent[numbreaks-1] + count - breakcount[numbreaks-1];
- X if (i <= thisindent)
- X r = 0; /* e.g., don't break top-level assignments */
- X else if (i == indent + extraindent)
- X r = 1; /* don't waste time on identical operations */
- X else
- X r = randtest(0xc00);
- X if (r != 0) {
- X j = trybreakline(pos, count, i,
- X badness + MAX(- extraindentpenalty,0),
- X flags, parens);
- X } else
- X j = 0;
- X if (r != 1) {
- X j &= trybreakline(pos, count, indent + extraindent,
- X badness + MAX(extraindentpenalty,0),
- X flags | TB_EXTRAIND, parens);
- X }
- X if (!randombreaks && bumpindent != 0) {
- X if (i == thisfutureindent) {
- X j &= trybreakline(pos, count, i + bumpindent,
- X badness + MAX(- extraindentpenalty,0)
- X + bumpindentpenalty,
- X flags, parens);
- X } else if (indent + extraindent == thisfutureindent) {
- X j &= trybreakline(pos, count,
- X indent + extraindent + bumpindent,
- X badness + MAX(extraindentpenalty,0)
- X + bumpindentpenalty,
- X flags | TB_EXTRAIND, parens);
- X }
- X }
- X if (edited) {
- X unedit();
- X unedit();
- X }
- X FREE(pp);
- X return j & jmask;
- X
- X case '\005': /* "set left margin" */
- X indent = breakindent[numbreaks-1] +
- X count - breakcount[numbreaks-1];
- X break;
- X
- X case '\007': /* "all-or-none breaking" */
- X flags |= TB_ALLORNONE;
- X break;
- X
- X case '\001': /* "possible break point" */
- X case '\002': /* "break point in parens" */
- X case '\006': /* "forced break point" */
- X case '\011': /* "break point after special args" */
- X case '\017': /* "break point for final : operator" */
- X /* first try the non-breaking case */
- X if (ch != '\001' && ch != '\006')
- X jmask &= ~TBR_SIMPLE;
- X if ((flags & TB_BRKCOUNT) != TB_BRKCOUNT)
- X flags++; /* increment TB_BRKCOUNT field */
- X if (outbuf[pos] == '?' && parens)
- X parens->qmindent = breakindent[numbreaks-1] +
- X count - breakcount[numbreaks-1];
- X j = TBR_REACHED;
- X if (ch == '\006' || (flags & TB_FORCEBRK)) {
- X /* don't try the non-breaking case */
- X } else {
- X if (ch == '\011') {
- X i = breakindent[numbreaks-1] +
- X count - breakcount[numbreaks-1] + 2;
- X } else {
- X i = indent;
- X }
- X f = flags;
- X if (f & TB_ALLORNONE)
- X f |= TB_NOBREAK;
- X r = randtest(0x800);
- X if (r != 1 || (flags & TB_NOBREAK)) {
- X j = trybreakline(pos, count, i, badness, f, parens) &
- X jmask;
- X if (randombreaks == -2 && !(j & TBR_REACHED)) {
- X r = -1;
- X j |= TBR_REACHED;
- X }
- X if (r == 0 || (j & TBR_SIMPLE))
- X flags |= TB_NOBREAK;
- X }
- X }
- X if (flags & TB_NOBREAK)
- X return j;
- X if (flags & TB_ALLORNONE)
- X flags |= TB_FORCEBRK;
- X if (flags & TB_EXTRAIND) {
- X flags &= ~TB_EXTRAIND;
- X flags |= TB_EXTRAIND2;
- X }
- X /* now try breaking here */
- X if (ch == '\017')
- X indent = parens->qmindent;
- X if (indent < 0)
- X indent = 0;
- X breakpos[numbreaks] = pos;
- X breakcount[numbreaks] = count;
- X breakindent[numbreaks] = indent;
- X breakparen[numbreaks] = parens ? parens->pos : 0;
- X numbreaks++;
- X penalty = extra;
- X if (indent == thisfutureindent) {
- X i = pos;
- X while (i < outbufpos-1 && outbuf[i] <= ' ')
- X i++;
- X ch2 = outbuf[i]; /* first character on next line */
- X if (ch2 != '(' && ch2 != '!' && ch2 != '~' && ch2 != '-')
- X penalty += nobumpindentpenalty;
- X }
- X switch (ch) {
- X case '\001':
- X penalty += commabreakpenalty;
- X if (flags & TB_ALREADYBRK)
- X penalty += morebreakpenalty;
- X break;
- X case '\011':
- X i = parencount(parens);
- X penalty += specialargbreakpenalty + commabreakextrapenalty*i;
- X break;
- X case '\002':
- X case '\017':
- X i = parencount(parens);
- X if (outbuf[pos-2] == '(')
- X penalty += parenbreakpenalty + parenbreakextrapenalty*i;
- X else if (outbuf[pos-2] == ',')
- X penalty += commabreakpenalty + commabreakextrapenalty*i;
- X else if (outbuf[pos-2] == '=')
- X penalty += assignbreakpenalty + assignbreakextrapenalty*i;
- X else if (outbuf[pos] == '?') {
- X penalty += qmarkbreakpenalty + qmarkbreakextrapenalty*i;
- X if (parens)
- X parens->qmindent = breakindent[numbreaks-1] +
- X count - breakcount[numbreaks-1];
- X } else
- X penalty += opbreakpenalty + opbreakextrapenalty*i;
- X if (outbuf[pos-2] == '-')
- X penalty += exhyphenpenalty;
- X if (flags & TB_ALREADYBRK)
- X penalty += morebreakpenalty + morebreakextrapenalty*i;
- X break;
- X default:
- X break;
- X }
- X while (pos < outbufpos && outbuf[pos] == '\013') {
- X penalty += wrongsidepenalty;
- X pos++;
- X }
- X penalty -= earlybreakpenalty*(flags & TB_BRKCOUNT);
- X /* the following test is not quite right, but it's not too bad. */
- X if (breakindent[numbreaks-2] == breakindent[numbreaks-1] &&
- X breakparen[numbreaks-2] != breakparen[numbreaks-1])
- X penalty += sameindentpenalty;
- X#if 0
- X else if (ch == '\002' && parens && /*don't think this is needed*/
- X parens->indent == breakindent[numbreaks-1] &&
- X parens->pos != breakparen[numbreaks-1])
- X penalty += sameindentpenalty + 0.001; /***/
- X#endif
- X penalty += (breakindent[numbreaks-1] - thisindent) *
- X indentamountpenalty;
- X if (penalty < 1) penalty = 1;
- X pos2 = pos;
- X while (pos2 < outbufpos && outbuf[pos2] == ' ')
- X pos2++;
- X flags |= TB_ALREADYBRK;
- X j = trybreakline(pos2, count, indent, badness + penalty,
- X flags, parens) & jmask;
- X numbreaks--;
- X return j;
- X
- X case '\015': /* "hang-indent operator" */
- X if (count <= breakcount[numbreaks-1] + 2 &&
- X !(flags & TB_EXTRAIND2)) {
- X breakindent[numbreaks-1] -= count - breakcount[numbreaks-1];
- X pos2 = pos;
- X while (pos2 < outbufpos && outbuf[pos2] <= ' ') {
- X if (outbuf[pos2] == ' ')
- X breakindent[numbreaks-1]--;
- X pos2++;
- X }
- X }
- X break;
- X
- X case '"':
- X case '\'':
- X closing = ch;
- X while (pos < outbufpos && outbuf[pos] != closing) {
- X if (outbuf[pos] == '\\')
- X pos++, count++;
- X pos++;
- X count++;
- X }
- X if (pos >= outbufpos) {
- X intwarning("output", "Mismatched quotes [248]");
- X continue;
- X }
- X pos++;
- X count++;
- X break;
- X
- X case '/':
- X if (pos < outbufpos && (outbuf[pos] == '*' ||
- X (outbuf[pos] == '/' && cplus > 0))) {
- X count += measurechars(pos, outbufpos-1);
- X pos = outbufpos; /* assume comment is at end of line */
- X }
- X break;
- X
- X }
- X }
- X numalts++;
- X badness += extra;
- X if (testinglinebreaker > 1) {
- X if (badness >= bestbadness &&
- X (badness < showbadlimit || showbadlimit == 0)) {
- X fprintf(outf, "\n#if 0 /* rejected #%ld, badness = %g >= %g */\n", numalts, badness, bestbadness);
- X flush_outbuf(numbreaks, breakpos, breakindent,
- X numedits, editpos, editold, editnew);
- X fprintf(outf, "#endif\n");
- X return TBR_SIMPLE & jmask;
- X } else if ((bestbadness < showbadlimit || showbadlimit == 0) &&
- X bestnumalts > 0) {
- X fprintf(outf, "\n#if 0 /* rejected #%ld, badness = %g > %g */\n", bestnumalts, bestbadness, badness);
- X flush_outbuf(bestnumbreaks, bestbreakpos, bestbreakindent,
- X bestnumedits, besteditpos,
- X besteditold, besteditnew);
- X fprintf(outf, "#endif\n");
- X }
- X }
- X bestbadness = badness;
- X bestnumbreaks = numbreaks;
- X bestnumalts = numalts;
- X for (i = 0; i < numbreaks; i++) {
- X bestbreakpos[i] = breakpos[i];
- X bestbreakindent[i] = breakindent[i];
- X }
- X bestnumedits = numedits;
- X for (i = 0; i < numedits; i++) {
- X besteditpos[i] = editpos[i];
- X besteditold[i] = editold[i];
- X besteditnew[i] = editnew[i];
- X }
- X return TBR_SIMPLE & jmask;
- X}
- X
- X
- X
- X
- Xint parse_breakstr(cp)
- Xchar *cp;
- X{
- X short val = 0;
- X
- X if (isdigit(*cp))
- X return atoi(cp);
- X while (*cp && !isspace(*cp) && *cp != '}') {
- X switch (toupper(*cp++)) {
- X
- X case 'N':
- X case '=':
- X break;
- X
- X case 'L':
- X val |= BRK_LEFT;
- X break;
- X
- X case 'R':
- X val |= BRK_RIGHT;
- X break;
- X
- X case 'H':
- X val |= BRK_HANG | BRK_LEFT;
- X break;
- X
- X case '>':
- X if (val & BRK_LEFT)
- X val |= BRK_LPREF;
- X else if (val & BRK_RIGHT)
- X val |= BRK_RPREF;
- X else
- X return -1;
- X break;
- X
- X case '<':
- X if (val & BRK_LEFT)
- X val |= BRK_RPREF;
- X else if (val & BRK_RIGHT)
- X val |= BRK_LPREF;
- X else
- X return -1;
- X break;
- X
- X case 'A':
- X val |= BRK_ALLNONE;
- X break;
- X
- X default:
- X return -1;
- X
- X }
- X }
- X return val;
- X}
- X
- X
- X
- X
- Xlong getcurtime()
- X{
- X#if USETIME
- X static unsigned long starttime = 0;
- X struct timeval t;
- X struct timezone tz;
- X
- X gettimeofday(&t, &tz);
- X if (starttime == 0)
- X starttime = t.tv_sec;
- X t.tv_sec -= starttime;
- X return (t.tv_sec*1000 + t.tv_usec/1000);
- X#else
- X static unsigned long starttime = 0;
- X if (!starttime) starttime = time(NULL);
- X return (time(NULL) - starttime) * 1000;
- X#endif
- X}
- X
- X
- X
- Xvoid output(msg)
- Xregister char *msg;
- X{
- X unsigned char ch;
- X double savelimit;
- X int i, savemaxlw, maxdp;
- X long alts;
- X long time0, time0a, time1;
- X
- X debughook();
- X if (outputmode) {
- X end_source();
- X while ((ch = *msg++) != 0) {
- X if (ch >= ' ') {
- X putc(ch, outf);
- X } else if (ch == '\n') {
- X putc('\n', outf);
- X outf_lnum++;
- X }
- X }
- X return;
- X }
- X while ((ch = *msg++) != 0) {
- X if (ch == '\n') {
- X if (outbufpos == 0) { /* blank line */
- X thisfutureindent = -1;
- X blanklines++;
- X continue;
- X }
- X if (sectionsize > blanklines)
- X blanklines = sectionsize;
- X sectionsize = 0;
- X if (eatblanks)
- X blanklines = 0;
- X while (blanklines > 0) {
- X blanklines--;
- X end_source();
- X putc('\n', outf);
- X outf_lnum++;
- X }
- X if (thisindent + outbufcount >= linewidth && !dontbreaklines) {
- X numbreaks = 1;
- X bestnumbreaks = 0;
- X bestbadness = BIGBADNESS;
- X breakpos[0] = 0;
- X breakindent[0] = thisindent;
- X breakcount[0] = 0;
- X breakerrorflag = 1;
- X numedits = 0;
- X bestnumedits = 0;
- X savelimit = showbadlimit;
- X numalts = 0;
- X bestnumalts = 0;
- X savemaxlw = maxlinewidth;
- X time0 = time0a = getcurtime();
- X if (regression)
- X srand(17);
- X if (thisindent + outbufcount > linewidth*3/2) {
- X i = 0;
- X maxdepth = 0;
- X readparens(&i, 0);
- X maxdp = maxdepth;
- X for (;;) { /* try some simple fixed methods first... */
- X for (i = 1; i <= 20; i++) {
- X randombreaks = -1;
- X trybreakline(0, 0, thisindent, 0.0, 0, NULL);
- X }
- X randombreaks = -2;
- X trybreakline(0, 0, thisindent, 0.0, 0, NULL);
- X for (i = 0; i <= maxdp+1; i++) {
- X randombreaks = i+1;
- X trybreakline(0, 0, thisindent, 0.0, 0, NULL);
- X }
- X if (bestbadness == BIGBADNESS && maxlinewidth < 9999) {
- X maxlinewidth = 9999; /* no choice but to relax */
- X numalts = 0;
- X } else
- X break;
- X }
- X time0a = getcurtime();
- X }
- X randombreaks = 0;
- X trybreakline(0, 0, thisindent, 0.0, 0, NULL);
- X if (bestbadness == BIGBADNESS && maxlinewidth < 9999) {
- X numalts = 0;
- X maxlinewidth = 9999; /* no choice but to relax this */
- X trybreakline(0, 0, thisindent, 0.0, 0, NULL);
- X }
- X time1 = getcurtime() - time0;
- X alts = numalts;
- X if (testinglinebreaker) {
- X if (savelimit < 0 && testinglinebreaker > 1) {
- X showbadlimit = bestbadness * (-savelimit);
- X numalts = 0;
- X bestnumalts = 0;
- X trybreakline(0, 0, thisindent, 0.0, 0, NULL);
- X }
- X fprintf(outf, "\n#if 1 /* accepted #%ld, badness = %g, tried %ld in %.3f sec */\n", bestnumalts, bestbadness, alts, time1/1000.0);
- X }
- X showbadlimit = savelimit;
- X maxlinewidth = savemaxlw;
- X flush_outbuf(bestnumbreaks, bestbreakpos, bestbreakindent,
- X bestnumedits, besteditpos,
- X besteditold, besteditnew);
- X if (((USETIME && time1 > 1000) || alts >= maxalts) &&
- X !regression) {
- X sprintf(outbuf, "Line breaker spent %.1f",
- X (time1 + time0 - time0a) / 1000.0);
- X if (time0 != time0a)
- X sprintf(outbuf + strlen(outbuf),
- X "+%.2f", (time0a - time0) / 1000.0);
- X sprintf(outbuf + strlen(outbuf),
- X " seconds, %ld tries on line %d [251]", alts, outf_lnum);
- X note(outbuf);
- X } else if (verbose) {
- X fprintf(logf, "%s, %d/%d: Line breaker spent %ld tries\n",
- X infname, inf_lnum, outf_lnum, alts);
- X }
- X if (testinglinebreaker)
- X fprintf(outf, "#endif\n\n");
- X } else {
- X if (testinglinebreaker < 2)
- X flush_outbuf(0, NULL, NULL, 0, NULL, NULL, NULL);
- X }
- X thisfutureindent = -1;
- X outbufpos = 0;
- X outbufcount = 0;
- X } else {
- X if (outbufpos == 0) {
- X if (ch == ' ' && !dontbreaklines) /* eat leading spaces */
- X continue;
- X thisindent = applydelta(outindent, deltaindent);
- X deltaindent = 0;
- X }
- X if (outbufpos == outbufsize) {
- X outbufsize *= 2;
- X outbuf = REALLOC(outbuf, outbufsize, char);
- X }
- X outbuf[outbufpos++] = ch;
- X if (ch >= ' ')
- X outbufcount++;
- X }
- X }
- X}
- X
- X
- X
- Xvoid out_n_spaces(n)
- Xint n;
- X{
- X while (--n >= 0)
- X output(" ");
- X}
- X
- X
- X
- Xvoid out_spaces(spc, over, len, delta)
- Xint spc, over, len, delta;
- X{
- X int n;
- X
- X if (spc == -999)
- X spc = commentindent;
- X if (spc < 0) { /* right-justify */
- X n = (-spc) - cur_column() - len;
- X if (n < minspcthresh)
- X n = minspacing;
- X else
- X over = 1000;
- X } else if (spc >= 2000) { /* tab to multiple */
- X spc -= 2000;
- X n = (spc-1) - ((cur_column()+spc-1) % spc);
- X if (n < minspcthresh)
- X n += spc;
- X } else if (spc >= 1000) { /* absolute column */
- X spc -= 1000;
- X n = spc - cur_column();
- X if (n < minspcthresh)
- X n = minspacing;
- X } else /* relative spacing */
- X n = spc;
- X if (line_start()) {
- X singleindent(n);
- X } else if (len > 0 && over != 1000 && cur_column() + n + len > linewidth) {
- X output("\n");
- X out_spaces(over, 1000, len, 0);
- X singleindent(delta);
- X } else {
- X out_n_spaces(n);
- X }
- X}
- X
- X
- X
- X
- Xvoid testlinebreaker(lev, fn)
- Xint lev;
- Xchar *fn;
- X{
- X char buf[256], *bp, *cp;
- X int first, indent;
- X
- X testinglinebreaker = lev;
- X if (!fn)
- X return;
- X inf = fopen(fn, "r");
- X if (!inf) {
- X perror(fn);
- X exit(1);
- X }
- X sprintf(buf, "%s.br", fn);
- X outf = fopen(buf, "w");
- X if (!outf) {
- X perror(buf);
- X exit(1);
- X }
- X setup_out();
- X outindent = 4;
- X first = 1;
- X while (fgets(buf, 256, inf)) {
- X cp = buf + strlen(buf) - 2;
- X if (cp >= buf) {
- X bp = buf;
- X indent = 0;
- X while (isspace(*bp))
- X if (*bp++ == '\t')
- X indent += 8;
- X else
- X indent++;
- X if (first) {
- X first = 0;
- X outindent = indent;
- X }
- X if (!(*cp == '{' ||
- X *cp == ')' ||
- X *cp == ';') ||
- X (*cp == '/' && cp[-1] == '*')) {
- X cp[1] = '\001'; /* eat the \n */
- X } else {
- X first = 1;
- X }
- X output(bp);
- X }
- X }
- X fclose(outf);
- X fclose(inf);
- X}
- X
- X
- X
- X
- X
- Xvoid outsection(size)
- Xint size;
- X{
- X if (size > sectionsize)
- X sectionsize = size;
- X}
- X
- X
- X
- XStrlist *outcomments(cmt)
- XStrlist *cmt;
- X{
- X char *cp;
- X int saveindent = outindent, savesingle = deltaindent, theindent;
- X int i = 0;
- X
- X if (!cmt)
- X return NULL;
- X if (!commentvisible(cmt)) {
- X setcommentkind(cmt, CMT_DONE);
- X return cmt->next;
- X }
- X if (*cmt->s == '\001') {
- X if (cmtdebug)
- X output(format_sd("[] [%s:%d]",
- X CMT_NAMES[getcommentkind(cmt)],
- X cmt->value & CMT_MASK));
- X for (cp = cmt->s; *cp; cp++) {
- X output("\n");
- X if (cmtdebug && cp[1])
- X output("[]");
- X }
- X setcommentkind(cmt, CMT_DONE);
- X return cmt->next;
- X }
- X dontbreaklines++;
- X if (!strcmp(cmt->s, embedcomment) && *embedcomment && cmt->next &&
- X (*cmt->next->s == '\002' || *cmt->next->s == '\003')) {
- X cmt = cmt->next;
- X embeddedcode = 1;
- X theindent = 0;
- X cp = cmt->next->s + 1;
- X while (*cp++ == ' ')
- X theindent++;
- X } else {
- X moreindent(deltaindent);
- X if (cmt->s[0] == '\004')
- X outindent = 0;
- X theindent = outindent;
- X deltaindent = 0;
- X output("/*");
- X }
- X cp = cmt->s;
- X for (;;) {
- X if (*cp == '\002' || *cp == '\003' || *cp == '\004')
- X cp++;
- X if (embeddedcode) {
- X for (i = 0; *cp == ' ' && i < theindent; i++)
- X cp++;
- X i = *cp;
- X }
- X output(cp);
- X if (cmtdebug)
- X output(format_sd(" [%s:%d] ",
- X CMT_NAMES[getcommentkind(cmt)],
- X cmt->value & CMT_MASK));
- X setcommentkind(cmt, CMT_DONE);
- X cmt = cmt->next;
- X if (!cmt || !commentvisible(cmt))
- X break;
- X cp = cmt->s;
- X if (*cp != '\002' && *cp != '\003')
- X break;
- X output("\n");
- X if (!embeddedcode) {
- X outindent = (*cp == '\002') ? theindent : 0;
- X deltaindent = 0;
- X }
- X }
- X if (embeddedcode) {
- X embeddedcode = 0;
- X if (i) { /* eat final blank line */
- X output("\n");
- X }
- X } else {
- X outindent = saveindent;
- X deltaindent = savesingle;
- X output("*/\n");
- X }
- X dontbreaklines--;
- X return cmt;
- X}
- X
- X
- X
- Xvoid outcomment(cmt)
- XStrlist *cmt;
- X{
- X Strlist *savenext;
- X
- X if (cmt) {
- X savenext = cmt->next;
- X cmt->next = NULL;
- X outcomments(cmt);
- X cmt->next = savenext;
- X }
- X}
- X
- X
- X
- Xvoid outtrailcomment(cmt, serial, indent)
- XStrlist *cmt;
- Xint serial, indent;
- X{
- X int savedelta = deltaindent;
- X
- X#if 0
- X suppressnewline = 1;
- X output("\n");
- X suppressnewline = 0;
- X#endif
- X cmt = findcomment(cmt, CMT_TRAIL, serial);
- X if (commentvisible(cmt)) {
- X out_spaces(indent, commentoverindent, commentlen(cmt), 0);
- X outcomment(cmt);
- X deltaindent = savedelta;
- X } else
- X output("\n");
- X}
- X
- X
- X
- Xvoid flushcomments(cmt, kind, serial)
- XStrlist **cmt;
- Xint kind, serial;
- X{
- X Strlist *cmt2, *cmt3;
- X int saveindent, savesingle, saveeat;
- X
- X if (!cmt)
- X cmt = &curcomments;
- X cmt2 = extractcomment(cmt, kind, serial);
- X saveindent = outindent;
- X savesingle = deltaindent;
- X moreindent(deltaindent);
- X deltaindent = 0;
- X saveeat = eatcomments;
- X if (eatcomments == 2)
- X eatcomments = 0;
- X cmt3 = cmt2;
- X while (cmt3)
- X cmt3 = outcomments(cmt3);
- X eatcomments = saveeat;
- X outindent = saveindent;
- X deltaindent = savesingle;
- X strlist_empty(&cmt2);
- X}
- X
- X
- X
- X
- X
- Xchar *rawCstring(fmt, s, len, special)
- Xchar *fmt;
- Xregister char *s;
- Xint len, special;
- X{
- X char buf[500];
- X register char *cp;
- X register unsigned char ch;
- X
- X cp = buf;
- X while (--len >= 0) {
- X ch = *((unsigned char *) s);
- X s++;
- X if (ch == 0 && (len == 0 || !isdigit(*s))) {
- X *cp++ = '\\';
- X *cp++ = '0';
- X } else if (ch == '\n') {
- X *cp++ = '\\';
- X *cp++ = 'n';
- X } else if (ch == '\b') {
- X *cp++ = '\\';
- X *cp++ = 'b';
- X } else if (ch == '\t') {
- X *cp++ = '\\';
- X *cp++ = 't';
- X } else if (ch == '\f') {
- X *cp++ = '\\';
- X *cp++ = 'f';
- X#if 0
- X } else if (ch == '\r') {
- X *cp++ = '\\';
- X *cp++ = 'r';
- X#endif
- X } else if (ch < ' ' || ch >= 127) {
- X *cp++ = '\\';
- X *cp++ = '0' + (ch>>6);
- X *cp++ = '0' + ((ch>>3) & 7);
- X *cp++ = '0' + (ch & 7);
- X } else if (ch == special) {
- X switch (ch) {
- X case '%':
- X *cp++ = ch;
- X *cp++ = ch;
- X break;
- X }
- X } else {
- X if (ch == '"' || ch == '\\')
- X *cp++ = '\\';
- X *cp++ = ch;
- X }
- X }
- X *cp = 0;
- X return format_s(fmt, buf);
- X}
- X
- X
- Xchar *makeCstring(s, len)
- Xregister char *s;
- Xint len;
- X{
- X return rawCstring("\"%s\"", s, len, 0);
- X}
- X
- X
- X
- Xchar *makeCchar(ich)
- Xint ich;
- X{
- X char buf[500];
- X register char *cp;
- X register unsigned char ch = (ich & 0xff);
- X
- X if (ich < 0 || ich > 255 || (ich == 0 && !nullcharconst))
- X return format_d("%d", ich);
- X cp = buf;
- X if (ch == 0) {
- X *cp++ = '\\';
- X *cp++ = '0';
- X } else if (ch == '\n') {
- X *cp++ = '\\';
- X *cp++ = 'n';
- X } else if (ch == '\b') {
- X *cp++ = '\\';
- X *cp++ = 'b';
- X } else if (ch == '\t') {
- X *cp++ = '\\';
- X *cp++ = 't';
- X } else if (ch == '\f') {
- X *cp++ = '\\';
- X *cp++ = 'f';
- X#if 0
- X } else if (ch == '\r') {
- X *cp++ = '\\';
- X *cp++ = 'r';
- X#endif
- X } else if (ch < ' ' || ch >= 127) {
- X *cp++ = '\\';
- X *cp++ = '0' + (ch>>6);
- X *cp++ = '0' + ((ch>>3) & 7);
- X *cp++ = '0' + (ch & 7);
- X } else {
- X if (ch == '\'' || ch == '\\')
- X *cp++ = '\\';
- X *cp++ = ch;
- X }
- X *cp = 0;
- X return format_s("'%s'", buf);
- X}
- X
- X
- X
- X
- X
- X
- X/* End. */
- X
- X
- END_OF_FILE
- if test 34270 -ne `wc -c <'src/out.c'`; then
- echo shar: \"'src/out.c'\" unpacked with wrong size!
- fi
- # end of 'src/out.c'
- fi
- echo shar: End of archive 12 \(of 32\).
- cp /dev/null ark12isdone
- MISSING=""
- 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
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 32 archives.
- echo "Now see PACKNOTES and the README"
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-