home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 2 / FFMCD02.bin / new / dev / misc / p2c / src / out.c < prev    next >
C/C++ Source or Header  |  1993-12-21  |  36KB  |  1,597 lines

  1. /* "p2c", a Pascal to C translator.
  2.    Copyright (C) 1989, 1990, 1991 Free Software Foundation.
  3.    Author's address: daveg@csvax.caltech.edu; 256-80 Caltech/Pasadena CA 91125.
  4.  
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation (any version).    
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. GNU General Public License for more details.
  13.  
  14. You should have received a copy of the GNU General Public License
  15. along with this program; see the file COPYING.  If not, write to
  16. the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
  17.  
  18.  
  19.  
  20.  
  21. /* This needs to go before trans.h (and thus p2c.proto) is read */
  22.  
  23. typedef struct S_paren {
  24.     struct S_paren *next;
  25.     int pos, indent, qmindent, flags;
  26. } Paren;
  27.  
  28.  
  29.  
  30. #define PROTO_OUT_C
  31. #include "trans.h"
  32.  
  33.  
  34. #ifndef USETIME
  35. # if defined(BSD) || defined(hpux)
  36. #  define USETIME 1
  37. # else
  38. #  define USETIME 0
  39. # endif
  40. #endif
  41.  
  42. #if USETIME
  43. # include <sys/time.h>
  44. #else
  45. # include <time.h>
  46. #endif
  47.  
  48.  
  49.  
  50.  
  51. /* Output control characters:
  52.  
  53.    \001  \B  Possible break point
  54.    \002  \X  Break point in parentheses
  55.    \003  \(  Invisible open paren
  56.    \004  \)  Invisible close paren
  57.    \005  \T  Set left margin
  58.    \006  \F  Forced break point
  59.    \007  \A  Preceding paren requires all-or-none breaking
  60.    \010  \[  Invisible open paren, becomes visible if not all on one line
  61.    \011  \S  Break point after last "special argument" of a function
  62.    \012  \n  (newline)
  63.    \013  \E  Preceding break has extra penalty
  64.    \014  \f  (form-feed)
  65.    \015  \H  Hang-indent the preceding operator
  66.    \016  \.  (unused)
  67.    \017  \C  Break point for last : of a ?: construct
  68.  
  69. */
  70.  
  71. char spchars[] = ".BX()TFA[SnEfH.C................";
  72.  
  73.  
  74.  
  75. Static int testinglinebreaker = 0;
  76.  
  77. Static int deltaindent, thisindent, thisfutureindent;
  78. Static int sectionsize, blanklines, codesectsize, hdrsectsize;
  79. Static int codelnum, hdrlnum;
  80.  
  81. #define MAXBREAKS  200
  82. Static int numbreaks, bestnumbreaks;
  83. Static double bestbadness;
  84. Static int breakpos[MAXBREAKS], breakindent[MAXBREAKS];
  85. Static int breakcount[MAXBREAKS], breakparen[MAXBREAKS];
  86. Static int bestbreakpos[MAXBREAKS], bestbreakindent[MAXBREAKS];
  87. Static int breakerrorflag;
  88.  
  89. #define MAXEDITS  200
  90. Static int numedits, bestnumedits;
  91. Static int editpos[MAXEDITS], besteditpos[MAXEDITS];
  92. Static char editold[MAXEDITS], editnew[MAXEDITS];
  93. Static char besteditold[MAXEDITS], besteditnew[MAXEDITS];
  94.  
  95. Static Paren *parenlist;
  96.  
  97. Static long numalts, bestnumalts;
  98. Static int randombreaks;
  99.  
  100. Static char *outbuf;
  101. Static int outbufpos, outbufcount, outbufsize;
  102. Static int suppressnewline, lastlinelength;
  103. Static int eatblanks;
  104. Static int embeddedcode;
  105. Static int showingsourcecode = 0;
  106.  
  107. #define BIGBADNESS  (1e20)
  108.  
  109.  
  110.  
  111. void setup_out()
  112. {
  113.     end_source();
  114.     if (!nobanner)
  115.     fprintf(outf, "/* From input file \"%s\" */\n", infname);
  116.     outf_lnum++;
  117.     hdrlnum = 1;
  118.     outindent = 0;
  119.     deltaindent = 0;
  120.     thisindent = 0;
  121.     thisfutureindent = -1;
  122.     sectionsize = 2;
  123.     blanklines = 0;
  124.     dontbreaklines = 0;
  125.     embeddedcode = 0;
  126.     outputmode = 0;
  127.     suppressnewline = 0;
  128.     eatblanks = 0;
  129.     outbufsize = 1000;
  130.     outbuf = ALLOC(outbufsize, char, misc);
  131.     outbufpos = 0;
  132.     outbufcount = 0;
  133.     srand(17);
  134. }
  135.  
  136.  
  137.  
  138. void select_outfile(fp)
  139. FILE *fp;
  140. {
  141.     if (outf == codef) {
  142.         codesectsize = sectionsize;
  143.     codelnum = outf_lnum;
  144.     } else {
  145.         hdrsectsize = sectionsize;
  146.     hdrlnum = outf_lnum;
  147.     }
  148.     outf = fp;
  149.     if (outf == codef) {
  150.         sectionsize = codesectsize;
  151.     outf_lnum = codelnum;
  152.     } else {
  153.         sectionsize = hdrsectsize;
  154.     outf_lnum = hdrlnum;
  155.     }
  156. }
  157.  
  158.  
  159.  
  160. void start_source()
  161. {
  162.     if (!showingsourcecode) {
  163.     fprintf(outf, "\n#ifdef Pascal\n");
  164.     showingsourcecode = 1;
  165.     }
  166. }
  167.  
  168. void end_source()
  169. {
  170.     if (showingsourcecode) {
  171.     fprintf(outf, "#endif /*Pascal*/\n\n");
  172.     showingsourcecode = 0;
  173.     }
  174. }
  175.  
  176.  
  177.  
  178. int line_start()
  179. {
  180.     return (outbufcount == 0);
  181. }
  182.  
  183.  
  184. int cur_column()
  185. {
  186.     if (outbufpos == 0)
  187.     return outindent;
  188.     else
  189.     return thisindent + outbufcount;
  190. }
  191.  
  192.  
  193.  
  194. int lookback(n)
  195. int n;
  196. {
  197.     if (n <= 0 || n > outbufpos)
  198.     return 0;
  199.     else
  200.     return outbuf[outbufpos - n];
  201. }
  202.  
  203.  
  204. int lookback_prn(n)
  205. int n;
  206. {
  207.     for (;;) {
  208.     if (n <= 0 || n > outbufpos)
  209.         return 0;
  210.     else if (outbuf[outbufpos - n] >= ' ')
  211.         return outbuf[outbufpos - n];
  212.     else
  213.         n++;
  214.     }
  215. }
  216.  
  217.  
  218.  
  219. /* Combine two indentation adjustments */
  220. int adddeltas(d1, d2)
  221. int d1, d2;
  222. {
  223.     if (d2 >= 1000)
  224.     return d2;
  225.     else
  226.     return d1 + d2;
  227. }
  228.  
  229.  
  230. /* Apply an indentation delta */
  231. int applydelta(i, d)
  232. int i, d;
  233. {
  234.     if (d >= 1000)
  235.     return d - 1000;
  236.     else
  237.     return i + d;
  238. }
  239.  
  240.  
  241. /* Adjust the current indentation by delta */
  242. void moreindent(delta)
  243. int delta;
  244. {
  245.     outindent = applydelta(outindent, delta);
  246. }
  247.  
  248.  
  249. /* Adjust indentation for just this line */
  250. void singleindent(delta)
  251. int delta;
  252. {
  253.     deltaindent = adddeltas(deltaindent, delta);
  254. }
  255.  
  256.  
  257. /* Predict indentation for next line */
  258. void futureindent(num)
  259. int num;
  260. {
  261.     thisfutureindent = applydelta(applydelta(outindent, deltaindent), num);
  262. }
  263.  
  264.  
  265. int parsedelta(cp, def)
  266. char *cp;
  267. int def;
  268. {
  269.     if (!cp || !*cp)
  270.     return def;
  271.     if ((*cp == '+' || *cp == '-') && isdigit(cp[1]))
  272.     return atoi(cp);
  273.     if (*cp == '*' && isdigit(cp[1]))
  274.     return 2000 + atoi(cp+1);
  275.     else
  276.     return 1000 + atoi(cp);
  277. }
  278.  
  279.  
  280.  
  281.  
  282. Static void leading_tab(col)
  283. int col;
  284. {
  285.     if (col > maxlinewidth)
  286.     return;    /* something wrong happened! */
  287.     if (phystabsize > 0) {
  288.     while (col >= phystabsize) {
  289.         putc('\t', outf);
  290.         col -= phystabsize;
  291.     }
  292.     }
  293.     while (col > 0) {
  294.     putc(' ', outf);
  295.     col--;
  296.     }
  297. }
  298.  
  299.  
  300.  
  301. void eatblanklines()
  302. {
  303.     eatblanks = 1;
  304. }
  305.  
  306.  
  307.  
  308. Static void flush_outbuf(numbreaks, breakpos, breakindent,
  309.              numedits, editpos, editold, editnew)
  310. int numbreaks, *breakpos, *breakindent, numedits, *editpos;
  311. char *editold, *editnew;
  312. {
  313.     unsigned char ch, ch2;
  314.     char *cp;
  315.     int i, j, linelen = 0, spaces, hashline;
  316.     int editsaves[MAXEDITS];
  317.  
  318.     end_source();
  319.     if (outbufcount > 0) {
  320.     for (i = 0; i < numedits; i++) {
  321.         editsaves[i] = outbuf[editpos[i]];
  322.         outbuf[editpos[i]] = editnew[i];
  323.     }
  324.     leading_tab(thisindent);
  325.     cp = outbuf;
  326.     hashline = (*cp == '#');    /* a preprocessor directive */
  327.     spaces = 0;
  328.     j = 1;
  329.     for (i = 0; i < outbufpos; ) {
  330.         if (j < numbreaks && i == breakpos[j]) {
  331.         if (hashline)
  332.             fprintf(outf, " \\");   /* trailing backslash required */
  333.         putc('\n', outf);
  334.         outf_lnum++;
  335.         leading_tab(breakindent[j]);
  336.         linelen = breakindent[j];
  337.         j++;
  338.         while (i < outbufpos && *cp == ' ')
  339.             i++, cp++;   /* eat leading spaces */
  340.         spaces = 0;      /* eat trailing spaces */
  341.         } else {
  342.         ch = *cp++;
  343.         if (ch == ' ') {
  344.             spaces++;
  345.         } else if (ch > ' ') {
  346.             linelen += spaces;
  347.             while (spaces > 0)
  348.             putc(' ', outf), spaces--;
  349.             linelen++;
  350.             if (ch == '\\' && embeddedcode) {
  351.             if (*cp == '[') {
  352.                 putc('{', outf);
  353.                 cp++, i++;
  354.             } else if (*cp == ']') {
  355.                 putc('}', outf);
  356.                 cp++, i++;
  357.             } else
  358.                 putc(ch, outf);
  359.             } else
  360.             putc(ch, outf);
  361.         } else if (testinglinebreaker >= 3) {
  362.             linelen += spaces;
  363.             while (spaces > 0)
  364.             putc(' ', outf), spaces--;
  365.             linelen++;
  366.             putc('\\', outf);
  367.             ch2 = spchars[ch];
  368.             if (ch2 != '.')
  369.             putc(ch2, outf);
  370.             else {
  371.             putc('0' + ((ch >> 6) & 7), outf);
  372.             putc('0' + ((ch >> 3) & 7), outf);
  373.             putc('0' + (ch & 7), outf);
  374.             }
  375.         }
  376.         i++;
  377.         }
  378.     }
  379.     for (i = 0; i < numedits; i++)
  380.         outbuf[editpos[i]] = editsaves[i];
  381.     eatblanks = 0;
  382.     } else if (eatblanks) {
  383.     return;
  384.     }
  385.     if (suppressnewline) {
  386.     lastlinelength = linelen;
  387.     } else
  388.     putc('\n', outf);
  389.     outf_lnum++;
  390. }
  391.  
  392.  
  393.  
  394. #define ISQUOTE(ch)  ((ch)=='"' || (ch)=='\'')
  395. #define ISOPENP(ch)  ((ch)=='(' || (ch)=='[' || (ch)=='\003' || (ch)=='\010')
  396. #define ISCLOSEP(ch) ((ch)==')' || (ch)==']' || (ch)=='\004')
  397. #define ISBREAK(ch)  ((ch)=='\001' || (ch)=='\002' || (ch)=='\006' || (ch)=='\011' || (ch)=='\017')
  398.  
  399. Static int readquotes(posp, err)
  400. int *posp, err;
  401. {
  402.     int pos;
  403.     char quote;
  404.  
  405.