home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 22 gnu / 22-gnu.zip / db02_src.zip / generate.cc < prev    next >
C/C++ Source or Header  |  1994-02-22  |  29KB  |  1,132 lines

  1. /**************************************************************************
  2.  * Source Id :
  3.  *
  4.  * $Id: generate.cc,v 1.45 1993/11/05 12:45:05 kevinl Exp $
  5.  *-------------------------------------------------------------------------
  6.  * Project Notes :
  7.  *
  8.  *  Diamond Base
  9.  *  ============
  10.  *    A solid database implementation, spurred on by the continuing
  11.  *  Metal (Lead) Base saga.
  12.  *
  13.  *  Project Team :
  14.  *      A. Davison
  15.  *      K. Lentin
  16.  *      D. Platt
  17.  *
  18.  *    Project Commenced : 05-02-1993
  19.  *
  20.  *-------------------------------------------------------------------------
  21.  *  Module Notes :
  22.  *
  23.  *  Object header and code generator.
  24.  *
  25.  *
  26.  *  Original Author : Krazy Kev
  27.  *
  28.  *-------------------------------------------------------------------------
  29.  * Revision History:
  30.  *
  31.  * $Log: generate.cc,v $
  32. // Revision 1.45  1993/11/05  12:45:05    kevinl
  33. // Fixed problems that CC picked up (and some multi bugs)
  34. //
  35. // Revision 1.44  1993/11/03  12:19:27    kevinl
  36. // Added ctype.h to generated code
  37. //
  38. // Revision 1.43  1993/11/03  12:09:11    davison
  39. // Replaced missing brace in ichar comparision code.
  40. //
  41. // Revision 1.42  1993/11/03  11:51:31    davison
  42. // Removed the default value from the (pKeyType,long) constructor.
  43. //
  44. // Revision 1.41  1993/11/03  10:04:46    kevinl
  45. // Added ichar and utils.{h,cc}
  46. //
  47. // Revision 1.40  1993/10/28  00:40:08    davison
  48. // Another missing backslash.
  49. //
  50. // Revision 1.39  1993/10/25  08:32:51    kevinl
  51. // Let's try dbData constructors
  52. //
  53. // Revision 1.38  1993/10/24  15:35:45    kevinl
  54. // Added derived class generation
  55. //
  56. // Revision 1.37  1993/10/24  09:14:26    kevinl
  57. // Fixed unused idxList in genCons????
  58. //
  59. // Revision 1.36  1993/10/23  06:35:34    davison
  60. // Changed bzero reference to memset.
  61. //
  62. // Revision 1.35  1993/10/19  14:27:37    kevinl
  63. // Fixed constructors/retrievers
  64. //
  65. // Revision 1.34  1993/10/19  11:43:02    kevinl
  66. // Default values
  67. //
  68. // Revision 1.33  1993/10/19  02:36:08    kevinl
  69. // Added get to genConsDefn
  70. //
  71. // Revision 1.32  1993/10/19  01:06:40    davison
  72. // Fixed a missing slash...
  73. //
  74. // Revision 1.31  1993/10/18  08:01:41    kevinl
  75. // Added constructors and fixed some probs
  76. //
  77. // Revision 1.30  1993/09/27  01:15:44    kevinl
  78. // Changed ORD_COMPARE to use < and >
  79. //
  80. // Revision 1.29  1993/09/26  06:40:32    kevinl
  81. // Added dbData support
  82. //
  83. // Revision 1.28  1993/09/06  13:25:57    kevinl
  84. // Removed a remnant hard coded classname, replaced with structName
  85. //
  86. // Revision 1.27  1993/08/29  12:56:27    kevinl
  87. // Fixed problems of assigning relations to each other.
  88. //
  89. // Revision 1.26  1993/07/19  11:53:42    kevinl
  90. // Removed some Borland warnings re incorrect assignments and a non-
  91. // terminated string
  92. //
  93. // Revision 1.25  1993/07/11  09:42:05    kevinl
  94. // Changed String to dbString
  95. //
  96. // Revision 1.24  1993/07/09  04:02:36    kevinl
  97. // Fixed return in setUnique
  98. // Nuked some ints
  99. //
  100. // Revision 1.23  1993/07/01  13:27:16    kevinl
  101. // Pointers to uniques no longer returned. {has,get,set}Unqiue members
  102. //
  103. // Revision 1.22  1993/06/23  05:21:22    kevinl
  104. // Mallocs are now in angular brackets
  105. //
  106. // Revision 1.21  1993/06/20  13:41:59    kevinl
  107. // Fixed multiple mallocs
  108. // Added String support
  109. //
  110. // Revision 1.20  1993/05/27  07:31:29    kevinl
  111. // Some missing \'s which gcc -Wall didn't pick up!!!
  112. //
  113. // Revision 1.19  1993/05/26  00:58:24    kevinl
  114. // Arrays for uniques and field lengths now not static
  115. // Fixed inlines with multiple returns
  116. // MALLOC_H_MISSING
  117. //
  118. // Revision 1.18  1993/05/12  02:19:25    kevinl
  119. // Added verStr to generated class
  120. // Fixed REAL_COMPARE
  121. //
  122. // Revision 1.17  1993/05/06  04:26:30    kevinl
  123. // SASC for malloc.h
  124. // Now uses key structures to align the keys
  125. // Also fixed empty unique arrays
  126. //
  127. // Revision 1.16  1993/05/01  14:41:47    kevinl
  128. // Conditional operator instead of trusting value of !=
  129. //
  130. // Revision 1.15  1993/04/27  07:10:23    kevinl
  131. // Added uniqueArray and isUnique
  132. // Comments
  133. //
  134. // Revision 1.14  1993/04/15  04:21:52    kevinl
  135. // Moved malloc.h
  136. //
  137. // Revision 1.13  1993/04/14  14:17:15    kevinl
  138. // Now we close the output streams
  139. //
  140. // Revision 1.12  1993/04/11  00:57:15    davison
  141. // Added a dbError() cast operator to return the error status for the class.
  142. //
  143. // Revision 1.11  1993/04/08  15:40:23    kevinl
  144. // Adjusted spacing in generated constructor
  145. //
  146. // Revision 1.10  1993/04/06  23:23:09    kevinl
  147. // Bye Bye bcopy
  148. //
  149. // Revision 1.9  1993/04/04  23:59:34  kevinl
  150. // Generate structs to hold aligned keys
  151. //
  152. // Revision 1.8  1993/04/01  11:23:23  kevinl
  153. // Set unique field to -1 in constructor
  154. //
  155. // Revision 1.7  1993/03/30  14:39:02  kevinl
  156. // Generate address of structure members so struct packing is not a factor
  157. //
  158. // Revision 1.6  1993/03/30  06:54:16  kevinl
  159. // Added getUnique member
  160. //
  161. // Revision 1.5  1993/03/29  08:20:09  darrenp
  162. // Added new malloc library support
  163. //
  164. // Revision 1.4  1993/03/25  22:20:10  davison
  165. // Fixed last patch - needed a space after "public" in the
  166. // class definition.
  167. //
  168. // Revision 1.3  1993/03/25  18:17:16  davison
  169. // Make the generated class inherit the structure publicly.
  170. //
  171. // Revision 1.2  1993/03/24  06:17:54  kevinl
  172. // fixed include file name, struct and class name
  173. // Fixed duplicate/unused a loop variable counter, indentation etc
  174. // Added theData() function
  175. //
  176. // Revision 1.1  1993/03/21  23:36:54  kevinl
  177. // Initial revision
  178. //
  179.  **************************************************************************/
  180.  
  181. #if !defined(MALLOC_H_MISSING) && !defined(MALLOC_H_INCLUDED)
  182. extern "C" {
  183. #include <malloc.h>
  184. }
  185. #define MALLOC_H_INCLUDED
  186. #endif
  187. #include <fstream.h>
  188. #ifdef __EMX__
  189. #include <strstrea.h>
  190. #else
  191. #include <strstream.h>
  192. #endif
  193. #include <string.h>
  194. #include <defs.h>
  195. #include <utils.h>
  196. #include <idxinfo.h>
  197. #include <d_types.h>
  198.  
  199. strstream keyStr;
  200.  
  201. // mySizeOf:
  202. // Since all our types are merely numbers, we need out own sizeof
  203.  
  204. long mySizeOf(int tp)
  205. {
  206.     switch (tp)
  207.     {
  208.         case D_SHORT: return sizeof(short);
  209.         case D_USHORT: return sizeof(ushort);
  210.         case D_DATA:
  211.         case D_STRING:
  212.         case D_LONG: return sizeof(long);
  213.         case D_ULONG: return sizeof(ulong);
  214.         case D_DOUBLE: return sizeof(double);
  215.         case D_FLOAT: return sizeof(float);
  216.         case D_MONEY: return sizeof(moneyType);
  217.         case D_DATE: return sizeof(dateType);
  218.         case D_ICHAR:
  219.         case D_CHAR: return sizeof(char);
  220.         case D_UNIQUE: return sizeof(uniqueType);
  221.     }
  222.     return 0;
  223. }
  224.  
  225. // typeName:
  226. // This is needed to output the correct code based on our form of types
  227.  
  228. char*
  229. typeName(long tp, bool realData=false)
  230. {
  231.     static char tpName[20];
  232.  
  233.     switch (tp) {
  234.         case D_SHORT: strcpy(tpName, "short"); break;
  235.         case D_USHORT: strcpy(tpName, "ushort"); break;
  236.         case D_DATA: strcpy(tpName, realData?"dbData":"long"); break;
  237.         case D_STRING: strcpy(tpName, realData?"dbString":"long"); break;
  238.         case D_LONG: strcpy(tpName, "long"); break;
  239.         case D_ULONG: strcpy(tpName, "ulong"); break;
  240.         case D_DOUBLE: strcpy(tpName, "double"); break;
  241.         case D_FLOAT: strcpy(tpName, "float"); break;
  242.         case D_MONEY: strcpy(tpName, "moneyType"); break;
  243.         case D_DATE: strcpy(tpName, "dateType"); break;
  244.         case D_CHAR: strcpy(tpName, "char"); break;
  245.         case D_ICHAR: strcpy(tpName, "ichar"); break;
  246.         case D_UNIQUE: strcpy(tpName, "uniqueType"); break;
  247.         default: strcpy(tpName, "THISISABUG"); break;
  248.     }
  249.     return tpName;
  250. }
  251.  
  252. // genUniqueArray:
  253. // Generate the list of bool's that specify is a field is unique
  254.  
  255. void genUniqueArray(ofstream& of, indexList* idxList, fieldList* fldList)
  256. {
  257.     indexInfo* i = idxList->indicies;
  258.     long u = -1;
  259.     long fldNum = 0;
  260.  
  261.     // Do we have a unique field?
  262.  
  263.     for (fieldInfo* f = fldList->fields; f; f=f->nextFld, fldNum++)
  264.         if (f->fldType == D_UNIQUE)
  265.         {
  266.             u = fldNum;
  267.             break;
  268.         }
  269.  
  270.     // No, leave
  271.     if (u==-1)
  272.     {
  273.         for (long l=0; l < idxList->numIndicies; l++)
  274.         {
  275.             if (l)
  276.                 of << ",";
  277.             of << "false";
  278.         }
  279.         return;
  280.     }
  281.  
  282.     // Now go through the indicies
  283.     while (i)
  284.     {
  285.         if (i != idxList->indicies) of << ","; // Add a comma to separate
  286.         bool gotIt = false;
  287.  
  288.         for (int j=0; j<MAX_FIELDS_IN_INDEX && i->idxFields[j] != -1;  j++)
  289.         {
  290.             // Is this the unique field?
  291.             if (u == i->idxFields[j])
  292.             {
  293.                 gotIt = true;
  294.                 break;
  295.             }
  296.         }
  297.  
  298.         // output it
  299.         of << (gotIt?"true":"false");
  300.         i=i->nextIdx;
  301.     }
  302. }
  303.  
  304. // genArray:
  305. // Generate the list of index sizes for the indexSize array
  306.  
  307. //void genArray(ofstream& of, indexList* idxList, fieldList* fldList)
  308. void genArray(ofstream& of, char* className, indexList* idxList)
  309. {
  310.     for (long i=0; i < idxList->numIndicies; i++)
  311.     {
  312.         if (i)
  313.             of << ",";
  314.         of << "sizeof(_" << className << "_idxStr" << i << ")";
  315.     }
  316. #if 0
  317.     indexInfo* i = idxList->indicies;
  318.  
  319.     while (i)
  320.     {
  321.         if (i != idxList->indicies) of << ","; // Add a comma to separate
  322.         long len = 0;
  323.  
  324.         // This ugly loopy thing turns up a lot. It is because we store
  325.         // field numbers in the index list, yet our fields are not directly
  326.         // accessable by those numbers. Given the infrequency of use of the
  327.         // gerenator compared to the rest of the system, there are more
  328.         // important things to fix.
  329.  
  330.         for (int j=0; j<MAX_FIELDS_IN_INDEX && i->idxFields[j] != -1;  j++)
  331.         {
  332.             fieldInfo* f = fldList->fields;
  333.             for (int k=0; k < i->idxFields[j]; k++)
  334.                 f=f->nextFld;
  335.  
  336.             // Add up the field length
  337.             len+=f->fldSize;
  338.         }
  339.  
  340.         // output it
  341.         of << len;
  342.         i=i->nextIdx;
  343.     }
  344. #endif
  345. }
  346.  
  347. // genStructs:
  348. // This generates the structure to store the relation data in.
  349.  
  350. void genStructs(ofstream& of, char* className, indexList* idxList, fieldList* fldList)
  351. {
  352.     indexInfo* i = idxList->indicies;
  353.     int num=0;
  354.  
  355.     while (i)
  356.     {
  357.         // OK, here's another ugli-ish thing. For historical (or maybe
  358.         // hysterical) reasons, the \n's are at the start of all these long
  359.         // strings. One day, when I have lots of time and patience, I will put
  360.         // them on the end of the strings, and get rid of the ugly \'s on the
  361.         // ends of all the lines.
  362.  
  363.         of << "\
  364. \ntypedef struct _" << className << "_idxStr" << num << " {\
  365. ";
  366.         for (int ch=0; ch <=1; ch++)
  367.             for (int j=0; j<MAX_FIELDS_IN_INDEX && i->idxFields[j] != -1;  j++)
  368.             {
  369.                 fieldInfo* f = fldList->fields;
  370.                 for (int k=0; k < i->idxFields[j]; k++)
  371.                     f=f->nextFld;
  372.  
  373.                 // This loop is executed twice. During the first pass, no
  374.                 // char types are included. These are added on the end during
  375.                 // the second pass. This is to solve alignment problems caused
  376.                 // by single chars in the middle of a series of word aligned
  377.                 // fields.
  378.                 if (ch ^ ((f->fldType != D_CHAR && f->fldType != D_ICHAR)?1:0))
  379.                 {
  380.                     of << "\
  381. \n    " << typeName(f->fldType) << "  ";
  382.  
  383.                     // This won't happen since they're not supported yet
  384.                     // but I typed it in by mistake so leave it here. It will
  385.                     // be needed later.
  386.                     if (f->fldType == D_STRING || f->fldType == D_DATA)
  387.                     {
  388.                         of << "_off_";
  389.                     }
  390.                     of << f->fldName;
  391.  
  392.                     // Is this an array?
  393.                     if (f->fldSize != mySizeOf(f->fldType))
  394.                     {
  395.                         of << "[" << f->fldSize / mySizeOf(f->fldType) << "]";
  396.                     }
  397.                     of << ";";
  398.                 }
  399.             }
  400.         of << "\
  401. \n};\
  402. \n\
  403. ";
  404.         i=i->nextIdx;
  405.         num++;
  406.     }
  407. }
  408.  
  409. // genUnique:
  410. // This generates 3 different methods. {get,set,has}Unique
  411. // They manipulate the Unqiue member if it exists.
  412. // The type parameter is number 0 1 2 for set get has
  413.  
  414. void genUnique(ofstream& of, fieldList* fldList, long type)
  415. {
  416.     if (type)
  417.         of << "return";
  418.     for (fieldInfo* f = fldList->fields; f; f=f->nextFld)
  419.         if (f->fldType == D_UNIQUE)
  420.         {
  421.             if (!type) // set
  422.                 of << " " << f->fldName << " = uniq;";
  423.             else if (type == 1) // get
  424.                 of << " " << f->fldName << ";";
  425.             else // has
  426.                 of << " true;";
  427.             return;
  428.         }
  429.     // There is no unique field
  430.     if (!type) // set
  431.         of << ";";
  432.     else if (type == 1) // get
  433.         of << " -1;";
  434.     else // has
  435.         of << " false;";
  436. }
  437.  
  438. // genConsDecls:
  439. // Generate header declarations for the constructors.
  440.  
  441. void genConsDecls(ofstream& of, char* className, fieldList* fldList, indexList* consList, bool& voidDone)
  442. {
  443.     indexInfo* c = consList->indicies;
  444.  
  445.     while (c)
  446.     {
  447.         of << "\
  448. \n    " << className << "(";
  449.  
  450.         long count = 0;
  451.     for (int j=0; j<MAX_FIELDS_IN_INDEX && c->idxFields[j] != -1;  j++)
  452.     {
  453.         fieldInfo* f = fldList->fields;
  454.         for (int k=0; k < c->idxFields[j]; k++)
  455.         f=f->nextFld;
  456.             if (j)
  457.                 of << ", ";
  458.             of << typeName(f->fldType,true);
  459.             if (f->fldSize != mySizeOf(f->fldType))
  460.                 of << "*";
  461.             of << " _cons_" << f->fldName;
  462.             count++;
  463.     }
  464.  
  465.         if (!count)
  466.             voidDone = TRUE;
  467.         of << ");";
  468.  
  469.     c=c->nextIdx;
  470.     }
  471. }
  472.  
  473. // genConsDefns:
  474. // Generate definitions for the constructors.
  475.  
  476. void genConsDefns(ofstream& of, char* className, char* structName, fieldList* fldList, indexList* consList)
  477. {
  478.     indexInfo* c = consList->indicies;
  479.  
  480.     while (c)
  481.     {
  482.         of << "\
  483. \n" << className << "::" << className << "(";
  484.  
  485.     for (int j=0; j<MAX_FIELDS_IN_INDEX && c->idxFields[j] != -1;  j++)
  486.     {
  487.         fieldInfo* f = fldList->fields;
  488.         for (int k=0; k < c->idxFields[j]; k++)
  489.         f=f->nextFld;
  490.             if (j)
  491.                 of << ", ";
  492.             of << typeName(f->fldType, true);
  493.             if (f->fldSize != mySizeOf(f->fldType))
  494.                 of << "*";
  495.             of << " _cons_" << f->fldName;
  496.     }
  497.  
  498.         of << ") : diaRel(\"" << className << "\")," << structName << "() {\
  499. \n    commonInit();\
  500. ";
  501.  
  502.     for (j=0; j<MAX_FIELDS_IN_INDEX && c->idxFields[j] != -1;  j++)
  503.     {
  504.         fieldInfo* f = fldList->fields;
  505.         for (int k=0; k < c->idxFields[j]; k++)
  506.         f=f->nextFld;
  507.             if (f->fldSize / mySizeOf(f->fldType) == 1)
  508.                 of << "\
  509. \n    " << f->fldName << " = _cons_" << f->fldName << ";";
  510.             else if (f->fldType == D_CHAR || f->fldType == D_ICHAR)
  511.                 of << "\
  512. \n    strNcpy(" << f->fldName << ",_cons_" << f->fldName << "," << f->fldSize << ");";
  513.             else of << "\
  514. \n    bcopy(_cons_" << f->fldName << "," << f->fldName << "," << f->fldSize << ");";
  515.     }
  516.  
  517.         if (c->idxType != -1)
  518.             of << "\
  519. \n    get(" << c->idxType << ");\
  520. ";
  521.         of << "\
  522. \n};\
  523. \n\
  524. ";
  525.  
  526.     c=c->nextIdx;
  527.     }
  528. }
  529.  
  530. // genGetSetCases:
  531. // This is used to generated the case's contained in the switches in getKey
  532. // and setKey.
  533.  
  534. void genGetSetCases(ofstream& of, char* className, indexList* idxList, fieldList* fldList, bool isGet)
  535. {
  536.     indexInfo* i = idxList->indicies;
  537.     long caseNum = 0;
  538.  
  539.     while (i)
  540.     {
  541.         of << "\
  542. \n        case " << caseNum++ << ":\
  543. \n        {\
  544. ";
  545.         long keyOff = 0;
  546.         long forNum = 0;
  547.         for (int j=0; j<MAX_FIELDS_IN_INDEX && i->idxFields[j] != -1;  j++)
  548.         {
  549.             bool tab;
  550.             fieldInfo* f = fldList->fields;
  551.             for (int k=0; k < i->idxFields[j]; k++)
  552.             {
  553.                 f=f->nextFld;
  554.             }
  555.  
  556.             // Got the right field
  557.  
  558.             // If this is a CHAR type of more than one char (a string) then
  559.             // use strncpy to get the string. Makes things a little quicker.
  560.             // NB Earlier I commented about not worrying about efficiency of
  561.             // generate. This is true, however, the efficiency of the code that
  562.             // genarate produces is quite important.
  563.  
  564.             if ((f->fldType == D_CHAR || f->fldType == D_ICHAR) && f->fldSize != 1)
  565.                 if (isGet)
  566.                     of << "\
  567. \n            strNcpy(((_" << className << "_idxStr" << caseNum-1 << "*)buffer)->" << f->fldName << ", " << f->fldName << ", " << f->fldSize << ");\
  568. ";
  569.                 else
  570.                     of << "\
  571. \n            strNcpy(" << f->fldName << ", ((_" << className << "_idxStr" << caseNum-1 << "*)buffer)->" << f->fldName << ",  " << f->fldSize << ");\
  572. ";
  573.             else
  574.             {
  575.                 // If this is an array then we must loop around copying
  576.                 // each of the elements individually.
  577.                 // Why not use bcopy of the whole block? Because the code was
  578.                 // 50 times slower when we did that!
  579.  
  580.                 // Note that we use the variable a##forNum so that the loop
  581.                 // variables to not clash, given the unfortunate scope rules
  582.                 // of C++ and for loops.
  583.  
  584.                 if (f->fldSize != mySizeOf(f->fldType))
  585.                 {
  586.                     of << "\
  587. \n            for (int a" << forNum << "=0;a" << forNum << "<" << f->fldSize << ";a"
  588. << forNum++ << "+=" << mySizeOf(f->fldType) << ")\
  589. ";
  590.                     // The tab is just to make sure that things all line up
  591.                     // correctly in the generated code. We might as well make
  592.                     // things look good.
  593.  
  594.                     tab = true;
  595.                 }
  596.                 else
  597.                     tab = false;
  598.  
  599.                 if (isGet)
  600.                     of << "\
  601. \n        " << (tab?"\t":"") << " ((_" << className << "_idxStr" << caseNum-1 << "*)buffer)->" << f->fldName << " = " << f->fldName << ";";
  602.                 else
  603.                     of << "\
  604. \n        " << (tab?"\t":"") << " " << f->fldName << " = ((_" << className << "_idxStr" << caseNum-1 << "*)buffer)->" << f->fldName << ";";
  605.  
  606.             }
  607.  
  608.             // The offset into the key where we cast the data we want from
  609.             keyOff += f->fldSize;
  610.         }
  611.         of << "\
  612. \n            break;\
  613. \n        }\
  614. ";
  615.         i = i->nextIdx;
  616.     }
  617. }
  618.  
  619. // genCompareCases:
  620. // This does a simialr job to genGetSetCases except it's used for the
  621. // compare function.
  622.  
  623. void genCompareCases(ofstream& of, char* className, indexList* idxList, fieldList* fldList)
  624. {
  625.     indexInfo* i = idxList->indicies;
  626.     long caseNum = 0;
  627.  
  628.     while (i)
  629.     {
  630.         of << "\
  631. \n        case " << caseNum++ << ":\
  632. \n        {\
  633. ";
  634.         long keyOff = 0;
  635.         long forNum = 0;
  636.         for (int j=0; j<MAX_FIELDS_IN_INDEX && i->idxFields[j] != -1;  j++)
  637.         {
  638.             bool tab;
  639.             fieldInfo* f = fldList->fields;
  640.             for (int k=0; k < i->idxFields[j]; k++)
  641.                 f=f->nextFld;
  642.  
  643.             if (f->fldType == D_CHAR && f->fldSize != 1)
  644.                 of << "\
  645. \n            if (res=strncmp(" << f->fldName << ", ((_" << className << "_idxStr" << caseNum-1 << "*)key)->" << f->fldName << ", " << f->fldSize << "))\
  646. \n                break;\
  647. ";
  648.             else
  649.             if (f->fldType == D_ICHAR && f->fldSize != 1)
  650.                 of << "\
  651. \n            if (res=strncasecmp(" << f->fldName << ", ((_" << className << "_idxStr" << caseNum-1 << "*)key)->" << f->fldName << ", " << f->fldSize << "))\
  652. \n                break;\
  653. ";
  654.             else
  655.             {
  656.                 if (f->fldSize != mySizeOf(f->fldType))
  657.                 {
  658.                     of << "\
  659. \n            for (int a" << forNum << "=0;a" << forNum << "<" << f->fldSize << ";a"
  660. << forNum++ << "+=" << mySizeOf(f->fldType) << ")\
  661. ";
  662.                     tab = true;
  663.                 }
  664.                 else
  665.                     tab = false;
  666.  
  667.                 // We use the generated compare functions
  668.                 of << "\
  669. \n        " << (tab?"\t":"") << " if (res=compare_" << typeName(f->fldType) << "((char*)(&" << f->fldName << "), (char*)(&((_" << className << "_idxStr" << caseNum-1 << "*)key)->" << f->fldName << ")))\
  670. \n            " << (tab?"\t":"") << " goto end_compare;\
  671. ";
  672.             }
  673.             keyOff += f->fldSize;
  674.         }
  675.  
  676.         of << "\
  677. \n            break;\
  678. \n        }\
  679. ";
  680.         i = i->nextIdx;
  681.     }
  682.     of << "\
  683. \n#pragma warn .pia\
  684. ";
  685. }
  686.  
  687. // generateStart:
  688. // This starts off the generation process by forming the file names and
  689. // creating the relevant streams. It also outputs all the non-schema-depandant
  690. // stuff that starts each file.
  691.  
  692. bool generateStart(ofstream& hf, ofstream& cf, char* filename)
  693. {
  694.     char *s;
  695.     char *incname;
  696.     char *fle = strdup(filename);
  697.     char *file = fle;
  698.  
  699.     // Strip off all leading paths (Unix and PC style)
  700.  
  701.     if ((s=strrchr(file, '/')) != 0)
  702.         file= s+1;
  703.     if ((s=strrchr(file, '\\')) != 0)
  704.         file= s+1;
  705.  
  706.     incname = new char[strlen(filename)+5];
  707.     strcpy(incname, filename);
  708.     strcat(incname, ".h");
  709.  
  710.     hf.open(incname);
  711.     if (!hf)
  712.     {
  713.         // Couldn't open, clean up and go.
  714.         delete fle;
  715.         delete incname;
  716.         return false;
  717.     }
  718.  
  719.     char *codename = new char[strlen(filename)+6];
  720.     strcpy(codename, filename);
  721.     strcat(codename, ".cc");
  722.     cf.open(codename);
  723.     if (!cf)
  724.     {
  725.         delete fle;
  726.         delete incname;
  727.         delete codename;
  728.         return false;
  729.     }
  730.  
  731.     // The top of the include file
  732.     hf << "\
  733. \n//\
  734. \n// Include file for " << filename << ".s schema file.\
  735. \n//\
  736. \n// Automatically generated: Generator Revison $Rev$\
  737. \n//\
  738. \n\
  739. \n#ifndef __" << file << "_H_\
  740. \n#define __" << file << "_H_\
  741. \n\
  742. \n#include <diarel.h>\
  743. \n#include <utils.h>\
  744. \n\
  745. \n#include \"" << file << "_s.h\"\
  746. ";
  747.  
  748.     // The .cc class definition file.
  749.     // The ORD_COMPARE and REAL_COMPARE defines are used to declare COMPARE
  750.     // functions for each of our types. I leave them in here, and not in the
  751.     // library or somewhere else so that these files are fairly self
  752.     // contained.
  753.     //
  754.     // Hopefully, most compilers can inline these nicely for us.
  755.  
  756.     cf << "\
  757. \n//\
  758. \n// Class definition file for " << filename << ".s schema file.\
  759. \n//\
  760. \n// Automatically generated: Generator Revison $Rev$\
  761. \n//\
  762. \n\
  763. \n#include <iostream.h>\
  764. \n#include <stdlib.h>\
  765. \n#include <string.h>\
  766. \n#include <stdio.h>\
  767. \n#include <ctype.h>\
  768. \n#include \"" << file << ".h\"\
  769. \n\
  770. \nchar* strNcpy(char* d, char* s, int n);\
  771. \n#define ORD_COMPARE(t) \\\
  772. \n    inline long compare_##t(pKeyType k1, pKeyType k2) \\\
  773. \n    { \\\
  774. \n        t _t1 = *((t *)k1); \\\
  775. \n        t _t2 = *((t *)k2); \\\
  776. \n        return (_t1==_t2)?0:((_t1<_t2)?-1:1); \\\
  777. \n    } \
  778. \n\
  779. \n#define REAL_COMPARE(t) \\\
  780. \n    inline long compare_##t(pKeyType k1, pKeyType k2) \\\
  781. \n    { \\\
  782. \n        t _t1 = *((t *)k1); \\\
  783. \n        t _t2 = *((t *)k2); \\\
  784. \n        return (_t1==_t2)?0:((_t1<_t2)?-1:1); \\\
  785. \n    }\
  786. \n\
  787. \ninline long compare_ichar(pKeyType k1, pKeyType k2)\
  788. \n{\
  789. \n    char _t1 = tolower(*((char*)k1));\
  790. \n    char _t2 = tolower(*((char*)k2));\
  791. \n    return (_t1==_t2)?0:((_t1<_t2)?-1:1);\
  792. \n}\
  793. \n\
  794. \nORD_COMPARE(short);\
  795. \nORD_COMPARE(ushort);\
  796. \nORD_COMPARE(long);\
  797. \nORD_COMPARE(ulong);\
  798. \nORD_COMPARE(dateType);\
  799. \nORD_COMPARE(char);\
  800. \nORD_COMPARE(uniqueType);\
  801. \nREAL_COMPARE(float);\
  802. \nREAL_COMPARE(double);\
  803. \nREAL_COMPARE(moneyType);\
  804. ";
  805.  
  806.     // Clean up and go.
  807.     delete fle;
  808.     delete incname;
  809.     delete codename;
  810.     return true;
  811. }
  812.  
  813. // generateClass:
  814. // This does all the work generating a class. It uses all the above
  815. // functions to keep things neat (well, sort of neat anyway).
  816.  
  817. bool generateClass(ofstream& hf, ofstream& cf, long recLen, indexList* idxList, fieldList* fldList, char* structName, char* className, int stringCount, indexList* consList, char** defaults)
  818. {
  819.     if (!hf) return false;
  820.  
  821.     hf << "\
  822. \n//\
  823. \n// Declaration of class for " << className << "\
  824. \n//\
  825. ";
  826.     genStructs(hf, className, idxList, fldList);
  827.     hf << "\
  828. \n\
  829. \nclass " << className << " : \
  830. \n        public diaRel,\
  831. \n        public " << structName;
  832.     if (stringCount)
  833.         hf << ",\
  834. \n        public _Strings_" << structName << "\
  835. ";
  836.     hf << "\
  837. \n{\
  838. \npublic:\
  839. \n\
  840. \n    inline virtual operator void*() { return (void*)((" << structName << "*)this); }\
  841. \n    inline virtual operator char*() { return (char*)((" << structName << "*)this); }\
  842. \n    inline virtual char* theData() { return (char*)((" << structName << "*)this); }\
  843. \n    inline virtual long getDataLength(void) { return " << recLen << "; };\
  844. \n#ifndef __CC\
  845. \ninline\
  846. \n#endif\
  847. \n        virtual long getKeyLength(long keyNum=0);\
  848. \n    inline virtual pKeyType getKey(long keyNum=0);\
  849. \n    virtual long compare(pKeyType key, long keyNum=0);\
  850. ";
  851.     bool voidCons = FALSE;
  852.     genConsDecls(hf, className, fldList, consList, voidCons);
  853.     if (!voidCons)
  854.         hf << "\
  855. \n    " << className << "();\
  856. ";
  857.     hf << "\
  858. \n    " << className << "(pKeyType newKey, long keyNum);\
  859. \n    " << className << "& operator=(" << className << "& X);\
  860. \n    void commonInit(void);\
  861. \n    void setKey(pKeyType newKey, long keyNum=0);\
  862. \n    long getUnique(void) { ";
  863.     genUnique(hf, fldList, 1);
  864.     hf << " }\
  865. \n    bool hasUnique(void) { ";
  866.     genUnique(hf, fldList, 2);
  867.     hf << " }\
  868. \n    void setUnique(long uniq) { ";
  869.     genUnique(hf, fldList, 0);
  870.     hf << " }\
  871. \n    bool isUnique(long keyNum=0);\
  872. \n    long numStrings(void) { return " << stringCount << "; }\
  873. ";
  874.     if (stringCount)
  875.         hf << "\
  876. \n    _db_strStruct strArray[" << stringCount << "];\
  877. \n    dbData* getString(long num) { return strArray[num].theString; }\
  878. \n    long* getLong(long num) { return strArray[num].theLong; }\
  879. ";
  880.     hf << "\
  881. \n    _db_strStruct* getArray(void) { return \
  882. ";
  883.     hf << (stringCount?"strArray":"0") << ";}\
  884. \n    operator dbError();\
  885. \n    char* verStr(void) { return \"$Id: generate.cc,v 1.45 1993/11/05 12:45:05 kevinl Exp $\"; }\
  886. \n};\
  887. ";
  888.  
  889.     if (!cf) return false;
  890.  
  891.     cf << "\
  892. \n\
  893. \n//\
  894. \n// Definitions for class " << structName << "\
  895. \n//\
  896. \nvoid " << className << "::commonInit(void)\
  897. \n{\
  898. \n    memset((" << structName << "*)this, 0, sizeof(" << structName << "));\
  899. \n    setUnique(-1);\
  900. ";
  901.     int i=0,j=0;
  902.     for (fieldInfo *f = fldList->fields; f; f=f->nextFld, j++) {
  903.         if (defaults[j])
  904.             if ((f->fldType == D_CHAR || f->fldType == D_ICHAR) && f->fldSize != 1)
  905.                 cf << "\
  906. \n    strNcpy(" << f->fldName << ", " << defaults[i] << ", " << f->fldSize << ");\
  907. ";
  908.             else
  909.                 cf << "\
  910. \n    " << f->fldName << " =" << defaults[j] << ";";
  911.  
  912.         if (f->fldType == D_STRING || f->fldType == D_DATA)
  913.             cf << "\
  914. \n    _off_" << f->fldName << "=0;\
  915. \n    strArray[" << i++ << "] = _db_strStruct(&_off_" << f->fldName << ",&" << f->fldName << ");\
  916. ";
  917.     }
  918.     cf << "\
  919. \n}\
  920. \n\
  921. ";
  922.     genConsDefns(cf, className, structName, fldList, consList);
  923.     if (!voidCons)
  924.         cf << "\
  925. \n" << className << "::" << className << "() : diaRel(\"" << className << "\")," << structName << "()\
  926. \n{\
  927. \n    commonInit();\
  928. \n}\
  929. ";
  930.     cf << "\
  931. \n\
  932. \n" << className << "::" << className << "(pKeyType newKey, long numKey) : diaRel(\"" << className << "\"), " << structName << "()\
  933. \n{\
  934. \n    commonInit();\
  935. \n    setKey(newKey, numKey);\
  936. \n}\
  937. \n\
  938. \n" << className << "& " << className << "::operator=(" << className << "& X)\
  939. \n{\
  940. \n    if (&X != this) {\
  941. \n        diaRel::operator=(X);\
  942. \n        (" << structName << ")(*this) = (" << structName << ")(X);\
  943. \n    }\
  944. \n    return *this;\
  945. \n}\
  946. \n\
  947. \nbool " << className << "::isUnique(long keyNum)\
  948. \n{\
  949. \n    static const bool uniqueFields[" << idxList->numIndicies << "] = {";
  950.  
  951.     genUniqueArray(cf, idxList, fldList);
  952.  
  953.     cf << "};\
  954. \n    if (keyNum==-1)\
  955. \n        return false;\
  956. \n    else\
  957. \n        return uniqueFields[keyNum];\
  958. \n}\
  959. \n\
  960. \nlong " << className << "::getKeyLength(long keyNum)\
  961. \n{\
  962. \n    static const long keyLengths[" << idxList->numIndicies << "] = {";
  963.  
  964.     genArray(cf, className, idxList);
  965.  
  966.     cf << "};\
  967. \n    if (keyNum==-1)\
  968. \n        return 0;\
  969. \n    else\
  970. \n        return keyLengths[keyNum];\
  971. \n}\
  972. \n\
  973. \npKeyType " << className << "::getKey(long keyNum)\
  974. \n{\
  975. \n    char* buffer = new char[getKeyLength(keyNum)];\
  976. \n\
  977. \n    switch (keyNum)\
  978. \n    {";
  979.  
  980.     genGetSetCases(cf, className, idxList, fldList, true);
  981.  
  982.     cf << "\
  983. \n    }\
  984. \n    return (pKeyType)buffer;\
  985. \n}\
  986. \n\
  987. \nvoid " << className << "::setKey(pKeyType buffer, long keyNum)\
  988. \n{\
  989. \n    switch (keyNum)\
  990. \n    {";
  991.  
  992.     genGetSetCases(cf, className, idxList, fldList, false);
  993.  
  994.     cf << "\
  995. \n    }\
  996. \n}\
  997. \n\
  998. \n" << className << "::operator dbError()\
  999. \n{\
  1000. \n    return status;\
  1001. \n}\
  1002. \n\
  1003. \nlong " << className << "::compare(pKeyType key, long keyNum)\
  1004. \n{\
  1005. \n    //char* myKey = (char*)getKey(keyNum);\
  1006. \n    long res=0;\
  1007. \n\
  1008. \n    switch (keyNum)\
  1009. \n    {\
  1010. \n#pragma warn -pia\
  1011. ";
  1012.     genCompareCases(cf, className, idxList, fldList);
  1013.  
  1014.     cf << "\
  1015. \n    }\
  1016. \n\
  1017. \nend_compare:\
  1018. \n\
  1019. \n    //delete myKey;\
  1020. \n    return res;\
  1021. \n}\
  1022. ";
  1023.     return true;
  1024. }
  1025.  
  1026. // generateEnd:
  1027. // End off the include file and close the streams.
  1028.  
  1029. bool generateEnd(ofstream& hf, ofstream& cf)
  1030. {
  1031.     if (!hf) return false;
  1032.     if (!cf) return false;
  1033.  
  1034.     hf << "\
  1035. \n\
  1036. \n#endif\
  1037. ";
  1038.     hf.close();
  1039.     cf.close();
  1040.     return true;
  1041. }
  1042.  
  1043. void genDeriveCons(ofstream& of, dbString base, dbString derive, fieldList* fldList, indexList* consList, bool doCode)
  1044. {
  1045.     indexInfo* c = consList->indicies;
  1046.  
  1047.     while (c)
  1048.     {
  1049.         if (doCode)
  1050.             of << "\
  1051. \n" << derive << "::" << derive << "(";
  1052.         else
  1053.             of << "\
  1054. \n    " << derive << "(";
  1055.  
  1056.     for (int j=0; j<MAX_FIELDS_IN_INDEX && c->idxFields[j] != -1;  j++)
  1057.     {
  1058.         fieldInfo* f = fldList->fields;
  1059.         for (int k=0; k < c->idxFields[j]; k++)
  1060.         f=f->nextFld;
  1061.             if (j)
  1062.                 of << ", ";
  1063.             of << typeName(f->fldType);
  1064.             if (f->fldSize != mySizeOf(f->fldType))
  1065.                 of << "*";
  1066.             of << " _cons_" << f->fldName;
  1067.     }
  1068.  
  1069.         of << ")";
  1070.  
  1071.         if (doCode)
  1072.         {
  1073.             of << " : " << base << "(";
  1074.             for (j=0; j<MAX_FIELDS_IN_INDEX && c->idxFields[j] != -1;  j++)
  1075.             {
  1076.                 fieldInfo* f = fldList->fields;
  1077.                 for (int k=0; k < c->idxFields[j]; k++)
  1078.                     f=f->nextFld;
  1079.                 if (j)
  1080.                     of << ", ";
  1081.                 of << " _cons_" << f->fldName;
  1082.             }
  1083.             of << ")\
  1084. \n{\
  1085. \n    // Something in here would be nice\
  1086. \n}\
  1087. \n\
  1088. ";
  1089.         }
  1090.         else
  1091.         {
  1092.             of << ";";
  1093.         }
  1094.  
  1095.     c=c->nextIdx;
  1096.     }
  1097. }
  1098.  
  1099. bool
  1100. generateDerived(dbString base, dbString derive, dbString deriveName, fieldList* fldList, indexList* consList)
  1101. {
  1102.     dbString s;
  1103.     s = deriveName + ".h";
  1104.     ofstream hf(s);
  1105.     s = deriveName + ".cc";
  1106.     ofstream cf(s);
  1107.  
  1108.     cf << "\
  1109. \n//\
  1110. \n// Derived class " << derive << " from base class " << base << ".\
  1111. \n// Generated by DiamondBase\
  1112. \n// $Id: generate.cc,v 1.45 1993/11/05 12:45:05 kevinl Exp $\
  1113. \n\
  1114. ";
  1115.  
  1116.     hf << "\
  1117. \n//\
  1118. \n// Derived class " << derive << " from base class " << base << ".\
  1119. \n// Generated by DiamondBase\
  1120. \n// $Id: generate.cc,v 1.45 1993/11/05 12:45:05 kevinl Exp $\
  1121. \n\
  1122. \nclass " << derive << " : public " << base << "{\
  1123. ";
  1124.     genDeriveCons(hf, base, derive, fldList, consList, false);
  1125.     genDeriveCons(cf, base, derive, fldList, consList, true);
  1126.  
  1127.     hf << "\
  1128. \n};\
  1129. ";
  1130.     return true;
  1131. }
  1132.