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