home *** CD-ROM | disk | FTP | other *** search
/ linuxmafia.com 2016 / linuxmafia.com.tar / linuxmafia.com / pub / linux / utilities-general / chef.c < prev    next >
C/C++ Source or Header  |  1999-03-22  |  7KB  |  254 lines

  1. /*
  2.     chef.c
  3.     ------
  4.     This program will convert English from stdin or file to Mock Swedish,
  5.     or Mock Chinese as the Swedes insist, on stdout.
  6.  
  7.     This program is a C conversion of the lex source by John Hagerman.
  8.  
  9.     Arjan Kenter, 16 Dec 1994
  10.                   19 Dec 1994 LaTeX related bugs fixed (forgot to test...)
  11.                   28 Feb 1996 HTML support included and newline bug fixed
  12.                    4 Dec 1996 Added code to skip carriage returns so that the chef web
  13.                               page will add Bork Bork Borks to input from PCs.
  14. */
  15.  
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include <ctype.h>
  20.  
  21. #define INWORD "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'"
  22. #define INTAG  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/"
  23.  
  24. #define BUFLEN 100 /* max number of chars to match + trailing context. */
  25.                    /* chosen safely for future extensions, needs only be 5. */
  26.  
  27. char buf[BUFLEN];
  28. int  head = 0;
  29. int  tail = 0;
  30. int  mtch = 0;
  31. int  eofl = 0;
  32.  
  33. int nextchar (void)
  34.   {
  35.     int c;
  36.     if (mtch == head)
  37.       {
  38.         if (eofl || (c = getchar ()) == EOF)
  39.           {
  40.             eofl = 1;
  41.             return EOF;
  42.           }
  43.         buf[head++] = c;
  44.         if (head == BUFLEN) head = 0;
  45.         if (head == tail)
  46.           {
  47.             fprintf (stderr, "Chef internal error: buffer overflowed.\n");
  48.             exit (EXIT_FAILURE);
  49.           }
  50.       }
  51.     c = buf[mtch++];
  52.     if (mtch == BUFLEN) mtch = 0;
  53.     if (c == '\r') c = nextchar (); /* Skip carriage returns. I hope this simplicity suffices. */
  54.     return c;
  55.   }
  56.  
  57. int back (int c)
  58.   {
  59.     if (c != EOF && --mtch < 0) mtch = BUFLEN-1;
  60.     return c;
  61.   }
  62.  
  63. int match (char *str)
  64.   {
  65.     int c;
  66.     unsigned char *s = (unsigned char *) str;
  67.  
  68.     mtch = tail;
  69.     while (*s && *s == nextchar ()) s++;
  70.     if (*s) mtch = tail;
  71.     return !*s;
  72.   }
  73.  
  74. int eof (void)
  75.   {
  76.     back (nextchar ());
  77.     return eofl && head == tail;
  78.   }
  79.  
  80. int eow (void)
  81.   {
  82.     return strchr (INWORD, back (nextchar ())) == NULL;
  83.   }
  84.  
  85. int eol (void)
  86.   {
  87.     return back (nextchar ()) == '\n';
  88.   }
  89.  
  90. int eotex (void)
  91.   {
  92.     int c = back (nextchar ());
  93.     return c == ' ' || c == '\n';
  94.   }
  95.  
  96. void accept (void)
  97.   {
  98.     tail = mtch;
  99.   }
  100.  
  101. void echo (void)
  102.   {
  103.     int c;
  104.     mtch = tail;
  105.     if ((c = nextchar ()) != EOF)
  106.       {
  107.         accept ();
  108.         putchar (c);
  109.       }
  110.   }
  111.  
  112. void echo_tag (void)
  113.   {
  114.     /* Echo everything upto and including next '>', where it */
  115.     /* appears outside "" delimited strings. */
  116.  
  117.     int c;
  118.     int instr = 0;
  119.     mtch = tail;
  120.     while ((c = nextchar ()) != EOF && (c != '>' || instr))
  121.       {
  122.         accept (); putchar (c);
  123.         if (c == '"') instr = !instr;
  124.       }
  125.   }
  126.  
  127. void echo_esc (void)
  128.   {
  129.     /* Echo everything upto next non-alphanumeric character. */
  130.  
  131.     int c;
  132.     echo (); /* Echo '&'. */
  133.     if ((c = nextchar ()) != EOF && (isalnum (c) || c == '#'))
  134.       {
  135.         accept ();
  136.         putchar (c);
  137.       }
  138.     while ((c = nextchar ()) != EOF && isalnum (c))
  139.       {
  140.         accept ();
  141.         putchar (c);
  142.       }
  143.   }
  144.  
  145. void chef (void)
  146.   {
  147.     int c, icount = 0;
  148.     int beginword, inword = 0;
  149.     int bork = 1;
  150.     while (!eof ())
  151.       {
  152.         /* Determine if we are at beginning of word, within word or
  153.            outside word.
  154.         */
  155.         mtch = tail;
  156.         beginword = strchr (INWORD, c = nextchar ()) && !inword;
  157.  
  158.         if (match ("\\")) /* TeX command encountered. */
  159.           {
  160.             do {echo ();} while (!eof () && !eotex ());
  161.             inword = 0;
  162.             continue;
  163.           }
  164.  
  165.         if (match ("<") && strchr (INTAG, nextchar ())) /* HTML tag encountered. */
  166.           {
  167.             echo_tag ();
  168.             inword = 0;
  169.             continue;
  170.           }
  171.  
  172.         if (match ("&") && (isalnum (c = nextchar ()) || c == '#')) /* HTML escape encountered. */
  173.           {
  174.             echo_esc ();
  175.             inword = 0;
  176.             continue;
  177.           }
  178.  
  179.         /* Suppress "Bork bork bork!" after a line with '%' in it to
  180.            avoid problems with comments in LaTeX files.
  181.         */
  182.  
  183.         if (match ("%")) {echo (); bork = 0; continue;}
  184.         if (eol ())      {echo (); bork = 1; inword = 0; continue;}
  185.  
  186.         if (beginword)
  187.           {
  188.             icount = 0;
  189.             if (match ("e"))    {accept (); inword = 1; printf ("i"); continue;}
  190.             if (match ("E"))    {accept (); inword = 1; printf ("I"); continue;}
  191.             if (match ("o"))    {accept (); inword = 1; printf ("oo"); continue;}
  192.             if (match ("O"))    {accept (); inword = 1; printf ("Oo"); continue;}
  193.             if (match ("bork")) {accept (); inword = 1; printf ("bork"); continue;}
  194.             if (match ("Bork")) {accept (); inword = 1; printf ("Bork"); continue;}
  195.           }
  196.  
  197.         if (inword)
  198.           {
  199.             if (match ("ew"))   {accept (); inword = 1; printf ("oo"); continue;}
  200.             if (match ("f"))    {accept (); inword = 1; printf ("ff"); continue;}
  201.             if (match ("ir"))   {accept (); inword = 1; printf ("ur"); continue;}
  202.             if (match ("ow"))   {accept (); inword = 1; printf ("oo"); continue;}
  203.             if (match ("o"))    {accept (); inword = 1; printf ("u");  continue;}
  204.             if (match ("u"))    {accept (); inword = 1; printf ("oo"); continue;}
  205.             if (match ("U"))    {accept (); inword = 1; printf ("Oo"); continue;}
  206.             if (match ("tion")) {accept (); inword = 1; printf ("shun"); continue;}
  207.             if (match ("i"))    {accept (); inword = 1; printf (icount++ ? "i" : "ee"); continue;}
  208.             if (match ("e")  && eow ()) {accept (); inword = 0; printf ("e-a"); continue;}
  209.             if (match ("en") && eow ()) {accept (); inword = 0; printf ("ee"); continue;}
  210.             if (match ("th") && eow ()) {accept (); inword = 0; printf ("t"); continue;}
  211.           }
  212.  
  213.         if (match ("an"))  {accept (); inword = 1; printf ("un");  continue;}
  214.         if (match ("An"))  {accept (); inword = 1; printf ("Un");  continue;}
  215.         if (match ("au"))  {accept (); inword = 1; printf ("oo");  continue;}
  216.         if (match ("Au"))  {accept (); inword = 1; printf ("Oo");  continue;}
  217.         if (match ("the")) {accept (); inword = 1; printf ("zee"); continue;}
  218.         if (match ("The")) {accept (); inword = 1; printf ("Zee"); continue;}
  219.         if (match ("v"))   {accept (); inword = 1; printf ("f");   continue;}
  220.         if (match ("V"))   {accept (); inword = 1; printf ("F");   continue;}
  221.         if (match ("w"))   {accept (); inword = 1; printf ("v");   continue;}
  222.         if (match ("W"))   {accept (); inword = 1; printf ("V");   continue;}
  223.         if (match ("a") && !eow ()) {accept (); inword = 1; printf ("e"); continue;}
  224.         if (match ("A") && !eow ()) {accept (); inword = 1; printf ("E"); continue;}
  225.         if (match (".") &&  eol () && bork)
  226.           {
  227.             accept (); inword = 0; printf (".\nBork Bork Bork!");
  228.             continue;
  229.           }
  230.  
  231.         inword = strchr (INWORD, c) != NULL;
  232.         echo ();
  233.       }
  234.   }
  235.  
  236. int main (int argc, char **argv)
  237.   {
  238.     if (argc > 2)
  239.       {
  240.         fprintf (stderr, "Usage: chef [file]\n");
  241.         exit (1);
  242.       }
  243.     if (argc == 2)
  244.       {
  245.         if (freopen (argv[1], "r", stdin) == NULL)
  246.           {
  247.             fprintf (stderr, "Can't open '%s'.\n", argv[1]);
  248.             exit (1);
  249.           }
  250.       }
  251.     chef ();
  252.     return 0;
  253.   }
  254.