Back to index

tetex-bin  3.0
fixwrites.c
Go to the documentation of this file.
00001 /* fixwrites -- convert Pascal write/writeln's into fprintf's or putc's.
00002    Originally by Tim Morgan, October 10, 1987.  */
00003 
00004 #include "config.h"
00005 #include <kpathsea/c-pathmx.h>
00006 
00007 int argc;
00008 char **gargv;
00009 
00010 char buf[BUFSIZ], filename[PATH_MAX], args[100];
00011 char *file, *argp, *as, *cmd;
00012 
00013 int tex = false;
00014 
00015 /* Replace the last (should be only) newline in S with a null.  */
00016 
00017 static void
00018 remove_newline P1C(string, s)
00019 {
00020   char *temp = strrchr (s, '\n');
00021   if (temp == NULL)
00022     {
00023       fprintf (stderr, "Lost newline somehow.\n");
00024       /* This is so the convert script can delete the output file on error.  */
00025       puts ("@error@");
00026       exit (1);
00027     }
00028 
00029   *temp = 0;
00030 }
00031 
00032 
00033 static char *
00034 insert_long P1C(string, cp)
00035 {
00036   char tbuf[BUFSIZ];
00037   register int i;
00038 
00039   for (i = 0; &buf[i] < cp; ++i)
00040     tbuf[i] = buf[i];
00041   strcpy (&tbuf[i], "(long)");
00042   strcpy (&tbuf[i + 6], cp);
00043   strcpy (buf, tbuf);
00044   return cp + 6;
00045 }
00046 
00047 
00048 static void
00049 join P1C(string, cp)
00050 {
00051   char temp[BUFSIZ], *tp;
00052 
00053   if (!fgets (temp, BUFSIZ, stdin))
00054     return;
00055   remove_newline (temp);
00056 
00057   *cp++ = ' ';
00058   for (tp = temp; *tp == ' '; ++tp)
00059     ;
00060 
00061   strcpy (cp, tp);
00062 }
00063 
00064 
00065 static void
00066 do_blanks P1C(int, indent)
00067 {
00068   register int i;
00069 
00070   for (i = 0; i < indent / 8; i++)
00071     putchar ('\t');
00072   indent %= 8;
00073   for (i = 0; i < indent; i++)
00074     putchar (' ');
00075 }
00076 
00077 
00078 /* Return true if we have a whole write/writeln statement.  We determine
00079    this by matching parens, ignoring those within strings.  */
00080 static int
00081 whole P1C(string, cp)
00082 {
00083   register int depth = 0;
00084 
00085   while (cp && *cp)
00086     {
00087       switch (*cp)
00088        {
00089        case '(':
00090          ++depth;
00091          break;
00092        case ')':
00093          --depth;
00094          break;
00095        case '"':
00096          for (++cp; cp && *cp && *cp != '"'; ++cp)
00097            if (*cp == '\\')
00098              ++cp;
00099          break;
00100        case '\'':
00101          ++cp;
00102          if (*cp == '\\') ++cp;
00103          ++cp;
00104          break;
00105        }
00106       ++cp;
00107     }
00108   return depth <= 0;
00109 }
00110 
00111 
00112 /* Skips to the next , or ), skipping over balanced paren pairs.  */
00113 
00114 static char *
00115 skip_balanced P1C(string, cp)
00116 {
00117   register int depth = 0;
00118 
00119   while (depth > 0 || (*cp != ',' && *cp != ')'))
00120     {
00121       switch (*cp)
00122        {
00123        case '(':
00124          ++depth;
00125          break;
00126        case ')':
00127          --depth;
00128          break;
00129        }
00130       ++cp;
00131     }
00132   return cp;
00133 }
00134 
00135 
00136 /* Return true if c appears, except inside a quoted string */
00137 
00138 static int
00139 bare P2C(string, cp,  char, c)
00140 {
00141   for (; *cp && *cp != c; ++cp)
00142     {
00143       if (*cp == '"')
00144        {
00145          ++cp;                     /* skip over initial quotation mark */
00146          while (*cp && *cp != '"')
00147            {                /* skip to closing double quote */
00148              if (*cp == '\\')
00149               ++cp;
00150              ++cp;
00151            }
00152        }
00153       else if (*cp == '\'')
00154        {
00155          ++cp;                     /* skip to contained char */
00156          if (*cp == '\'')
00157            ++cp;            /* if backslashed, it's double */
00158          ++cp;                     /* skip to closing single-quote mark */
00159        }
00160     }
00161   return *cp;
00162 }
00163 
00164 
00165 /* xchr[...] is supposed to be replaced by Xchr(...)  when characters
00166    take more than a single octet each, as is the case in Omega.  Now
00167    there are several occurrences of xchr[...[...]...], which are
00168    translated into Xchr(...[...)...], and the compiler dies on syntax
00169    errors.  Ensures that it is the matching bracket that is replaced,
00170    not the first one.  */
00171 
00172 char *
00173 advance_cp P2C(char *, cp, int, lefts)
00174 {
00175   char *cp1;
00176   char *cp2;
00177 
00178   cp1 = strchr (cp + 1, ']');
00179   cp2 = strchr (cp + 1, '[');
00180   if (cp2 && cp2 < cp1)
00181     return advance_cp (cp2, lefts + 1);
00182   if (lefts == 1)
00183     return cp1;
00184   return advance_cp (cp1, lefts - 1);
00185 }
00186 
00187 int
00188 main P2C(int, argc,  string *, argv)
00189 {
00190   register char *cp;
00191   int blanks_done, indent, i;
00192   char *program_name = "";
00193 
00194   for (i = 1; i < argc; i++)
00195     {
00196       if (STREQ(argv[i],"-t"))
00197        tex = true;
00198       else
00199        program_name = argv[i];
00200     }
00201 
00202   while (fgets (buf, BUFSIZ, stdin))
00203     {
00204       remove_newline (buf);
00205       blanks_done = false;
00206 
00207       for (cp = buf; *cp; ++cp) ;
00208 
00209       while (cp != buf && *--cp == ' ') ;
00210 
00211       while (*cp == '.')
00212        {
00213          join (cp + 1);
00214          while (*cp)
00215            ++cp;
00216          while (*--cp == ' ') ;
00217        }
00218 
00219       for (cp = buf, indent = 0; *cp == ' ' || *cp == '\t'; ++cp)
00220        {
00221          if (*cp == ' ')
00222            indent++;
00223          else
00224            indent += 8;
00225        }
00226 
00227       if (!*cp)
00228        {                    /* All blanks, possibly with "{" */
00229          puts (buf);
00230          continue;
00231        }
00232       if (*cp == '{')
00233 
00234         {
00235          do_blanks (indent);
00236          putchar ('{');
00237          ++cp;
00238          while (*cp == ' ' || *cp == '\t')
00239            ++cp;
00240          blanks_done = true;
00241          if (!*cp)
00242            {
00243              putchar ('\n');
00244              continue;
00245            }
00246        }
00247 
00248       if (!blanks_done)
00249        do_blanks (indent);
00250 
00251       if (strncmp (cp, "read ( input", 12) == 0)
00252        {
00253          char variable_name[20];
00254          if (sscanf (cp, "read ( input , %s )", variable_name) != 1)
00255             {
00256              fprintf (stderr, "sscanf failed\n");
00257               exit (1);
00258             }
00259          printf ("%s = getint();\n", variable_name);
00260          continue;
00261        }
00262 
00263       if (strncmp (cp, "lab", 3) == 0 && strchr (cp, ':'))
00264        {
00265          do
00266            {
00267              putchar (*cp);
00268            }
00269           while (*cp++ != ':');
00270 
00271           while (*cp == ' ')
00272            ++cp;
00273          putchar (' ');
00274        }
00275 
00276       if (strncmp (cp, "else write", 10) == 0)
00277        {
00278          puts ("else");
00279          do_blanks (indent);
00280          cp += 5;
00281          while (*cp == ' ')
00282            ++cp;
00283        }
00284 
00285       if (bare (cp, '{'))
00286        {
00287          while (*cp != '{')
00288            {
00289              putchar (*cp);
00290              ++cp;
00291            }
00292          ++cp;
00293          puts ("{");
00294          indent += 4;
00295          do_blanks (indent);
00296          while (*cp == ' ')
00297            ++cp;
00298        }
00299 
00300       if (strncmp (cp, "write (", 7) && strncmp (cp, "writeln (", 9))
00301        {
00302          /* if not a write/writeln, just copy it to stdout and continue */
00303          puts (cp);
00304          continue;
00305        }
00306       cmd = cp;
00307       while (!whole (buf))  /* make sure we have whole stmt */
00308        {
00309          fgets (&buf[strlen (buf)], BUFSIZ - strlen (buf), stdin);
00310          remove_newline (buf);
00311        }
00312 
00313       while (*cp != '(')
00314        ++cp;
00315       ++cp;
00316       while (*(cp + 1) == ' ')
00317        ++cp;
00318 
00319       /* Some writes start with a variable, instead of a file. */
00320       if (*(cp + 1) == '"' || *(cp + 1) == '\''
00321           || strncmp (cp + 1, "buffer", 6) == 0
00322           || strncmp (cp + 1, "xchr", 4) == 0
00323           || strncmp (cp + 1, "k ,", 3) == 0
00324           || strncmp (cp + 1, "s ,", 3) == 0
00325           || strncmp (cp + 1, "dig", 3) == 0
00326           || strncmp (cp + 1, "HEX", 3) == 0
00327           || strncmp (cp + 1, "versionstring", 13) == 0
00328           || strncmp (cp + 1, "kpathseaversionstring", 21) == 0
00329          )
00330        strcpy (filename, "stdout");
00331       else
00332        {
00333          file = filename;
00334          while (*cp != ',' && *cp != ')')
00335            *file++ = *cp++;
00336          *file = '\0';
00337        }
00338       if (*cp == ')')
00339        {
00340          printf ("putc ('\\n', %s);\n", filename);
00341          continue;
00342        }
00343       argp = ++cp;
00344       as = args;
00345       while (*cp == ' ')
00346        ++cp;
00347       while (*cp != ')')
00348        {
00349          if (*cp == '\'' || strncmp (cp, "xchr", 4) == 0
00350               || (strncmp (cp ,"HEX", 3) == 0
00351                   && (STREQ (program_name, "ofm2opl")
00352                       || STREQ (program_name, "opl2ofm")
00353                       || STREQ (program_name, "ovp2ovf")
00354                       || STREQ (program_name, "ovf2ovp")))
00355              || strncmp (cp, "ASCII04", 7) == 0
00356              || strncmp (cp, "ASCII1", 6) == 0
00357              || strncmp (cp, "ASCIIall", 8) == 0              
00358              || strncmp (cp, "months", 6) == 0
00359              || strncmp (cp, "nameoffile", 10) == 0
00360              || (strncmp (cp, "buffer", 6) == 0
00361                   && (STREQ (program_name, "vptovf")
00362                       || STREQ (program_name, "pltotf")
00363                       || STREQ (program_name, "ovp2ovf")
00364                       || STREQ (program_name, "ofm2opl")))
00365               || (((strncmp (cp, "buf", 3) == 0
00366                   || strncmp (cp, "xdig", 4) == 0
00367                   || strncmp (cp, "xext", 4) == 0
00368                   || strncmp (cp, "xhyf", 4) == 0)
00369                   && STREQ (program_name, "patgen")))
00370              )
00371            {
00372              *as++ = '%';
00373              *as++ = 'c';
00374              if (tex && strncmp (cp, "xchr", 4) == 0)
00375               {
00376                 *cp = 'X';
00377                 cp = strchr (cp, '[');
00378                 *cp = '(';
00379                 cp = advance_cp(cp,1);
00380                 *cp++ = ')';
00381               }
00382              else if (*cp == '\'')
00383               cp += 2;
00384            }
00385           
00386          else if (*cp == '"')
00387            {
00388              *as++ = '%';
00389              *as++ = 's';
00390              while (*++cp != '"')  /* skip to end of string */
00391               if (*cp == '\\')
00392                 ++cp;              /* allow \" in string */
00393            }
00394 
00395           /* More kludges -- recognize some things as strings and use %s:
00396              - versionstring
00397              - poolname
00398              - formatengine */
00399           else if (strncmp (cp, "versionstring", 13) == 0
00400                    || strncmp (cp, "poolname", 8) == 0
00401                    || strncmp (cp, "formatengine", 12) == 0)
00402             {
00403               *as++ = '%';
00404               *as++ = 's';
00405             }
00406 
00407          /* And yet another kludge, to handle stringcast (<whatever>) */
00408           else if (strncmp (cp, "stringcast", 10) == 0)
00409            {
00410              *as++ = '%';
00411              *as++ = 's';
00412              cp = skip_balanced (cp);  /* Skip cast expression */
00413            }
00414 
00415           else
00416            {
00417              *as++ = '%';
00418              *as++ = 'l';
00419              *as++ = 'd';
00420              cp = insert_long (cp);
00421              cp = skip_balanced (cp);     /* It's a numeric expression */
00422            }
00423          while (*cp != ',' && *cp != ')')
00424            ++cp;
00425          while (*cp == ',' || *cp == ' ')
00426            ++cp;
00427        }
00428 
00429       if (strncmp (cmd, "writeln", 7) == 0)
00430        {
00431          *as++ = '\\';
00432          *as++ = 'n';
00433        }
00434 
00435       *as = '\0';
00436       if (strcmp (args, "%c") == 0)
00437        {
00438          for (as = argp; *as; ++as) ;
00439          while (*--as != ')') ;
00440          *as = '\0';
00441          printf ("putc (%s, %s);\n", argp, filename);
00442        }
00443       else if (STREQ (args, "%s"))
00444         printf ("Fputs (%s, %s\n", filename, argp);
00445       else
00446         printf ("fprintf (%s, \"%s\", %s\n", filename, args, argp);
00447     }
00448 
00449   return EXIT_SUCCESS;
00450 }