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 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 '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 X#else X# include 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