VPR-6.0
|
00001 #include <assert.h> 00002 #include <stdio.h> 00003 #include <stdlib.h> 00004 #include <string.h> 00005 #include "util.h" 00006 #include "ezxml.h" 00007 #include "read_xml_util.h" 00008 00009 /** Finds child element with given name and returns it. Errors out if 00010 * more than one instance exists. */ 00011 ezxml_t 00012 FindElement(INP ezxml_t Parent, INP const char *Name, INP boolean Required) 00013 { 00014 ezxml_t Cur; 00015 00016 /* Find the first node of correct name */ 00017 Cur = ezxml_child(Parent, Name); 00018 00019 /* Error out if node isn't found but they required it */ 00020 if(Required) 00021 { 00022 if(NULL == Cur) 00023 { 00024 printf(ERRTAG 00025 "[LINE %d] Element '%s' not found within element '%s'.\n", Parent->line, 00026 Name, Parent->name); 00027 exit(1); 00028 } 00029 } 00030 00031 /* Look at next tag with same name and error out if exists */ 00032 if(Cur != NULL && Cur->next) 00033 { 00034 printf(ERRTAG "[LINE %d] Element '%s' found twice within element '%s'.\n", Parent->line, 00035 Name, Parent->name); 00036 exit(1); 00037 } 00038 return Cur; 00039 } 00040 /** Finds child element with given name and returns it. */ 00041 ezxml_t 00042 FindFirstElement(INP ezxml_t Parent, INP const char *Name, INP boolean Required) 00043 { 00044 ezxml_t Cur; 00045 00046 /* Find the first node of correct name */ 00047 Cur = ezxml_child(Parent, Name); 00048 00049 /* Error out if node isn't found but they required it */ 00050 if(Required) 00051 { 00052 if(NULL == Cur) 00053 { 00054 printf(ERRTAG 00055 "[LINE %d] Element '%s' not found within element '%s'.\n", Parent->line, 00056 Name, Parent->name); 00057 exit(1); 00058 } 00059 } 00060 00061 return Cur; 00062 } 00063 00064 00065 /** Checks the node is an element with name equal to one given */ 00066 void 00067 CheckElement(INP ezxml_t Node, INP const char *Name) 00068 { 00069 assert(Node != NULL && Name != NULL); 00070 if(0 != strcmp(Node->name, Name)) 00071 { 00072 printf(ERRTAG 00073 "[LINE %d] Element '%s' within element '%s' does match expected " 00074 "element type of '%s'\n", Node->line, Node->name, Node->parent->name, 00075 Name); 00076 exit(1); 00077 } 00078 } 00079 00080 /** Checks that the node has no remaining child nodes or property nodes, 00081 * then unlinks the node from the tree which updates pointers and 00082 * frees the memory 00083 */ 00084 void 00085 FreeNode(INOUTP ezxml_t Node) 00086 { 00087 ezxml_t Cur; 00088 char *Txt; 00089 00090 00091 /* Shouldn't have unprocessed properties */ 00092 if(Node->attr[0]) 00093 { 00094 printf(ERRTAG "[LINE %d] Node '%s' has invalid property %s=\"%s\".\n", Node->line, 00095 Node->name, Node->attr[0], Node->attr[1]); 00096 exit(1); 00097 } 00098 00099 /* Shouldn't have non-whitespace text */ 00100 Txt = Node->txt; 00101 while(*Txt) 00102 { 00103 if(!IsWhitespace(*Txt)) 00104 { 00105 printf(ERRTAG 00106 "[LINE %d] Node '%s' has unexpected text '%s' within it.\n", Node->line, 00107 Node->name, Node->txt); 00108 exit(1); 00109 } 00110 ++Txt; 00111 } 00112 00113 /* We shouldn't have child items left */ 00114 Cur = Node->child; 00115 if(Cur) 00116 { 00117 printf(ERRTAG "[LINE %d] Node '%s' has invalid child node '%s'.\n", Node->line, 00118 Node->name, Cur->name); 00119 exit(1); 00120 } 00121 00122 /* Now actually unlink and free the node */ 00123 ezxml_remove(Node); 00124 } 00125 00126 /** Returns TRUE if character is whatspace between tokens */ 00127 boolean 00128 IsWhitespace(char c) 00129 { 00130 switch (c) 00131 { 00132 case ' ': 00133 case '\t': 00134 case '\r': 00135 case '\n': 00136 return TRUE; 00137 default: 00138 return FALSE; 00139 } 00140 } 00141 00142 const char * 00143 FindProperty(INP ezxml_t Parent, INP const char *Name, INP boolean Required) 00144 { 00145 const char *Res; 00146 00147 Res = ezxml_attr(Parent, Name); 00148 if(Required) 00149 { 00150 if(NULL == Res) 00151 { 00152 printf(ERRTAG 00153 "[Line %d] Required property '%s' not found for element '%s'.\n", Parent->line, 00154 Name, Parent->name); 00155 exit(1); 00156 } 00157 } 00158 return Res; 00159 } 00160 00161 00162 00163 /** Count tokens and length in all the Text children nodes of current node. */ 00164 extern void 00165 CountTokensInString(INP const char *Str, OUTP int *Num, OUTP int *Len) 00166 { 00167 boolean InToken; 00168 *Num = 0; 00169 *Len = 0; 00170 InToken = FALSE; 00171 while(*Str) 00172 { 00173 if(IsWhitespace(*Str)) 00174 { 00175 InToken = FALSE; 00176 } 00177 00178 else 00179 00180 { 00181 if(!InToken) 00182 { 00183 ++(*Num); 00184 } 00185 ++(*Len); 00186 InToken = TRUE; 00187 } 00188 ++Str; /* Advance pointer */ 00189 } 00190 } 00191 00192 /** Returns a token list of the text nodes of a given node. This 00193 * unlinks all the text nodes from the document */ 00194 extern char ** 00195 GetNodeTokens(INP ezxml_t Node) 00196 { 00197 int Count, Len; 00198 char *Cur, *Dst; 00199 boolean InToken; 00200 char **Tokens; 00201 00202 00203 /* Count the tokens and find length of token data */ 00204 CountTokensInString(Node->txt, &Count, &Len); 00205 00206 /* Error out if no tokens found */ 00207 if(Count < 1) 00208 { 00209 return NULL; 00210 } 00211 Len = (sizeof(char) * Len) + /* Length of actual data */ 00212 (sizeof(char) * Count); /* Null terminators */ 00213 00214 /* Alloc the pointer list and data list. Count the final 00215 * empty string we will use as list terminator */ 00216 Tokens = (char **)my_malloc(sizeof(char *) * (Count + 1)); 00217 Dst = (char *)my_malloc(sizeof(char) * Len); 00218 Count = 0; 00219 00220 /* Copy data to tokens */ 00221 Cur = Node->txt; 00222 InToken = FALSE; 00223 while(*Cur) 00224 { 00225 if(IsWhitespace(*Cur)) 00226 { 00227 if(InToken) 00228 { 00229 *Dst = '\0'; 00230 ++Dst; 00231 } 00232 InToken = FALSE; 00233 } 00234 00235 else 00236 { 00237 if(!InToken) 00238 { 00239 Tokens[Count] = Dst; 00240 ++Count; 00241 } 00242 *Dst = *Cur; 00243 ++Dst; 00244 InToken = TRUE; 00245 } 00246 ++Cur; 00247 } 00248 if(InToken) 00249 { /* Null term final token */ 00250 *Dst = '\0'; 00251 ++Dst; 00252 } 00253 ezxml_set_txt(Node, ""); 00254 Tokens[Count] = NULL; /* End of tokens marker is a NULL */ 00255 00256 /* Return the list */ 00257 return Tokens; 00258 } 00259 00260 00261 /** Returns a token list of the text nodes of a given node. This 00262 * does not unlink the text nodes from the document */ 00263 extern char ** 00264 LookaheadNodeTokens(INP ezxml_t Node) 00265 { 00266 int Count, Len; 00267 char *Cur, *Dst; 00268 boolean InToken; 00269 char **Tokens; 00270 00271 00272 /* Count the tokens and find length of token data */ 00273 CountTokensInString(Node->txt, &Count, &Len); 00274 00275 /* Error out if no tokens found */ 00276 if(Count < 1) 00277 { 00278 return NULL; 00279 } 00280 Len = (sizeof(char) * Len) + /* Length of actual data */ 00281 (sizeof(char) * Count); /* Null terminators */ 00282 00283 /* Alloc the pointer list and data list. Count the final 00284 * empty string we will use as list terminator */ 00285 Tokens = (char **)my_malloc(sizeof(char *) * (Count + 1)); 00286 Dst = (char *)my_malloc(sizeof(char) * Len); 00287 Count = 0; 00288 00289 /* Copy data to tokens */ 00290 Cur = Node->txt; 00291 InToken = FALSE; 00292 while(*Cur) 00293 { 00294 if(IsWhitespace(*Cur)) 00295 { 00296 if(InToken) 00297 { 00298 *Dst = '\0'; 00299 ++Dst; 00300 } 00301 InToken = FALSE; 00302 } 00303 00304 else 00305 { 00306 if(!InToken) 00307 { 00308 Tokens[Count] = Dst; 00309 ++Count; 00310 } 00311 *Dst = *Cur; 00312 ++Dst; 00313 InToken = TRUE; 00314 } 00315 ++Cur; 00316 } 00317 if(InToken) 00318 { /* Null term final token */ 00319 *Dst = '\0'; 00320 ++Dst; 00321 } 00322 Tokens[Count] = NULL; /* End of tokens marker is a NULL */ 00323 00324 /* Return the list */ 00325 return Tokens; 00326 } 00327 00328 /** Find integer attribute matching Name in XML tag Parent and return it if exists. 00329 Removes attribute from Parent */ 00330 extern int GetIntProperty(INP ezxml_t Parent, 00331 INP const char *Name, 00332 INP boolean Required, 00333 INP int default_value) 00334 { 00335 const char * Prop; 00336 int property_value; 00337 00338 property_value = default_value; 00339 Prop = FindProperty(Parent, Name, Required); 00340 if(Prop) 00341 { 00342 property_value = my_atoi(Prop); 00343 ezxml_set_attr(Parent, Name, NULL); 00344 } 00345 return property_value; 00346 } 00347 00348 /** Find floating-point attribute matching Name in XML tag Parent and return it if exists. 00349 Removes attribute from Parent */ 00350 extern float GetFloatProperty(INP ezxml_t Parent, 00351 INP const char *Name, 00352 INP boolean Required, 00353 INP float default_value) 00354 { 00355 00356 const char * Prop; 00357 float property_value; 00358 00359 property_value = default_value; 00360 Prop = FindProperty(Parent, Name, Required); 00361 if(Prop) 00362 { 00363 property_value = atof(Prop); 00364 ezxml_set_attr(Parent, Name, NULL); 00365 } 00366 return property_value; 00367 } 00368 00369 /** Find boolean attribute matching Name in XML tag Parent and return it if exists. 00370 Removes attribute from Parent */ 00371 extern boolean GetBooleanProperty(INP ezxml_t Parent, 00372 INP const char *Name, 00373 INP boolean Required, 00374 INP boolean default_value) 00375 { 00376 00377 const char * Prop; 00378 boolean property_value; 00379 00380 property_value = default_value; 00381 Prop = FindProperty(Parent, Name, Required); 00382 if(Prop) 00383 { 00384 if((strcmp(Prop, "false") == 0) || 00385 (strcmp(Prop, "FALSE") == 0) || 00386 (strcmp(Prop, "False") == 0)) { 00387 property_value = FALSE; 00388 } else if ((strcmp(Prop, "true") == 0) || 00389 (strcmp(Prop, "TRUE") == 0) || 00390 (strcmp(Prop, "True") == 0)) { 00391 property_value = TRUE; 00392 } else { 00393 printf(ERRTAG "[LINE %d] Unknown value %s for boolean attribute %s in %s", Parent->line, 00394 Prop, Name, Parent->name); 00395 exit(1); 00396 } 00397 ezxml_set_attr(Parent, Name, NULL); 00398 } 00399 return property_value; 00400 } 00401 00402 00403 /** Counts number of child elements in a container element. 00404 * Name is the name of the child element. 00405 * Errors if no occurances found. */ 00406 extern int 00407 CountChildren(INP ezxml_t Node, INP const char *Name, INP int min_count) 00408 { 00409 ezxml_t Cur, sibling; 00410 int Count; 00411 00412 Count = 0; 00413 Cur = Node->child; 00414 sibling = NULL; 00415 00416 if(Cur) 00417 { 00418 sibling = Cur->sibling; 00419 } 00420 00421 while(Cur) 00422 { 00423 if(strcmp(Cur->name, Name) == 0) 00424 { 00425 ++Count; 00426 } 00427 Cur = Cur->next; 00428 if(Cur == NULL) 00429 { 00430 Cur = sibling; 00431 if(Cur != NULL) 00432 { 00433 sibling = Cur->sibling; 00434 } 00435 } 00436 } 00437 /* Error if no occurances found */ 00438 if(Count < min_count) 00439 { 00440 printf(ERRTAG "[Line %d] Expected node '%s' to have %d " 00441 "child elements, but none found.\n", Node->line, Node->name, min_count); 00442 exit(1); 00443 } 00444 return Count; 00445 } 00446 00447