v21i057: Pascal to C translator, Part12/32

Rich Salz rsalz at uunet.uu.net
Wed Mar 28 08:16:23 AEST 1990


Submitted-by: Dave Gillespie <daveg at 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 at 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 at 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
-- 
Please send comp.sources.unix-related mail to rsalz at uunet.uu.net.
Use a domain-based address or give alternate paths, or you may lose out.



More information about the Comp.sources.unix mailing list