home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 329_01 / define.c < prev    next >
C/C++ Source or Header  |  1989-10-17  |  8KB  |  379 lines

  1. /*  >  DEFINE.C
  2.  *
  3.  *  Define -- Construct C definitions from
  4.  *  descriptions given in plain English
  5.  *  (C)  October 17  1989  by Asaf Arkin
  6.  *  All rights reserved
  7.  */
  8.  
  9.  
  10.  
  11. /*  Include files:
  12.  */
  13.  
  14. #include  <ctype.h>
  15. #include  <stdio.h>
  16. #include  <stdlib.h>
  17. #include  <string.h>
  18.  
  19.  
  20. /*  Macro constants:- True/False; Token types.
  21.  */
  22.  
  23. #define  FALSE  0
  24. #define  TRUE   1
  25.  
  26. #define  POINTER   010
  27. #define  FUNCTION  020
  28. #define  FUNCACPT  021
  29. #define  ARRAY     030
  30. #define  ARRAYSZ   031
  31. #define  OTHER     000
  32.  
  33.  
  34. /*  Static variable definitions:
  35.  *    Token is the last token read by GetToken().
  36.  *    DefinBase points to the first char of the definition, DefinLen is the
  37.  *    definition's length, and InsertAt is the offset to DefinBase at which
  38.  *    to Insert() new characters.
  39.  */
  40.  
  41. static char  Token;
  42. static char  *DefinBase;
  43. static int    DefinLen,  InsertAt;
  44.  
  45.  
  46. /*  Structure containing illegal combinations: array of func, func returning
  47.  *  array, and func returning func. Define will report, if you attempt any of
  48.  *  these in a definition.
  49.  */
  50.  
  51. struct
  52. {
  53.   char  Prev,  Cur,  *Msg;
  54. }  Error[3] =
  55. {
  56.   ARRAY, FUNCTION, "array of function returning",
  57.   FUNCTION, ARRAY, "function returning array of",
  58.   FUNCTION, FUNCTION, "function returning function"
  59. };
  60.  
  61.  
  62. /*  Function declarations:
  63.  */
  64.  
  65. extern void  Prepare(char *);
  66. extern char  *Define(char *);
  67. extern char  *FuncAccept(char *);
  68. extern void  Insert(char);
  69. extern char  *GetToken(char *);
  70. extern char  *Compare(char *, char *, int);
  71.  
  72.  
  73.  
  74. /*  PROGRAM: Define.
  75.  */
  76.  
  77. void  main(void)
  78. {
  79.   char  *Text,  *Ptr,  Buffer[256];
  80.  
  81.   while (TRUE)
  82.   {
  83.     printf("English: ");
  84.     if (!( Text=gets(Buffer) ))
  85.       break;
  86.     Prepare(Text);
  87.     if (Define(Text))
  88.     {
  89.       printf("C Defin: %s;\n",DefinBase);
  90.       free(DefinBase);
  91.     }
  92.   }
  93. }
  94.  
  95.  
  96. /*  void  Prepare(char *)
  97.  *
  98.  *  Prepare English description: collapse multiple spaces and tabs into a
  99.  *  single space, and replace line delimiters with a null.
  100.  */
  101.  
  102. void  Prepare(char *Text)
  103. {
  104.   int  Ofst = 0;
  105.  
  106.   while (*Text)
  107.   {
  108.     if (Text[Ofst]==' ' || Text[Ofst]=='\t')
  109.     {
  110.       *Text++=' ';
  111.       while (Text[Ofst]==' ' || Text[Ofst]=='\t')
  112.         ++Ofst;
  113.     }
  114.     if (Text[Ofst]=='\n' || Text[Ofst]=='\r' || Text[Ofst]=='\0')
  115.     {
  116.       *Text='\0';
  117.       return;
  118.     }
  119.     *Text=Text[Ofst];
  120.     ++Text;
  121.   }
  122. }
  123.  
  124.  
  125. /*  char  *Define(char *)
  126.  *
  127.  *  Construct C definition from description given in plain English.
  128.  *  Define() returns a pointer to the end of the English text.
  129.  */
  130.  
  131. char  *Define(char *Text)
  132. {
  133.   char  *Ptr;
  134.   char  Prev,  Cur,  i;
  135.  
  136.   DefinBase=NULL;
  137.   DefinLen= InsertAt=0;
  138.   Prev= Cur=OTHER;
  139.  
  140.   /*  Copy identifier name (if present) to start of newly created memory
  141.    *  block -- around this name the definition will be built.
  142.    */
  143.   if (*Text==' ')
  144.     ++Text;
  145.   GetToken(Text);
  146.   if (Token==OTHER)
  147.     while (isalnum(*Text) || *Text=='_')
  148.       Insert(*Text++);
  149.   if (Ptr=Compare(Text,"is",2))
  150.     Text=Ptr;
  151.   /*  Construct rest of definition: prefix and postfix identifier name with C
  152.    *  tokens in accordance with the description.
  153.    *  Also, report any illegal combinations found in the definition.
  154.    */
  155.   while (*Text)
  156.   {
  157.     if (*Text==' ')
  158.       ++Text;
  159.     Text=GetToken(Text);
  160.     Prev=Cur;
  161.     Cur=Token & 070;
  162.     for (i=0; i<3; ++i)
  163.       if (Prev==Error[i].Prev && Cur==Error[i].Cur)
  164.         printf("Error: %s ... Illegal!\n",Error[i].Msg);
  165.  
  166.     InsertAt=DefinLen;
  167.     switch (Token)
  168.     {
  169.       case POINTER:
  170.         /*  Pointer:- if pointer to function or array, enclose definition
  171.          *  with (..). In any case, prepend * to definition.
  172.          */
  173.         if (Compare(Text,"function",4) || Compare(Text,"array",5))
  174.         {
  175.           Insert(')');
  176.           InsertAt=0;
  177.           Insert('(');
  178.         }
  179.         else
  180.           InsertAt=0;
  181.         Insert('*');
  182.         break;
  183.       case FUNCTION:
  184.         /*  Function:- append () to definition.
  185.          */
  186.         Insert('(');
  187.         Insert(')');
  188.         break;
  189.       case FUNCACPT:
  190.         Text=FuncAccept(Text);
  191.         if (Ptr=Compare(Text,"returning",6))
  192.           Text=Ptr;
  193.         break;
  194.       case ARRAY:
  195.         /*  Array:- append [] to definition.
  196.          */
  197.         Insert('[');
  198.         Insert(']');
  199.         break;
  200.       case ARRAYSZ:
  201.         /*  Sized array:- append [size] to definition.
  202.          */
  203.         Insert('[');
  204.         if (*Text==' ')
  205.           ++Text;
  206.         while (isalnum(*Text) || *Text=='_')
  207.           Insert(*Text++);
  208.         Insert(']');
  209.         if (Ptr=Compare(Text,"of",2))
  210.           Text=Ptr;
  211.         break;
  212.       default:
  213.         /*  Data type:- insert data type at start of definition and quit.
  214.          */
  215.         InsertAt=0;
  216.         while (isalnum(*Text) || *Text=='_' || *Text==' ')
  217.           Insert(*Text++);
  218.         Insert(' ');
  219.         InsertAt=DefinLen;
  220.         Insert('\0');
  221.         return  Text;
  222.     }
  223.   }
  224.   InsertAt=DefinLen;
  225.   Insert('\0');
  226.   return  Text;
  227. }
  228.  
  229.  
  230. /*  char  *FuncAccept(char *)
  231.  *
  232.  *  Function accepting parameters:- read multiple parameters, if enclosed
  233.  *  with parentheses, else read one parameter; use Define() to read each
  234.  *  parameter.
  235.  *  FuncAccept() returns a pointer to text to after the parameters.
  236.  */
  237.  
  238. char  *FuncAccept(char *Text)
  239. {
  240.   char  Paren;
  241.   char  *SaveBase,  *Base;
  242.   int    SaveOfst,   Ofst;
  243.  
  244.   if (*Text==' ')
  245.     ++Text;
  246.   if (*Text=='(')
  247.     Paren=TRUE,  ++Text;
  248.   else
  249.     Paren=FALSE;
  250.   InsertAt=DefinLen;
  251.   Insert('(');
  252.   while (TRUE)
  253.   {
  254.     SaveBase=DefinBase,  SaveOfst=DefinLen;
  255.     Text=Define(Text);
  256.     Base=DefinBase;
  257.     DefinBase=SaveBase,  DefinLen=SaveOfst;
  258.     InsertAt=DefinLen;
  259.     for (Ofst=0; Base[Ofst]; ++Ofst)
  260.       Insert(Base[Ofst]);
  261.     free(Base);
  262.     if (!Paren)
  263.       break;
  264.     if (*Text==' ')
  265.       ++Text;
  266.     if (*Text==',')
  267.     {
  268.       ++Text;
  269.       Insert(',');
  270.       Insert(' ');
  271.       continue;
  272.     }
  273.     if (*Text==')')
  274.       ++Text;
  275.     else
  276.       printf("Error: missed ')' on function definition.\n\n");
  277.     break;
  278.   }
  279.   Insert(')');
  280.   return  Text;
  281. }
  282.  
  283.  
  284. /*  void  Insert(char)
  285.  *
  286.  *  Insert one character into C definition at DefinBase+InsertAt; InsertAt
  287.  *  increments by one.
  288.  */
  289.  
  290. void  Insert(char Char)
  291. {
  292.   char  *Ptr;
  293.  
  294.   if ( Ptr=realloc(DefinBase,DefinLen+1) )
  295.   {
  296.     DefinBase=Ptr;
  297.     memmove(DefinBase+InsertAt+1,DefinBase+InsertAt,DefinLen++ -InsertAt);
  298.     DefinBase[InsertAt++]=Char;
  299.   }
  300. }
  301.  
  302.  
  303. /*  char  *GetToken(char *)
  304.  *
  305.  *  Read and return English token from description: OTHER is returned if
  306.  *  token not recognized. The token is held in static variable Token;
  307.  *  GetToken() returns a pointer to Text to after the token.
  308.  */
  309.  
  310. char  *GetToken(char *Text)
  311. {
  312.   char  *Ptr;
  313.  
  314.   if ( (Ptr=Compare(Text,"pointer",4)) || (Ptr=Compare(Text,"ptr",3)) )
  315.   {
  316.     Text=Ptr;
  317.     Token=POINTER;
  318.     if (Ptr=Compare(Text,"to",2))
  319.       return  Ptr;
  320.     return  Text;
  321.   }
  322.   if (Ptr=Compare(Text,"function",4))
  323.   {
  324.     Text=Ptr;
  325.     if (Ptr=Compare(Text,"accepting",6))
  326.     {
  327.       Token=FUNCACPT;
  328.       return  Ptr;
  329.     }
  330.     Token=FUNCTION;
  331.     if (Ptr=Compare(Text,"returning",6))
  332.       return  Ptr;
  333.     return  Text;
  334.   }
  335.   if (Ptr=Compare(Text,"array",5))
  336.   {
  337.     Text=Ptr;
  338.     if (Ptr=Compare(Text,"size",4))
  339.     {
  340.       Token=ARRAYSZ;
  341.       return  Ptr;
  342.     }
  343.     Token=ARRAY;
  344.     if (Ptr=Compare(Text,"of",2))
  345.       return  Ptr;
  346.     return  Text;
  347.   }
  348.   Token=OTHER;
  349.   return  Text;
  350. }
  351.  
  352.  
  353. /*  char  *Compare(char *, char *, int)
  354.  *
  355.  *  Compare description (First) with token name (Second). Token in First must
  356.  *  contain at least Minimum characters from Second (case insensitive).
  357.  *  Compare() returns pointer to First to after token, or null if no match
  358.  *  found.
  359.  */
  360.  
  361. char  *Compare(char *First, char *Second, int Minimum)
  362. {
  363.   int  Count = 0;
  364.  
  365.   if (*First==' ')
  366.     ++First;
  367.   while (tolower(*First)==*Second)
  368.   {
  369.     ++First;
  370.     ++Second;
  371.     ++Count;
  372.   }
  373.   if (Count<Minimum || (*First!=' ' && *First))
  374.     return  NULL;
  375.   return  First;
  376. }
  377.  
  378.  
  379.