00001
00002
00003 #include "common.h"
00004 #include "linefile.h"
00005 #include "tokenizer.h"
00006 #include "asParse.h"
00007
00008 static char const rcsid[] = "$Id: asParse.c,v 1.6 2007/02/11 21:43:15 kent Exp $";
00009
00010
00011
00012
00013
00014
00015 struct asTypeInfo asTypes[] = {
00016 {t_double, "double", FALSE, FALSE, "double", "double", "Double", "Double", "%g"},
00017 {t_float, "float", FALSE, FALSE, "float", "float", "Float", "Float", "%g"},
00018 {t_char, "char", FALSE, FALSE, "char", "char", "Char", "Char", "%c"},
00019 {t_int, "int", FALSE, FALSE, "int", "int", "Signed", "Signed", "%d"},
00020 {t_uint, "uint", TRUE, FALSE, "int unsigned", "unsigned", "Unsigned","Unsigned", "%u"},
00021 {t_short, "short", FALSE, FALSE, "smallint", "short", "Short", "Signed", "%d"},
00022 {t_ushort, "ushort", TRUE, FALSE, "smallint unsigned","unsigned short","Ushort", "Unsigned", "%u"},
00023 {t_byte, "byte", FALSE, FALSE, "tinyint", "signed char", "Byte", "Signed", "%d"},
00024 {t_ubyte, "ubyte", TRUE, FALSE, "tinyint unsigned", "unsigned char", "Ubyte", "Unsigned", "%u"},
00025 {t_off, "bigint", FALSE, FALSE,"bigint", "long long", "LongLong", "LongLong", "%lld"},
00026 {t_string, "string", FALSE, TRUE, "varchar(255)", "char *", "String", "String", "%s"},
00027 {t_lstring, "lstring", FALSE, TRUE, "longblob", "char *", "String", "String", "%s"},
00028 {t_enum, "enum", FALSE, FALSE, "enum", "!error!", "Enum", "Enum", NULL},
00029 {t_set, "set", FALSE, FALSE, "set", "unsigned", "Set", "Set", NULL},
00030 {t_object, "object", FALSE, FALSE, "longblob", "!error!", "Object", "Object", NULL},
00031 {t_object, "table", FALSE, FALSE, "longblob", "!error!", "Object", "Object", NULL},
00032 {t_simple, "simple", FALSE, FALSE, "longblob", "!error!", "Simple", "Simple", NULL},
00033 };
00034
00035 static struct asTypeInfo *findLowType(struct tokenizer *tkz)
00036
00037
00038 {
00039 char *s = tkz->string;
00040 int i;
00041 for (i=0; i<ArraySize(asTypes); ++i)
00042 {
00043 if (sameWord(asTypes[i].name, s))
00044 return &asTypes[i];
00045 }
00046 tokenizerErrAbort(tkz, "Unknown type '%s'", s);
00047 return NULL;
00048 }
00049
00050 static struct asColumn *mustFindColumn(struct asObject *table, char *colName)
00051
00052 {
00053 struct asColumn *col;
00054
00055 for (col = table->columnList; col != NULL; col = col->next)
00056 {
00057 if (sameWord(col->name, colName))
00058 return col;
00059 }
00060 errAbort("Couldn't find column %s", colName);
00061 return NULL;
00062 }
00063
00064 static struct asObject *findObType(struct asObject *objList, char *obName)
00065
00066 {
00067 struct asObject *obj;
00068 for (obj = objList; obj != NULL; obj = obj->next)
00069 {
00070 if (sameWord(obj->name, obName))
00071 return obj;
00072 }
00073 return NULL;
00074 }
00075
00076 static void asParseColArraySpec(struct tokenizer *tkz, struct asObject *obj,
00077 struct asColumn *col)
00078
00079 {
00080 if (col->lowType->type == t_simple)
00081 col->isArray = TRUE;
00082 else
00083 col->isList = TRUE;
00084 tokenizerMustHaveNext(tkz);
00085 if (isdigit(tkz->string[0]))
00086 {
00087 col->fixedSize = atoi(tkz->string);
00088 tokenizerMustHaveNext(tkz);
00089 }
00090 else if (isalpha(tkz->string[0]))
00091 {
00092 #ifdef OLD
00093 if (obj->isSimple)
00094 tokenizerErrAbort(tkz, "simple objects can't include variable length arrays\n");
00095 #endif
00096 col->linkedSizeName = cloneString(tkz->string);
00097 col->linkedSize = mustFindColumn(obj, col->linkedSizeName);
00098 col->linkedSize->isSizeLink = TRUE;
00099 tokenizerMustHaveNext(tkz);
00100 }
00101 else
00102 tokenizerErrAbort(tkz, "must have column name or integer inside []'s\n");
00103 tokenizerMustMatch(tkz, "]");
00104 }
00105
00106 static void asParseColSymSpec(struct tokenizer *tkz, struct asObject *obj,
00107 struct asColumn *col)
00108
00109 {
00110 tokenizerMustHaveNext(tkz);
00111 while (tkz->string[0] != ')')
00112 {
00113 slSafeAddHead(&col->values, slNameNew(tkz->string));
00114
00115 tokenizerMustHaveNext(tkz);
00116 if (!((tkz->string[0] == ',') || (tkz->string[0] == ')')))
00117 tokenizerErrAbort(tkz, "expected `,' or `)' got `%s'", tkz->string);
00118 if (tkz->string[0] != ')')
00119 tokenizerMustHaveNext(tkz);
00120 }
00121 tokenizerMustMatch(tkz, ")");
00122 slReverse(&col->values);
00123 }
00124
00125 static void asParseColDef(struct tokenizer *tkz, struct asObject *obj)
00126
00127 {
00128 struct asColumn *col;
00129 AllocVar(col);
00130
00131 col->lowType = findLowType(tkz);
00132 tokenizerMustHaveNext(tkz);
00133
00134 if (col->lowType->type == t_object || col->lowType->type == t_simple)
00135 {
00136 col->obName = cloneString(tkz->string);
00137 tokenizerMustHaveNext(tkz);
00138 }
00139
00140 if (tkz->string[0] == '[')
00141 asParseColArraySpec(tkz, obj, col);
00142 else if (tkz->string[0] == '(')
00143 asParseColSymSpec(tkz, obj, col);
00144
00145 col->name = cloneString(tkz->string);
00146 tokenizerMustHaveNext(tkz);
00147 tokenizerMustMatch(tkz, ";");
00148 col->comment = cloneString(tkz->string);
00149 tokenizerMustHaveNext(tkz);
00150 if (col->lowType->type == t_char && col->fixedSize != 0)
00151 col->isList = FALSE;
00152 slAddHead(&obj->columnList, col);
00153 }
00154
00155 static struct asObject *asParseTableDef(struct tokenizer *tkz)
00156
00157 {
00158 struct asObject *obj;
00159 AllocVar(obj);
00160 if (sameWord(tkz->string, "table"))
00161 obj->isTable = TRUE;
00162 else if (sameWord(tkz->string, "simple"))
00163 obj->isSimple = TRUE;
00164 else if (sameWord(tkz->string, "object"))
00165 ;
00166 else
00167 tokenizerErrAbort(tkz, "Expecting 'table' or 'object' got '%s'", tkz->string);
00168 tokenizerMustHaveNext(tkz);
00169 obj->name = cloneString(tkz->string);
00170 tokenizerMustHaveNext(tkz);
00171 obj->comment = cloneString(tkz->string);
00172
00173
00174 tokenizerMustHaveNext(tkz);
00175 tokenizerMustMatch(tkz, "(");
00176 while (tkz->string[0] != ')')
00177 asParseColDef(tkz, obj);
00178 slReverse(&obj->columnList);
00179 return obj;
00180 }
00181
00182 static void asLinkEmbeddedObjects(struct asObject *obj, struct asObject *objList)
00183
00184 {
00185 struct asColumn *col;
00186 for (col = obj->columnList; col != NULL; col = col->next)
00187 {
00188 if (col->obName != NULL)
00189 {
00190 if ((col->obType = findObType(objList, col->obName)) == NULL)
00191 errAbort("%s used but not defined", col->obName);
00192 if (obj->isSimple)
00193 {
00194 if (!col->obType->isSimple)
00195 errAbort("Simple object %s with embedded non-simple object %s",
00196 obj->name, col->name);
00197 }
00198 }
00199 }
00200 }
00201
00202 static struct asObject *asParseTokens(struct tokenizer *tkz)
00203
00204 {
00205 struct asObject *objList = NULL;
00206 struct asObject *obj;
00207
00208 while (tokenizerNext(tkz))
00209 {
00210 obj = asParseTableDef(tkz);
00211 if (findObType(objList, obj->name))
00212 tokenizerErrAbort(tkz, "Duplicate definition of %s", obj->name);
00213 slAddTail(&objList, obj);
00214 }
00215
00216 for (obj = objList; obj != NULL; obj = obj->next)
00217 asLinkEmbeddedObjects(obj, objList);
00218
00219 return objList;
00220 }
00221
00222 static struct asObject *asParseLineFile(struct lineFile *lf)
00223
00224 {
00225 struct tokenizer *tkz = tokenizerOnLineFile(lf);
00226 struct asObject *objList = asParseTokens(tkz);
00227 tokenizerFree(&tkz);
00228 return objList;
00229 }
00230
00231 struct asObject *asParseFile(char *fileName)
00232
00233 {
00234 return asParseLineFile(lineFileOpen(fileName, TRUE));
00235 }
00236
00237
00238 struct asObject *asParseText(char *text)
00239
00240 {
00241 char *dupe = cloneString(text);
00242 struct lineFile *lf = lineFileOnString("text", TRUE, dupe);
00243 struct asObject *objList = asParseLineFile(lf);
00244 return objList;
00245 }
00246