home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / listings / v_11_05 / test_obj / tutils.c < prev    next >
C/C++ Source or Header  |  1993-01-22  |  20KB  |  517 lines

  1. /* File:     tutils.c
  2.    Copyright Norman Wilde 1993
  3.    Notes:    code for utilities used in testing system
  4. */
  5. #include <stdlib.h>
  6. #include <stdio.h>
  7. #include <string.h>
  8. #include <assert.h>
  9. #include "tutils.h"
  10. /* ----------- buffer for strings, blocks, etc. ------------- */
  11. #define MAXCOLLECT 10000
  12. char collectBuf[MAXCOLLECT] = {'\0'}; /* reserve space for buffer*/
  13. char * collectPos = collectBuf;       /* points to next free space in buffer*/
  14. void collect(char c) {        /* collect char c into the buffer */
  15.   *collectPos++ = c;
  16.   assert(collectPos - collectBuf < MAXCOLLECT); // abort if buf overflows
  17. }
  18. void collectFirst(char c) {  /* reset buf and collect c */
  19.   collectPos = collectBuf;
  20.   collect(c);
  21. }
  22. char * release() {           /* copy the string in the buf to the
  23.                                 heap, terminate it, and return the copy*/
  24.   char * t = (char *) calloc(sizeof (char), collectPos - collectBuf + 1);
  25.   char * s;
  26.   char * i;
  27.   s = t;
  28.   assert ( t > 0);
  29.   for (i = collectBuf; i < collectPos; )
  30.      *t++ = *i++;
  31.   *t = '\0';
  32.   return s;
  33. }
  34. /* ----------- simple linked list of strings with data---------------- */
  35. struct STRLIST * listNew(char* aStr, void * aData) {
  36.     /* Answer a new list with aStr as only element */
  37.     struct STRLIST *t = (struct STRLIST *) malloc(sizeof(struct STRLIST));
  38.     t->str  = aStr;
  39.     t->data = aData;
  40.     t->next = NULL;
  41.     return t;
  42. }
  43. struct STRLIST * listAdd(struct STRLIST * aList,char* aStr, void * aData) {
  44.     /* Add aStr to aList */
  45.     struct STRLIST *t = (struct STRLIST *) malloc(sizeof(struct STRLIST));
  46.     t->str  = aStr;
  47.     t->data = aData;
  48.     t->next = aList;
  49.     return t;
  50. }
  51. void * listFind(struct STRLIST * aList, char * aStr) {
  52.     /* Locate string matching aStr in aList. Answer the data ptr. if
  53.        found, NULL if not found */
  54.   struct STRLIST * v;
  55.   for(v = aList; v != NULL; v = v->next) {
  56.     if(strcmp(aStr,v->str) ==0) break;
  57.   }
  58.   if(v==NULL)
  59.     return NULL;
  60.   else
  61.     return v->data;
  62. }
  63. int listSize(struct STRLIST *aList) {
  64.     /* Answer the number of elements in the list */
  65.   struct STRLIST * v;
  66.   int size = 0;
  67.   for(v = aList; v != NULL; v = v->next)
  68.     size++;
  69.   return size;
  70. }
  71. /* --- routines to create the test driver program ------- */
  72. #define FBUFSIZE 10000                   /*size of some internal bufs */
  73. static char Buffer[FBUFSIZE];            /*assemble strings as needed */
  74. static char r_name[21] = {'\0'};         /*name given in the runtest
  75.                        stmt currently being processed*/
  76. static char * MainDecls = NULL;          /*store on heap the declarations in
  77.                        the main fcn being built */
  78. static char * MainStmts = NULL;          /*store on heap the statements in
  79.                        the main fcn beint built */
  80. static void addMainDecls(char * decls) {
  81.    /* append to MainDecls a copy of the string in decls */
  82.    char * temp;
  83.    if(MainDecls == NULL) {
  84.        MainDecls = calloc(strlen(decls) + 1, sizeof(char));
  85.        strcpy(MainDecls, decls);
  86.        return;
  87.    } else {
  88.        temp = calloc(strlen(decls) + strlen(MainDecls) + 1, sizeof(char));
  89.        strcpy(temp, MainDecls);
  90.        strcat(temp, decls);
  91.        free(MainDecls);
  92.        MainDecls = temp;
  93.        return;
  94.    }
  95. }
  96. static void addMainStmts(char * stmts) {
  97.    /* append to MainStmts a copy of the string in stmts */
  98.    char * temp;
  99.    if(MainStmts == NULL) {
  100.        MainStmts = calloc(strlen(stmts) + 1, sizeof(char));
  101.        strcpy(MainStmts, stmts);
  102.        return;
  103.    } else {
  104.        temp = calloc(strlen(stmts) + strlen(MainStmts) + 1, sizeof(char));
  105.        strcpy(temp, MainStmts);
  106.        strcat(temp, stmts);
  107.        free(MainStmts);
  108.        MainStmts = temp;
  109.        return;
  110.    }
  111. }
  112. void addBlock(char * block) {
  113.    /* add to the driver the given embedded block */
  114.    /* remove first '{' and last '}' */
  115.    char * tmpStr = calloc(strlen(block), sizeof(char));
  116.    strncat(tmpStr, block + 1, strlen(block) -2);
  117.    printf("%s\n", tmpStr);
  118.    free(tmpStr);
  119. }
  120.  
  121. void setRunName(char * theRName) {
  122.    /* set the name of the test run to the frist 20 chars of theRName*/
  123.    strncpy(r_name, theRName, 20);
  124. }
  125. static char * getArgDeclStr(struct STRLIST *varList) {
  126.    /* Answer a string on the heap with a comma separated list of the
  127.       variables in varList formatted as:
  128.      <argtype> var, <argtype>var,
  129.       suitable for a function's argument declarations.
  130.    */
  131.    char * res, * remainder, * type;
  132.    int thisVarLength, resultLength;
  133.    if(varList == NULL) return NULL;
  134.    type = getVarArgType(varList->str);
  135.    thisVarLength = strlen(varList->str) + strlen(type) + 3;
  136.    if(varList->next == NULL){
  137.      res = calloc(thisVarLength + 1, sizeof (char) );
  138.      sprintf(res, "%s %s", type, varList->str);
  139.      return res;
  140.    }
  141.    remainder = getArgDeclStr( varList->next);
  142.    resultLength = strlen(remainder) + thisVarLength + 1;
  143.    res = calloc(resultLength + 1, sizeof (char) );
  144.    sprintf(res, "%s %s,%s", type, varList->str, remainder);
  145.    free(remainder);
  146.    return res;
  147. }
  148. static char * genFcnString(
  149.    char * run_name,
  150.    char * fcn_name,
  151.    struct STRLIST *varList,
  152.    char* body) {
  153.     /* Answer function string (on heap) for first variable in list*/
  154.   char * declarations;                        /*decls for var. varList->str*/
  155.   int n;                                      /*num. chars assembled */
  156.   char * theFunc;                             /*the result function string*/
  157.   char * remainingVars;                       /*string with vars after this*/
  158.   /* must have at least one variable in the list */
  159.   assert( varList != NULL );
  160.   declarations = getVarDeclStr(varList->str);
  161.   if(varList->next != NULL) {
  162.     remainingVars = getArgDeclStr(varList->next);
  163.     n = sprintf(Buffer,"void %s_%s(int vals[], %s){\n%s%s\n}\n",
  164.         run_name, fcn_name, remainingVars, declarations, body);
  165.     assert(n>0 && n < FBUFSIZE - 2);
  166.     free(remainingVars);
  167.     theFunc = calloc(strlen(Buffer)+1, sizeof(char));
  168.     strcpy(theFunc,Buffer);
  169.   } else {
  170.     n = sprintf(Buffer,"void %s_%s(int vals[]){\n %s%s\n}\n",
  171.         run_name, fcn_name, declarations, body);
  172.     assert(n>0 && n < FBUFSIZE - 2);
  173.     theFunc = calloc(strlen(Buffer)+1, sizeof(char));
  174.     strcpy(theFunc,Buffer);
  175.   }
  176.   return theFunc;
  177. }  
  178. static char * genBottomFcnString(
  179.    char * run_name,
  180.    struct STRLIST *varList,
  181.    char* body) {
  182.     /* Answer function string (on heap) for the 'bottom' function
  183.        that contains the actual test code*/
  184.   int n;                                      /*num. chars assembled */
  185.   char * theFunc;                             /*the result function string*/
  186.   char * remainingVars;                       /*string with vars after this*/
  187.   /* must have at least one variable in the list */
  188.   assert( varList != NULL );
  189.   remainingVars = getArgDeclStr(varList);
  190.   n = sprintf(Buffer,"void %s_bottom(int vals[], %s)\n%s\n",
  191.           run_name, remainingVars, body);
  192.   assert(n>0 && n < FBUFSIZE - 2);
  193.   free(remainingVars);
  194.   theFunc = calloc(strlen(Buffer)+1, sizeof(char));
  195.   strcpy(theFunc,Buffer);
  196.   return theFunc;
  197. }
  198. static char * getVarNameStr(struct STRLIST *varList) {
  199.    /* Answer a string on the heap with a comma separated list of the
  200.       variables in varList. If there are no variables, return
  201.       an empty string.
  202.    */
  203.    char * res, * remainder;
  204.    int thisVarLength, resultLength;
  205.    if(varList == NULL)               /* if no variables, return empty str */
  206.      return calloc(1, sizeof (char) );
  207.    thisVarLength = strlen(varList->str);
  208.    if(varList->next == NULL){
  209.      res = calloc(thisVarLength + 1, sizeof (char) );
  210.      sprintf(res, "%s", varList->str);
  211.      return res;
  212.    }
  213.    remainder = getVarNameStr( varList->next);
  214.    resultLength = strlen(remainder) + thisVarLength + 1;
  215.    res = calloc(resultLength + 1, sizeof (char) );
  216.    sprintf(res, "%s,%s", varList->str, remainder);
  217.    free(remainder);
  218.    return res;
  219. }
  220.  
  221. static char * genArgString(struct STRLIST *varList) {
  222.    /* Answer a string (on heap) of the form:
  223.      <1stvar>[vals[n-1]], <2ndvar>, ...<nthvar>
  224.    */
  225.   int n = listSize(varList);       /* elements in varList */
  226.   int m;
  227.   char * theStr, * theRest;
  228.   if(varList == NULL)   /* return a pointer to a '\0' on the heap */
  229.     return ((char *) calloc(1, sizeof(char)));
  230.   theRest = getVarNameStr(varList->next);
  231.   if(strlen(theRest) > 0)
  232.       m = sprintf(Buffer, "%s[vals[%i]],%s", varList->str, n-1, theRest);
  233.   else
  234.       m = sprintf(Buffer, "%s[vals[%i]]", varList->str, n-1);
  235.   assert(m>0 && m < FBUFSIZE - 2);
  236.   theStr = calloc(strlen(Buffer)+1, sizeof(char));
  237.   strcpy(theStr,Buffer);
  238.   free(theRest);
  239.   return theStr;
  240. }
  241.  
  242. static char * genNextBodyString(
  243.    char * run_name,
  244.    char * suffex,
  245.    struct STRLIST *varList) {
  246.     /* Answer a string (on heap) for the body of the next
  247.        function down the list. Contains a function call:
  248.           <run_name>_<suffex>(vals, <arguments in varList>);
  249.     */
  250.   char * varNameStr = genArgString(varList);  /*vars with subscripts*/
  251.   char * nextBody;                            /*heap space for next body */
  252.   int n;                                      /*num. chars assembled */
  253.   n = sprintf(Buffer,"  %s_%s(vals,%s);\n",
  254.         run_name,suffex,varNameStr);
  255.   assert(n>0 && n < FBUFSIZE - 2);
  256.   nextBody = calloc(strlen(Buffer)+1, sizeof(char));
  257.   strcpy(nextBody,Buffer);
  258.   return nextBody;
  259. }
  260. static struct STRLIST * makeVarFuncs(
  261.    char * run_name,
  262.    struct STRLIST *varList,
  263.    char* body) {
  264.   /* Answer a list of strings that are test functions for each
  265.      variable in varList. Each test function has the form:
  266.     void <run_name>_<var>(int vals[], <other args>) {
  267.       <declaration of array for variable var>
  268.       <body>
  269.     }
  270.      The body is a call to the previous function in the list
  271.   */
  272.   struct STRLIST * funcList = NULL;           /*fcns after this one */
  273.   char * nextBody;                            /*heap space for next body */
  274.   char * theFunc;                             /*heap space for this fcn */
  275.   int n;                                      /*num. chars assembled */
  276.   /* must have at least one variable in the list */
  277.   assert( varList != NULL );
  278.   if(varList->next != NULL) {
  279.     /* Generate functions for the rest of the variable list - recursive*/
  280.     nextBody = genNextBodyString(run_name, varList->str, varList->next);
  281.     funcList = makeVarFuncs(run_name, varList->next, nextBody);
  282.     theFunc = genFcnString(run_name, varList->str, varList, body);
  283.     return (listAdd(funcList, theFunc, ""));
  284.   }
  285.   else {
  286.     theFunc = genFcnString(run_name, varList->str, varList, body);
  287.     return (listNew(theFunc, ""));
  288.   };
  289. }
  290. static char * getLastVar(struct STRLIST *varList) {
  291.    /* Answer the string with the name of the last variable in varList */
  292.    struct STRLIST * v;
  293.    assert(varList != NULL);
  294.    for(v = varList; v->next != NULL; v = v->next) ; /* empty loop */
  295.    return v->str;
  296. }
  297. static char * getNumValsStr(struct STRLIST *varList) {
  298.    /* Answer a string on the heap with a comma separated list of the
  299.       number of values of each variable in varList formatted as:
  300.      <vals_lastVar>,...,<vals_firstVar>
  301.       suitable for an array declaration
  302.    */
  303.    char * res, * remainder;
  304.    int thisVarNumVals;
  305.    assert(varList != NULL);
  306.    thisVarNumVals =
  307.       getVarNumVals(varList->str);  /* values of first var on list */
  308.    assert(thisVarNumVals > 0);
  309.    if(varList->next != NULL) {
  310.      remainder = getNumValsStr(varList->next);
  311.      sprintf(Buffer, "%s,%i", remainder, thisVarNumVals);
  312.      free(remainder);
  313.    } else {
  314.      sprintf(Buffer,"%i", thisVarNumVals);
  315.    }
  316.    res = calloc(strlen(Buffer) + 1, sizeof (char) );
  317.    strcpy(res,Buffer);
  318.    return res;
  319. }
  320.  
  321. void makeVary(struct STRLIST * varList, char * block) {
  322.   struct STRLIST * v, * t;
  323.   char * nextBody;              /*body of the first level function */
  324.   char * theFunc;               /*generated top level function */
  325.   char * numValsStr;            /*str with max values of each variable */
  326.   int numVars;                  /*no. of variables in varList */
  327.   char * top_var;               /*name of last variable in varList */
  328.   int m;
  329.   assert( varList != NULL); /* must have at least one variable */
  330.   nextBody = genNextBodyString(r_name, "bottom", varList);
  331.   v = makeVarFuncs(r_name, varList, nextBody);
  332.   theFunc = genBottomFcnString(r_name, varList, block);
  333.   v = listAdd(v, theFunc, "");
  334.   /* write the generated functions to stdout */
  335.   for( t = v; t != NULL; t = t->next )
  336.     printf("%s\n", t->str);
  337.   /* WRITE THE FOLLOWING TO THE MAIN
  338.   int nvals_<r_name>[<links in varList>]={<list of no. of vals of each var - rev.order>};
  339.   Test_gen_varying g_<r_name>(<links in varList>,nvals_<r_name>);
  340.   int vals_<r_name>[<links in varList>]={-1};
  341.   while (g_<r_name>.next_vector(vals_<r_name>) == YES) {
  342.       <r_name>_<name of last var>(vals_<r_name>);
  343.    };
  344.   */
  345.   numValsStr = getNumValsStr(varList);
  346.   numVars = listSize(varList);
  347.   top_var = getLastVar(varList);
  348.   m = sprintf(Buffer,                /* declarations for the main */
  349.       "int nvals_%s[%i] = { %s };\n"
  350.       "Test_gen_varying g_%s(%i, nvals_%s);\n"
  351.       "int vals_%s[%i] = { -1 };\n",
  352.       r_name,numVars,numValsStr,
  353.       r_name,numVars,r_name,
  354.       r_name,numVars);
  355.   assert( m > 0 && m < FBUFSIZE - 2);
  356.   addMainDecls(Buffer);
  357.   m = sprintf(Buffer,                   /* statements for the main */
  358.       "while (g_%s.next_vector(vals_%s) == YES) {\n"
  359.       "   %s_%s(vals_%s);\n"
  360.       "};\n",
  361.       r_name,r_name,
  362.       r_name,top_var,r_name);
  363.   assert( m > 0 && m < FBUFSIZE - 2);
  364.   addMainStmts(Buffer);
  365. }
  366.  
  367. void makeComb(struct STRLIST * varList, char * block) {
  368.   struct STRLIST * v, * t;
  369.   char * nextBody;              /*body of the first level function */
  370.   char * theFunc;               /*generated top level function */
  371.   char * numValsStr;            /*str with max values of each variable */
  372.   int numVars;                  /*no. of variables in varList */
  373.   char * top_var;               /*name of last variable in varList */
  374.   int m;
  375.   assert( varList != NULL); /* must have at least one variable */
  376.   nextBody = genNextBodyString(r_name, "bottom", varList);
  377.   v = makeVarFuncs(r_name, varList, nextBody);
  378.   theFunc = genBottomFcnString(r_name, varList, block);
  379.   v = listAdd(v, theFunc, "");
  380.   /* write the generated functions to stdout */
  381.   for( t = v; t != NULL; t = t->next )
  382.     printf("%s\n", t->str);
  383.   /* WRITE THE FOLLOWING TO THE MAIN
  384.   int nvals_<r_name>[<links in varList>]={<list of no. of vals of each var - rev.order>};
  385.   Test_gen_combining g_<r_name>(<links in varList>,nvals_<r_name>);
  386.   int vals_<r_name>[<links in varList>]={-1};
  387.   while (g_<r_name>.next_vector(vals_<r_name>) == YES) {
  388.       <r_name>_<name of last var>(vals_<r_name>);
  389.    };
  390.   */
  391.   numValsStr = getNumValsStr(varList);
  392.   numVars = listSize(varList);
  393.   top_var = getLastVar(varList);
  394.   m = sprintf(Buffer,                /* declarations for the main */
  395.       "int nvals_%s[%i] = { %s };\n"
  396.       "Test_gen_combining g_%s(%i, nvals_%s);\n"
  397.       "int vals_%s[%i] = { -1 };\n",
  398.       r_name,numVars,numValsStr,
  399.       r_name,numVars,r_name,
  400.       r_name,numVars);
  401.   assert( m > 0 && m < FBUFSIZE - 2);
  402.   addMainDecls(Buffer);
  403.   m = sprintf(Buffer,                   /* statements for the main */
  404.       "while (g_%s.next_vector(vals_%s) == YES) {\n"
  405.       "   %s_%s(vals_%s);\n"
  406.       "};\n",
  407.       r_name,r_name,
  408.       r_name,top_var,r_name);
  409.   assert( m > 0 && m < FBUFSIZE - 2);
  410.   addMainStmts(Buffer);
  411. }
  412.  
  413. void writeDriver(void) {
  414.    /* write the main function of the driver to standard output */
  415.    printf("void main() {\n%s%s}\n", MainDecls, MainStmts);
  416. }
  417.  
  418. /* --- routines to manage a table of all the variables in a test file --- */
  419. static struct STRLIST * VarTable = NULL;  /* The table of variables */
  420. void addVars(struct STRLIST * vList, char * typeStr, struct STRLIST * iList) {
  421.     /* Add to the table the variables in vList, each of which is
  422.        of type typeStr and has the set of initializors iList */
  423.   struct STRLIST *v;
  424.   struct VARIABLE * newVar;
  425.   for(v = vList; v != NULL; v = v->next) {
  426.     newVar = (struct VARIABLE *) malloc(sizeof(struct VARIABLE));
  427.     newVar->name  = v->str;
  428.     newVar->dtype = typeStr;
  429.     newVar->atype = typeStr;
  430.     newVar->inits = iList;
  431.     if(VarTable == NULL)
  432.       VarTable = listNew(v->str, newVar);
  433.     else
  434.       VarTable = listAdd(VarTable, v->str, newVar);
  435.   };
  436. }
  437. void addTVars(struct STRLIST * vList, char * decType, char * argType, struct STRLIST * iList) {
  438.     /* Add to the table the variables in vList, each of which is
  439.        of type decType for declarations and type argType for arguments
  440.        and has the set of initializors iList */
  441.   struct STRLIST *v;
  442.   struct VARIABLE * newVar;
  443.   for(v = vList; v != NULL; v = v->next) {
  444.     newVar = (struct VARIABLE *) malloc(sizeof(struct VARIABLE));
  445.     newVar->name  = v->str;
  446.     newVar->dtype = decType;
  447.     newVar->atype = argType;
  448.     newVar->inits = iList;
  449.     if(VarTable == NULL)
  450.       VarTable = listNew(v->str, newVar);
  451.     else
  452.       VarTable = listAdd(VarTable, v->str, newVar);
  453.   };
  454. }
  455. char * getVarDecType(char * aVar) {
  456.     /* answer a string with the type of the variable, suitable for
  457.        a C/C++ declaration */
  458.   struct VARIABLE *v;
  459.   v = (struct VARIABLE *) listFind(VarTable, aVar);
  460.   if(v == NULL)
  461.     return "DUMMY TYPE";
  462.   else
  463.     return(v->dtype);
  464. }
  465.   char * getVarArgType(char * aVar) {
  466.     /* answer a string with the type of the variable, suitable for
  467.        a C/C++ function argument declaration */
  468.   struct VARIABLE *v;
  469.   v = (struct VARIABLE *) listFind(VarTable, aVar);
  470.   if(v == NULL)
  471.     return "DUMMY TYPE";
  472.   else
  473.     return(v->atype);
  474. }
  475. int getVarNumVals(char * aVar) {
  476.    /* answer the number of values in the set of initializors of
  477.       aVar, or 0 if aVar is not found in the table */
  478.   struct VARIABLE *v;
  479.   v = (struct VARIABLE *) listFind(VarTable, aVar);
  480.   if(v == NULL)
  481.     return 0;
  482.   else
  483.     return(listSize(v->inits));
  484. }
  485. static char * genInitsStr(struct STRLIST * inList) {
  486.    /* Answer a string with the initializors in inList, separated
  487.       by ",\n" */
  488.    char * res, * remainder;
  489.    char * thisInit;
  490.    assert(inList != NULL);
  491.    thisInit = inList->str;          /* first initializor on list */
  492.    if(inList->next != NULL) {
  493.      remainder = genInitsStr(inList->next);
  494.      sprintf(Buffer, "%s,\n%s", remainder, thisInit);
  495.      free(remainder);
  496.    } else {
  497.      sprintf(Buffer,"%s", thisInit);
  498.    }
  499.    res = calloc(strlen(Buffer) + 1, sizeof (char) );
  500.    strcpy(res,Buffer);
  501.    return res;
  502. }
  503. char * getVarDeclStr(char * aVar) {
  504.     /* answer a string with a c/c++ initialized declaration for
  505.        aVar, using all the initializors of the variable */
  506.   struct VARIABLE *v;                      /* data struct for aVar */
  507.   char * initStr;                          /* string with the initializors */
  508.   char * res;                              /* result string */
  509.   v = (struct VARIABLE *) listFind(VarTable, aVar);
  510.   assert (v != NULL); /* the variable must exist */
  511.   initStr = genInitsStr(v->inits);
  512.   sprintf(Buffer, "%s %s[] = {\n%s};\n", getVarDecType(aVar), aVar, initStr);
  513.   res = calloc(strlen(Buffer) + 1, sizeof (char) );
  514.   strcpy(res,Buffer);
  515.   free(initStr);
  516.   return res;
  517. }