00001
00045 #include <stdlib.h>
00046 #include <stdio.h>
00047 #include <string.h>
00048 #include <ctype.h>
00049 #include <float.h>
00050 #include <sys/types.h>
00051 #include <sys/stat.h>
00052 #include <math.h>
00053
00054 #ifdef WIN32
00055 typedef struct _stat STAT;
00056 #define FSTAT _fstat
00057 #define tzset _tzset
00058 #define snprintf _snprintf
00059 #else
00060 #include <unistd.h>
00061 typedef struct stat STAT;
00062 #define FSTAT fstat
00063 #endif
00064
00065 #define QNAN (sqrt(-1))
00066
00067 #include "object.h"
00068 #include "load.h"
00069 #include "output.h"
00070 #include "random.h"
00071 #include "convert.h"
00072
00073 static unsigned int linenum=0;
00074 static char filename[1024];
00075
00076 static char *format_object(char *classname, int id)
00077 {
00078 static char256 buffer;
00079 strcpy(buffer,"(unidentified)");
00080 sprintf(buffer,global_object_format,classname,id);
00081 return buffer;
00082 }
00083
00084 static OBJECT **object_index = NULL;
00085 static unsigned char *object_linked = NULL;
00086 static unsigned int object_index_size = 65536;
00087 STATUS load_set_index(OBJECT *obj, OBJECTNUM id)
00088 {
00089 if (object_index==NULL)
00090 {
00091 object_index = malloc(sizeof(OBJECT*)*object_index_size);
00092 memset(object_index,0,sizeof(OBJECT*)*object_index_size);
00093 object_linked = malloc(sizeof(unsigned char)*object_index_size);
00094 memset(object_linked,0,sizeof(unsigned char)*object_index_size);
00095 }
00096 if (id>=object_index_size)
00097 {
00098 int new_size = (id/object_index_size+1)*object_index_size;
00099 object_index = realloc(object_index,sizeof(OBJECT*)*new_size);
00100 memset(object_index+object_index_size,0,sizeof(OBJECT*)*object_index_size);
00101 object_linked = realloc(object_linked,sizeof(unsigned char)*new_size);
00102 memset(object_linked+object_index_size,0,sizeof(unsigned char)*object_index_size);
00103 object_index_size = new_size;
00104 }
00105 if (object_index==NULL) { errno = ENOMEM; return FAILED;}
00106
00107 object_index[id] = obj;
00108 object_linked[id] = 0;
00109 return SUCCESS;
00110 }
00111 OBJECT *load_get_index(OBJECTNUM id)
00112 {
00113 if (object_index==NULL || id<0 || id>=object_index_size)
00114 return NULL;
00115 object_linked[id]++;
00116 return object_index[id];
00117 }
00118 static OBJECT *get_next_unlinked(CLASS *oclass)
00119 {
00120 unsigned int id;
00121 if (object_index==NULL)
00122 return NULL;
00123 for (id=0; id<object_index_size; id++)
00124 {
00125 if (object_linked[id]==0 && object_index[id]!=NULL && object_index[id]->oclass==oclass)
00126 {
00127 object_linked[id]++;
00128 return object_index[id];
00129 }
00130 }
00131 return NULL;
00132 }
00133 static void free_index(void)
00134 {
00135 if (object_index!=NULL)
00136 free(object_index);
00137 object_index=NULL;
00138 object_index_size = 65536;
00139 }
00140
00141 static UNRESOLVED *first_unresolved = NULL;
00142 UNRESOLVED *add_unresolved(OBJECT *by, OBJECT **ref, CLASS *oclass, char *id, unsigned int line, int flags)
00143 {
00144 UNRESOLVED *item = malloc(sizeof(UNRESOLVED));
00145 if (item==NULL) { errno = ENOMEM; return NULL; }
00146 item->by = by;
00147 item->ref = ref;
00148 item->oclass = oclass;
00149 strncpy(item->id,id,sizeof(item->id));
00150 item->line = line;
00151 item->next = first_unresolved;
00152 item->flags = flags;
00153 first_unresolved = item;
00154 return item;
00155 }
00156 static int resolve_list(UNRESOLVED *item)
00157 {
00158 OBJECT *obj;
00159 char classname[33];
00160 char propname[33];
00161 OBJECTNUM id = 0;
00162 char op[2];
00163 char star;
00164 UNRESOLVED *next;
00165 while (item!=NULL)
00166 {
00167
00168
00169 if(0 == strcmp(item->id, "root"))
00170 obj = NULL;
00171 else if (sscanf(item->id,"%32[^.].%32[^:]:",classname,propname)==2)
00172 {
00173 char *value = strchr(item->id,':');
00174 FINDLIST *match;
00175 if (value++==NULL)
00176 {
00177 output_message("%s(%d): %s reference to %s is missing match value", filename, item->line,
00178 format_object(item->by->oclass->name, item->by->id), item->id);
00179 return FAILED;
00180 }
00181 match = find_objects(FL_NEW,FT_CLASS,SAME,classname,AND,FT_PROPERTY,propname,SAME,value,FT_END);
00182 if (match==NULL || match->hit_count==0)
00183 {
00184 output_message("%s(%d): %s reference to %s does not match any existing objects", filename, item->line,
00185 format_object(item->by->oclass->name, item->by->id), item->id);
00186 return FAILED;
00187 }
00188 else if (match->hit_count>1)
00189 {
00190 output_message("%s(%d): %s reference to %s matches more than one object", filename, item->line,
00191 format_object(item->by->oclass->name, item->by->id), item->id);
00192 return FAILED;
00193 }
00194 obj=find_first(match);
00195 }
00196 else if (sscanf(item->id,"%[^:]:id%[+-]%d",classname,op,&id)==3)
00197 {
00198 CLASS *oclass = class_get_class_from_classname(classname);
00199 obj = object_find_by_id(item->by->id + (op[0]=='+'?+1:-1)*id);
00200 if (obj==NULL)
00201 {
00202 output_message("%s(%d): unable resolve reference from %s to %s", filename, item->line,
00203 format_object(item->by->oclass->name, item->by->id), item->id);
00204 return FAILED;
00205 }
00206 }
00207 else if (sscanf(item->id,global_object_scan,classname,&id)==2)
00208 {
00209 obj = load_get_index(id);
00210 if (obj==NULL)
00211 {
00212 output_message("%s(%d): unable resolve reference from %s to %s", filename, item->line,
00213 format_object(item->by->oclass->name, item->by->id), item->id);
00214 return FAILED;
00215 }
00216 if ((strcmp(obj->oclass->name,classname)!=0) && (strcmp("id", classname) != 0))
00217 {
00218 output_message("%s(%d): class of reference from %s to %s mismatched", filename, item->line,
00219 format_object(item->by->oclass->name, item->by->id), item->id);
00220 return FAILED;
00221 }
00222 }
00223 else if (sscanf(item->id,"%[^:]:%c",classname,&star)==2 && star=='*')
00224 {
00225 CLASS *oclass = class_get_class_from_classname(classname);
00226 obj = get_next_unlinked(oclass);
00227 if (obj==NULL)
00228 {
00229 output_message("%s(%d): unable resolve reference from %s to %s", filename, item->line,
00230 format_object(item->by->oclass->name, item->by->id), item->id);
00231 return FAILED;
00232 }
00233 }
00234 else if ((obj=object_find_name(item->id))!=NULL)
00235 {
00236
00237 }
00238 else
00239 {
00240 output_message("%s(%d): syntax error in reference from '%s' to '%s'", filename, item->line, object_name(item->by), item->id);
00241 return FAILED;
00242 }
00243 *(item->ref) = obj;
00244 if ((item->flags&UR_RANKS)==UR_RANKS)
00245 object_set_rank(obj,item->by->rank);
00246 next = item->next;
00247 free(item);
00248 item=next;
00249 }
00250 return SUCCESS;
00251 }
00252 int load_resolve_all()
00253 {
00254 return resolve_list(first_unresolved);
00255 }
00256
00257 #define PARSER char *_p
00258 #define START int _mm=0, _m=0, _n=0, _l=linenum;
00259 #define ACCEPT { _n+=_m; _p+=_m; _m=0; }
00260 #define HERE (_p+_m)
00261 #define OR {_m=0;}
00262 #define REJECT { linenum=_l; return 0; }
00263 #define WHITE (_m+=white(HERE))
00264 #define LITERAL(X) (_mm=literal(HERE,(X)),_m+=_mm,_mm>0)
00265 #define TERM(X) (_mm=(X),_m+=_mm,_mm>0)
00266 #define COPY(X) {size--; (X)[_n++]=*_p++;}
00267 #define DONE return _n;
00268 #define BEGIN_REPEAT {char *__p=_p; int __mm=_mm, __m=_m, __n=_n, __l=_l; int __ln=linenum;
00269 #define REPEAT _p=__p;_m=__m; _mm=__mm; _n=__n; _l=__l; linenum=__ln;
00270 #define END_REPEAT }
00271
00272 static void syntax_error(char *p)
00273 {
00274 char context[16], *nl;
00275 strncpy(context,p,15);
00276 nl = strchr(context,'\n');
00277 if (nl!=NULL) *nl='\0'; else context[15]='\0';
00278 if (strlen(context)>0)
00279 output_message("%s(%d): syntax error at '%s...'", filename, linenum, context);
00280 else
00281 output_message("%s(%d): syntax error", filename, linenum);
00282 }
00283
00284 static int white(PARSER)
00285 {
00286 if (*_p=='\0' || !isspace(*_p))
00287 return 0;
00288 if (*_p=='\n') linenum++;
00289
00290 return white(_p+1)+1;
00291 }
00292
00293 static int comment(PARSER)
00294 {
00295 int _n = white(_p);
00296 if (_p[_n]=='#')
00297 {
00298 while (_p[_n]!='\n')
00299 _n++;
00300 linenum++;
00301 }
00302 return _n;
00303 }
00304
00305 static int literal(PARSER, char *text)
00306 {
00307 if (strncmp(_p,text,strlen(text))==0)
00308 return (int)strlen(text);
00309 return 0;
00310 }
00311
00312 static int name(PARSER, char *result, int size)
00313 {
00314 START;
00315 while (size>1 && isalpha(*_p) || isdigit(*_p) || *_p=='_') COPY(result);
00316 result[_n]='\0';
00317 DONE;
00318 }
00319
00320 static int unitspec(PARSER, UNIT **unit)
00321 {
00322 char result[1024];
00323 int size=sizeof(result);
00324 START;
00325 while (size>1 && isalpha(*_p) || isdigit(*_p) || *_p=='*' || *_p=='/' || *_p=='^') COPY(result);
00326 result[_n]='\0';
00327 if ((*unit=unit_find(result))==NULL)
00328 REJECT;
00329 DONE;
00330 }
00331
00332 static int unitsuffix(PARSER, UNIT **unit)
00333 {
00334 START;
00335 if (LITERAL("["))
00336 {
00337 if (!TERM(unitspec(HERE,unit)))
00338 {
00339 output_message("%s(%d): missing valid unit after [", filename, linenum);
00340 REJECT;
00341 }
00342 if (!LITERAL("]"))
00343 {
00344 output_message("%s(%d): missing ] after unit '%s'", filename, linenum,(*unit)->name);
00345 }
00346 ACCEPT;
00347 DONE;
00348 }
00349 REJECT;
00350 DONE;
00351 }
00352
00353 static int nameunit(PARSER,char *result,int size,UNIT **unit)
00354 {
00355 START;
00356 if (TERM(name(HERE,result,size)) && unitsuffix(HERE,unit)) ACCEPT; DONE;
00357 REJECT;
00358 }
00359
00360 static int dotted_name(PARSER, char *result, int size)
00361 {
00362 START;
00363 while (size>1 && isalpha(*_p) || isdigit(*_p) || *_p=='_' || *_p=='.') COPY(result);
00364 result[_n]='\0';
00365 DONE;
00366 }
00367
00368 static int value(PARSER, char *result, int size)
00369 {
00370
00371 char delim=';';
00372 char *start=_p;
00373 START;
00374 if (*_p=='"')
00375 {
00376 delim='"';
00377 *_p++;
00378 size--;
00379 }
00380 while (size>1 && *_p!='\0' && *_p!=delim && *_p!='\n') COPY(result);
00381 result[_n]='\0';
00382 if (delim!=';')
00383 while (*_p!='\0' && *_p!=';' && *_p!='\n') _p++;
00384 return (int)(_p - start);
00385 }
00386
00387 static int integer(PARSER, int64 *value)
00388 {
00389 char result[256];
00390 int size=sizeof(result);
00391 START;
00392 while (size>1 && isdigit(*_p)) COPY(result);
00393 result[_n]='\0';
00394 *value=atoi64(result);
00395 return _n;
00396 }
00397
00398 static int integer32(PARSER, int32 *value)
00399 {
00400 char result[256];
00401 int size=sizeof(result);
00402 START;
00403 while (size>1 && isdigit(*_p)) COPY(result);
00404 result[_n]='\0';
00405 *value=atoi(result);
00406 return _n;
00407 }
00408
00409 static int real(PARSER, double *value)
00410 {
00411 char result[256];
00412 int size=sizeof(result);
00413 START;
00414 if (*_p=='+' || *_p=='-') COPY(result);
00415 while (size>1 && isdigit(*_p)) COPY(result);
00416 if (*_p=='.') COPY(result);
00417 while (size>1 && isdigit(*_p)) COPY(result);
00418 if (*_p=='E' || *_p=='e') COPY(result);
00419 if (*_p=='+' || *_p=='-') COPY(result);
00420 while (size>1 && isdigit(*_p)) COPY(result);
00421 result[_n]='\0';
00422 *value=atof(result);
00423 return _n;
00424 }
00425
00426 static int functional(PARSER, double *pValue)
00427 {
00428 char32 fname;
00429 double a, b;
00430 START;
00431 if WHITE ACCEPT;
00432 if (LITERAL("random.") && TERM(name(HERE,fname,sizeof(fname))) && LITERAL("(") && TERM(real(HERE,&a)) && LITERAL(",") && TERM(real(HERE,&b)) && LITERAL(")"))
00433 {
00434 RANDOMTYPE rtype = random_type(fname);
00435 if (rtype==RT_INVALID)
00436 {
00437 output_message("%s(%d): %s is not a valid random distribution", filename,linenum,fname);
00438 REJECT;
00439 }
00440 else
00441 {
00442 *pValue = random_value(rtype,a,b);
00443 ACCEPT;
00444 }
00445 } else if TERM(real(HERE,pValue)) ACCEPT
00446 else
00447 {
00448 output_message("%s(%d): expected property or functional value", filename,linenum);
00449 REJECT;
00450 }
00451 DONE;
00452 }
00453
00454 static int functional_unit(PARSER,double *pValue,UNIT **unit)
00455 {
00456 START;
00457 if TERM(functional(HERE,pValue))
00458 {
00459 *unit = NULL;
00460 if WHITE ACCEPT;
00461 if TERM(unitspec(HERE,unit)) ACCEPT;
00462 ACCEPT;
00463 DONE;
00464 }
00465 REJECT;
00466 }
00467
00468 static int time_value_seconds(PARSER, TIMESTAMP *t)
00469 {
00470 START;
00471 if WHITE ACCEPT;
00472 if (TERM(integer(HERE,t)) && LITERAL("s")) { *t *= TS_SECOND; ACCEPT; DONE;}
00473 OR
00474 if (TERM(integer(HERE,t)) && LITERAL("S")) { *t *= TS_SECOND; ACCEPT; DONE;}
00475 REJECT;
00476 }
00477
00478 static int time_value_minutes(PARSER, TIMESTAMP *t)
00479 {
00480 START;
00481 if WHITE ACCEPT;
00482 if (TERM(integer(HERE,t)) && LITERAL("m")) { *t *= 60*TS_SECOND; ACCEPT; DONE;}
00483 OR
00484 if (TERM(integer(HERE,t)) && LITERAL("M")) { *t *= 60*TS_SECOND; ACCEPT; DONE;}
00485 REJECT;
00486 }
00487
00488 static int time_value_hours(PARSER, TIMESTAMP *t)
00489 {
00490 START;
00491 if WHITE ACCEPT;
00492 if (TERM(integer(HERE,t)) && LITERAL("h")) { *t *= 3600*TS_SECOND; ACCEPT; DONE;}
00493 OR
00494 if (TERM(integer(HERE,t)) && LITERAL("H")) { *t *= 3600*TS_SECOND; ACCEPT; DONE;}
00495 REJECT;
00496 }
00497
00498 static int time_value_days(PARSER, TIMESTAMP *t)
00499 {
00500 START;
00501 if WHITE ACCEPT;
00502 if (TERM(integer(HERE,t)) && LITERAL("d")) { *t *= 86400*TS_SECOND; ACCEPT; DONE;}
00503 OR
00504 if (TERM(integer(HERE,t)) && LITERAL("D")) { *t *= 86400*TS_SECOND; ACCEPT; DONE;}
00505 REJECT;
00506 }
00507
00508 int time_value_datetime(PARSER, TIMESTAMP *t)
00509 {
00510 int64 Y,m,d,H,M,S;
00511 START;
00512 if WHITE ACCEPT;
00513 if LITERAL("'") ACCEPT;
00514 if (TERM(integer(HERE,&Y)) && LITERAL("-")
00515 && TERM(integer(HERE,&m)) && LITERAL("-")
00516 && TERM(integer(HERE,&d)) && LITERAL(" ")
00517 && TERM(integer(HERE,&H)) && LITERAL(":")
00518 && TERM(integer(HERE,&M)) && LITERAL(":")
00519 && TERM(integer(HERE,&S)))
00520 {
00521 struct tm dt = {(int)S,(int)M,(int)H,(int)d,(int)m-1,(int)Y-1900,0,0,0};
00522 int64 tt = mktime(&dt);
00523 if (tt!=-1) {*t=(int64)tt*TS_SECOND;
00524 ACCEPT;
00525 if LITERAL("'") ACCEPT;
00526 DONE;}
00527 }
00528 REJECT;
00529 }
00530
00531 int time_value(PARSER, TIMESTAMP *t)
00532 {
00533 START;
00534 if WHITE ACCEPT;
00535 if (TERM(time_value_seconds(HERE,t)) && WHITE,LITERAL(";")) {ACCEPT; DONE; }
00536 OR
00537 if (TERM(time_value_minutes(HERE,t)) && WHITE,LITERAL(";")) {ACCEPT; DONE; }
00538 OR
00539 if (TERM(time_value_hours(HERE,t)) && WHITE,LITERAL(";")) {ACCEPT; DONE; }
00540 OR
00541 if (TERM(time_value_days(HERE,t)) && WHITE,LITERAL(";")) {ACCEPT; DONE; }
00542 OR
00543 if (TERM(time_value_datetime(HERE,t)) && WHITE,LITERAL(";")) {ACCEPT; DONE; }
00544 OR
00545 if (TERM(integer(HERE,t)) && WHITE,LITERAL(";")) {ACCEPT; DONE; }
00546 else REJECT;
00547 DONE;
00548 }
00549
00550 double load_latitude(char *buffer)
00551 {
00552 int32 d, m=0;
00553 double s=0;
00554 char ns;
00555 if((strcmp(buffer, "none") == 0) || (strcmp(buffer, "NONE") == 0)){
00556 return QNAN;
00557 }
00558 if (sscanf(buffer,"%d%c%d'%lf\"",&d,&ns,&m,&s)>1)
00559 {
00560 double v = (double)d+(double)m/60+s/3600;
00561 if (v>=0 && v<=90)
00562 {
00563 if (ns=='S')
00564 return -v;
00565 else if (ns=='N')
00566 return v;
00567 }
00568 }
00569 output_message("%s(%d): '%s' is not a valid latitude", filename,linenum,buffer);
00570 return QNAN;
00571 }
00572
00573 double load_longitude(char *buffer)
00574 {
00575 int32 d, m=0;
00576 double s=0;
00577 char ns;
00578 if((strcmp(buffer, "none") == 0) || (strcmp(buffer, "NONE") == 0)){
00579 return QNAN;
00580 }
00581 if (sscanf(buffer,"%d%c%d'%lf\"",&d,&ns,&m,&s)>1)
00582 {
00583 double v = (double)d+(double)m/60+s/3600;
00584 if (v>=0 && v<=180)
00585 {
00586 if (ns=='W')
00587 return -v;
00588 else if (ns=='E')
00589 return v;
00590 }
00591 }
00592 output_message("%s(%d): '%s' is not a valid longitude", filename,linenum,buffer);
00593 return QNAN;
00594 }
00595
00596 static int clock_properties(PARSER)
00597 {
00598 TIMESTAMP tsval;
00599 char32 timezone;
00600 double realval;
00601 START;
00602 if WHITE ACCEPT;
00603 if (LITERAL("tick") && WHITE)
00604 {
00605 if (TERM(real(HERE,&realval)) && WHITE,LITERAL(";"))
00606 {
00607 if (realval!=TS_RESOLUTION)
00608 {
00609 output_message("%s(%d): timestamp resolution %g does not match system resolution %g, this version does not support variable tick", filename, linenum, realval, TS_RESOLUTION);
00610 REJECT;
00611 }
00612 ACCEPT;
00613 goto Next;
00614 }
00615 output_message("%s(%d): expected tick value", filename, linenum);
00616 REJECT;
00617 }
00618 OR if (LITERAL("timestamp") && WHITE)
00619 {
00620 if (TERM(time_value(HERE,&tsval)))
00621 {
00622 global_clock = tsval;
00623 ACCEPT;
00624 goto Next;
00625 }
00626 output_message("%s(%d): expected time value", filename, linenum);
00627 REJECT;
00628 }
00629 OR if (LITERAL("timezone") && WHITE)
00630 {
00631 if (TERM(value(HERE,timezone,sizeof(timezone))) && WHITE,LITERAL(";") && strlen(timezone)>0)
00632 {
00633 if (timestamp_set_tz(timezone)==NULL)
00634 output_warning("%s(%d): timezone %s is not defined",filename,linenum,timezone);
00635 ACCEPT;
00636 goto Next;
00637 }
00638 output_message("%s(%d): expected time zone specification", filename, linenum);
00639 REJECT;
00640 }
00641 OR if (WHITE,LITERAL("}")) { DONE;}
00642 OR { syntax_error(HERE); REJECT; }
00643
00644 Next:
00645 if TERM(clock_properties(HERE)) ACCEPT;
00646 DONE;
00647 }
00648
00649 static int clock_block(PARSER)
00650 {
00651 START;
00652 if WHITE ACCEPT;
00653 if LITERAL("clock") ACCEPT else REJECT;
00654 if WHITE ACCEPT;
00655 if LITERAL("{") ACCEPT
00656 else
00657 {
00658 output_message("%s(%d): expected clock block opening {",filename,linenum);
00659 REJECT;
00660 }
00661 if WHITE ACCEPT;
00662 if TERM(clock_properties(HERE)) ACCEPT;
00663 if WHITE ACCEPT;
00664 if LITERAL("}") ACCEPT else
00665 {
00666 output_message("%s(%d): expected clock block closing }",filename,linenum);
00667 REJECT;
00668 }
00669 DONE;
00670 }
00671
00672 static int module_properties(PARSER, MODULE *mod)
00673 {
00674 int64 val;
00675 CLASSNAME classname;
00676 char256 propname;
00677 char256 propvalue;
00678 START;
00679 if WHITE ACCEPT;
00680 if (LITERAL("major"))
00681 {
00682 if WHITE ACCEPT;
00683 if (TERM(integer(HERE,&val)))
00684 {
00685 if WHITE ACCEPT;
00686 if LITERAL(";")
00687 {
00688 if (val!=mod->major)
00689 {
00690 output_message("%s(%d): %s has an incompatible module major version", filename,linenum,mod->name);
00691 REJECT;
00692 }
00693 ACCEPT;
00694 goto Next;
00695 }
00696 else
00697 {
00698 output_message("%s(%d): expected ; after %s module major number", filename,linenum, mod->name);
00699 REJECT;
00700 }
00701 }
00702 else
00703 {
00704 output_message("%s(%d): expected %s module major number", filename,linenum, mod->name);
00705 REJECT;
00706 }
00707 }
00708 OR if (LITERAL("minor"))
00709 {
00710 if WHITE ACCEPT;
00711 if (TERM(integer(HERE,&val)))
00712 {
00713 if WHITE ACCEPT;
00714 if LITERAL(";")
00715 {
00716 if (val!=mod->minor)
00717 {
00718 output_message("%s(%d): %s has an incompatible module minor version", filename,linenum,mod->name);
00719 REJECT;
00720 }
00721 ACCEPT;
00722 goto Next;
00723 }
00724 else
00725 {
00726 output_message("%s(%d): expected ; after %s module minor number", filename,linenum, mod->name);
00727 REJECT;
00728 }
00729 }
00730 else
00731 {
00732 output_message("%s(%d): expected %s module minor number", filename,linenum, mod->name);
00733 REJECT;
00734 }
00735 }
00736 OR if (LITERAL("class"))
00737 {
00738 if WHITE ACCEPT;
00739 if TERM(name(HERE,classname,sizeof(classname)))
00740 {
00741 if WHITE ACCEPT;
00742 if LITERAL(";")
00743 {
00744 CLASS *oclass = class_get_class_from_classname(classname);
00745 if (oclass==NULL || oclass->module!=mod)
00746 {
00747 output_message("%s(%d): module '%s' does not implement class '%s'", filename, linenum, mod->name, classname);
00748 REJECT;
00749 }
00750 ACCEPT;
00751 goto Next;
00752 }
00753 else
00754 {
00755 output_message("%s(%d): expected ; after module %s class %s declaration", filename,linenum, mod->name, classname);
00756 REJECT;
00757 }
00758 }
00759 else
00760 {
00761 output_message("%s(%d): missing class name in module %s class declaration", filename,linenum, mod->name);
00762 REJECT;
00763 }
00764 }
00765 OR if (TERM(name(HERE,propname,sizeof(propname))))
00766 {
00767 if WHITE ACCEPT;
00768 if TERM(value(HERE,propvalue,sizeof(propvalue)))
00769 {
00770 if WHITE ACCEPT;
00771 if LITERAL(";")
00772 {
00773 if (module_setvar(mod,propname,propvalue)>0)
00774 {
00775 ACCEPT;
00776 goto Next;
00777 }
00778 else
00779 {
00780 output_message("%s(%d): invalid module %s property '%s'", filename, linenum, mod->name, propname);
00781 REJECT;
00782 }
00783 }
00784 else
00785 {
00786 output_message("%s(%d): expected ; after module %s property specification", filename, linenum, mod->name);
00787 REJECT;
00788 }
00789 }
00790 else
00791 {
00792 output_message("%s(%d): missing module %s property %s value", filename, linenum, mod->name, propname);
00793 REJECT;
00794 }
00795 }
00796 OR if LITERAL("}") {/* don't accept yet */ DONE;}
00797 OR { syntax_error(HERE); REJECT; }
00798 /* may be repeated */
00799 Next:
00800 if TERM(module_properties(HERE,mod)) ACCEPT;
00801 DONE;
00802 }
00803
00804 static int module_block(PARSER)
00805 {
00806 char module_name[64];
00807 char fmod[8],mod[54];
00808 MODULE *module;
00809 START;
00810 if WHITE ACCEPT;
00811 if LITERAL("module") ACCEPT else REJECT;
00812 if WHITE ACCEPT;
00813 /* load options should go here and get converted to argc/argv */
00814
00815 /* foreign module */
00816 if (TERM(name(HERE,fmod,sizeof(fmod))) && LITERAL("::") && TERM(name(HERE,mod,sizeof(mod))))
00817 {
00818 sprintf(module_name,"%s::%s",fmod,mod);
00819 if ((module=module_load(module_name,0,NULL))!=NULL)
00820 {
00821 ACCEPT;
00822 }
00823 else
00824 {
00825 output_message("%s(%d): %s module '%s' load failed, %s", filename, linenum, fmod, mod,strerror(errno));
00826 REJECT;
00827 }
00828 }
00829
00830 OR
00831 /* native C/C++ module */
00832 if (TERM(name(HERE,module_name,sizeof(module_name))))
00833 {
00834 if ((module=module_load(module_name,0,NULL))!=NULL)
00835 {
00836 ACCEPT;
00837 }
00838 else
00839 {
00840 output_message("%s(%d): module '%s' load failed, %s", filename, linenum, module_name,strerror(errno));
00841 REJECT;
00842 }
00843 }
00844 if WHITE ACCEPT;
00845 if LITERAL(";") {ACCEPT;DONE;}
00846 OR
00847 if LITERAL("{") ACCEPT
00848 else
00849 {
00850 output_message("%s(%d): expected module %s block opening {", filename, linenum, module_name);
00851 REJECT;
00852 }
00853 if TERM(module_properties(HERE,module)) ACCEPT else REJECT;
00854 if WHITE ACCEPT;
00855 if LITERAL("}") ACCEPT
00856 else
00857 {
00858 output_message("%s(%d): expected module %s block closing }", filename, linenum, module_name);
00859 REJECT;
00860 }
00861 DONE;
00862 }
00863
00864 static int property_type(PARSER, PROPERTYTYPE *ptype)
00865 {
00866 char32 type;
00867 START;
00868 if WHITE ACCEPT;
00869 if TERM(name(HERE,type,sizeof(type)))
00870 {
00871 *ptype = class_get_propertytype_from_typename(type);
00872 if (*ptype==PT_void)
00873 {
00874 output_message("%s(%d): property type %s is not recognized", filename, linenum, type);
00875 REJECT;
00876 }
00877 ACCEPT;
00878 }
00879 else REJECT;
00880 DONE;
00881 }
00882
00883 static int class_properties(PARSER, CLASS *oclass)
00884 {
00885 PROPERTYTYPE type;
00886 PROPERTYNAME propname;
00887 START;
00888 if WHITE ACCEPT;
00889 if (TERM(property_type(HERE,&type)) && WHITE && TERM(name(HERE,propname,sizeof(propname))) && WHITE && LITERAL(";"))
00890 {
00891 PROPERTY *prop = class_find_property(oclass,propname);
00892 if (prop==NULL)
00893 {
00894 output_message("%s(%d): property %s is not defined in class %s", filename, linenum, propname, oclass->name);
00895 REJECT;
00896 }
00897 else if (prop->ptype!=type)
00898 {
00899 output_message("%s(%d): property %s is defined in class %s as type %s", filename, linenum, propname, oclass->name, class_get_property_typename(prop->ptype));
00900 REJECT;
00901 }
00902 ACCEPT;
00903 }
00904 else if LITERAL("}") {/* don't accept yet */ DONE;}
00905 else { syntax_error(HERE); REJECT; }
00906 /* may be repeated */
00907 if TERM(class_properties(HERE,oclass)) ACCEPT;
00908 DONE;
00909 }
00910
00911 static int class_block(PARSER)
00912 {
00913 CLASSNAME classname;
00914 CLASS *oclass;
00915 START;
00916 if WHITE ACCEPT;
00917 if LITERAL("class")
00918 {
00919 if WHITE ACCEPT;
00920 if TERM(name(HERE,classname,sizeof(classname)))
00921 {
00922 if WHITE ACCEPT;
00923 if LITERAL("{")
00924 {
00925 oclass = class_get_class_from_classname(classname);
00926 if (oclass==NULL) REJECT;
00927 ACCEPT;
00928 }
00929 else
00930 {
00931 output_message("%s(%d): expected class %s block opening {",filename,linenum,classname);
00932 REJECT;
00933 }
00934 }
00935 else
00936 {
00937 output_message("%s(%d): expected class name",filename,linenum);
00938 REJECT;
00939 }
00940 if TERM(class_properties(HERE,oclass)) ACCEPT;
00941 if WHITE ACCEPT;
00942 if LITERAL("}") ACCEPT
00943 else
00944 {
00945 output_message("%s(%d): expected closing } after class block", filename, linenum);
00946 REJECT;
00947 }
00948 }
00949 else REJECT;
00950 DONE;
00951 }
00952
00953 int set_flags(OBJECT *obj, char1024 propval)
00954 {
00955 extern KEYWORD oflags[];
00956 if (convert_to_set(propval,&(obj->flags),object_flag_property())<=0)
00957 {
00958 output_message("%s(%d): flags of %s:%d could not be set to %s", filename, linenum, obj->oclass->name, obj->id, propval);
00959 return 0;
00960 };
00961 return 1;
00962 }
00963
00964 static int object_properties(PARSER, CLASS *oclass, OBJECT *obj)
00965 {
00966 PROPERTYNAME propname;
00967 char1024 propval;
00968 double dval;
00969 UNIT *unit=NULL;
00970 START;
00971 if WHITE ACCEPT;
00972 if TERM(dotted_name(HERE,propname,sizeof(propname)))
00973 {
00974 PROPERTY *prop = class_find_property(oclass,propname);
00975 if WHITE ACCEPT;
00976 if (prop!=NULL && prop->ptype==PT_double && TERM(functional_unit(HERE,&dval,&unit)))
00977 {
00978 if (prop==NULL)
00979 {
00980 output_message("%s(%d): property '%s' not found", filename, linenum,propname);
00981 REJECT;
00982 } else if (unit!=NULL && prop->unit!=NULL && strcmp((char *)unit, "") != 0 && unit_convert_ex(unit,prop->unit,&dval)==0)
00983 {
00984 output_message("%s(%d): units of value are incompatible with units of property, cannot convert from %s to %s", filename, linenum, unit->name,prop->unit->name);
00985 REJECT;
00986 }
00987 else if (object_set_double_by_name(obj,propname,dval)==0)
00988 {
00989 output_message("%s(%d): property %s of %s could not be set to '%g'", filename, linenum, propname, format_object(obj->oclass->name, obj->id), dval);
00990 REJECT;
00991 }
00992 else
00993 ACCEPT;
00994 }
00995 else if TERM(value(HERE,propval,sizeof(propval)))
00996 {
00997 if (prop==NULL)
00998 {
00999 /* check for special properties */
01000 if (strcmp(propname,"root")==0)
01001 obj->parent = NULL;
01002 else if (strcmp(propname,"parent")==0)
01003 add_unresolved(obj,(void*)&obj->parent,oclass,propval,linenum,UR_RANKS);
01004 else if (strcmp(propname,"rank")==0)
01005 obj->rank = atoi(propval);
01006 else if (strcmp(propname,"clock")==0)
01007 obj->clock = atoi64(propval);
01008 else if (strcmp(propname,"latitude")==0)
01009 obj->latitude = load_latitude(propval);
01010 else if (strcmp(propname,"longitude")==0)
01011 obj->longitude = load_longitude(propval);
01012 else if (strcmp(propname,"in")==0)
01013 obj->in_svc = convert_to_timestamp(propval);
01014 else if (strcmp(propname,"out")==0)
01015 obj->out_svc = convert_to_timestamp(propval);
01016 else if (strcmp(propname,"name")==0)
01017 object_set_name(obj,propval);
01018 else if (strcmp(propname,"flags")==0)
01019 {
01020 if(set_flags == 0)
01021 REJECT;
01022 }
01023 else if (strcmp(propname,"library")==0)
01024 {
01025 output_warning("%s(%d): libraries not yet supported", filename, linenum);
01026 ACCEPT;
01027 DONE;
01028 }
01029 else
01030 {
01031 output_message("%s(%d): property %s is not defined in class %s", filename, linenum, propname, oclass->name);
01032 REJECT;
01033 }
01034 }
01035 else if (prop->ptype==PT_object)
01036 { void *addr = object_get_addr(obj,propname);
01037 if (addr==NULL)
01038 {
01039 output_message("%s(%d): unable to set parent of %s", filename, linenum, format_object(oclass->name, obj->id));
01040 REJECT;
01041 }
01042 add_unresolved(obj,addr,oclass,propval,linenum,UR_NONE);
01043 }
01044 else if (object_set_value_by_name(obj,propname,propval)==0)
01045 {
01046 output_message("%s(%d): property %s of %s could not be set to '%s'", filename, linenum, propname, format_object(obj->oclass->name, obj->id), propval);
01047 REJECT;
01048 }
01049 ACCEPT;
01050 }
01051 if WHITE ACCEPT;
01052 if LITERAL(";") {ACCEPT;}
01053 else
01054 {
01055 output_message("%s(%d): expected ';' at end of property specification", filename,linenum);
01056 REJECT;
01057 }
01058 }
01059 else if LITERAL("}") {/* don't accept yet */ DONE;}
01060 else { syntax_error(HERE); REJECT; }
01061 /* may be repeated */
01062 if TERM(object_properties(HERE,oclass,obj)) ACCEPT;
01063 DONE;
01064 }
01065
01066 static int object_name_id(PARSER,char *classname, int64 *id)
01067 {
01068 START;
01069 if WHITE ACCEPT;
01070 if TERM(dotted_name(HERE,classname,sizeof(CLASSNAME)))
01071 {
01072 *id = -1; /* anonymous object */
01073 if LITERAL(":")
01074 {
01075 TERM(integer(HERE,id));
01076 }
01077 ACCEPT;
01078 DONE;
01079 }
01080 else if TERM(name(HERE,classname,sizeof(CLASSNAME)))
01081 {
01082 *id = -1; /* anonymous object */
01083 if LITERAL(":")
01084 {
01085 TERM(integer(HERE,id));
01086 }
01087 ACCEPT;
01088 DONE;
01089 }
01090 else
01091 REJECT;
01092 }
01093
01094 static int object_name_id_range(PARSER,char *classname, int64 *from, int64 *to)
01095 {
01096 START;
01097 if WHITE ACCEPT;
01098 if (TERM(dotted_name(HERE,classname,sizeof(CLASSNAME))) && LITERAL(":") && TERM(integer(HERE,from)) && LITERAL("..")) ACCEPT
01099 else if (TERM(name(HERE,classname,sizeof(CLASSNAME))) && LITERAL(":") && TERM(integer(HERE,from)) && LITERAL("..")) ACCEPT
01100 else REJECT;
01101 if (TERM(integer(HERE,to))) ACCEPT else
01102 {
01103 output_message("%s(%d): expected id range end value", filename, linenum);
01104 REJECT;
01105 }
01106 DONE;
01107 }
01108
01109 static int object_name_id_count(PARSER,char *classname, int64 *count)
01110 {
01111 START;
01112 if WHITE ACCEPT;
01113 if (TERM(dotted_name(HERE,classname,sizeof(CLASSNAME))) && LITERAL(":") && LITERAL("..")) ACCEPT
01114 else if (TERM(name(HERE,classname,sizeof(CLASSNAME))) && LITERAL(":") && LITERAL("..")) ACCEPT
01115 else REJECT;
01116 if (TERM(integer(HERE,count))) ACCEPT else
01117 {
01118 output_message("%s(%d): expected id count", filename, linenum);
01119 REJECT;
01120 }
01121 DONE;
01122 }
01123
01124 static int object_block(PARSER)
01125 {
01126 static OBJECT nameobj;
01127 CLASSNAME classname;
01128 CLASS *oclass;
01129 OBJECT *obj;
01130 int64 id=-1, id2=-1;
01131 START;
01132 if WHITE ACCEPT;
01133 if LITERAL("object") ACCEPT else REJECT
01134 if WHITE ACCEPT;
01135 if TERM(object_name_id_range(HERE,classname,&id,&id2))
01136 {
01137 oclass = class_get_class_from_classname(classname);
01138 if (oclass==NULL) REJECT;
01139 id2++;
01140 ACCEPT;
01141 }
01142 else if TERM(object_name_id_count(HERE,classname,&id2))
01143 {
01144 id=-1; id2--; /* count down to zero inclusive */
01145 oclass = class_get_class_from_classname(classname);
01146 if (oclass==NULL) REJECT;
01147 ACCEPT;
01148 }
01149 else if TERM(object_name_id(HERE,classname,&id))
01150 {
01151 oclass = class_get_class_from_classname(classname);
01152 if (oclass==NULL)
01153 {
01154 output_message("%s(%d): class '%s' is not known", filename, linenum, classname);
01155 REJECT;
01156 }
01157 ACCEPT;
01158 }
01159 else
01160 {
01161 output_message("%s(%d): expected object id or range", filename, linenum);
01162 REJECT;
01163 }
01164 if WHITE ACCEPT;
01165 if (LITERAL("{")) ACCEPT else
01166 {
01167 output_message("%s(%d): expected object block starting {", filename, linenum);
01168 REJECT;
01169 }
01170
01171 /* id(s) is/are valid */
01172 nameobj.name = classname;
01173 if (id2==-1) id2=id+1; /* create singleton */
01174 BEGIN_REPEAT;
01175 while (id<id2)
01176 {
01177 REPEAT;
01178 obj = &nameobj;
01179 if ((*oclass->create)(&obj,NULL)==FAILED) REJECT;
01180 if (obj==NULL || obj==&nameobj) REJECT;
01181 if (id!=-1 && load_set_index(obj,(OBJECTNUM)id)==FAILED)
01182 {
01183 output_message("%s(%d): unable to index object id number for %s", filename, linenum, format_object(classname, (int)id));
01184 REJECT;
01185 }
01186 if TERM(object_properties(HERE,oclass,obj))
01187 {
01188 ACCEPT;
01189 } else REJECT;
01190 if (id==-1) id2--; else id++;
01191 }
01192 END_REPEAT;
01193 if WHITE ACCEPT;
01194 if LITERAL("}") ACCEPT else
01195 {
01196 output_message("%s(%d): expected object block closing }", filename, linenum);
01197 REJECT;
01198 }
01199 DONE;
01200 }
01201
01202 static int import(PARSER)
01203 {
01204 char32 modname;
01205 char1024 fname;
01206 START;
01207 if WHITE ACCEPT;
01208 if LITERAL("import")
01209 {
01210 if WHITE ACCEPT;
01211 if TERM(name(HERE,modname,sizeof(modname)))
01212 {
01213 if WHITE ACCEPT;
01214 if TERM(value(HERE,fname,sizeof(fname)))
01215 {
01216 if LITERAL(";")
01217 {
01218 int result;
01219 MODULE *module = module_find(modname);
01220 if (module==NULL)
01221 {
01222 output_message("%s(%d): module %s not loaded", filename, linenum, modname);
01223 REJECT;
01224 }
01225 result = module_import(module,fname);
01226 if (result < 0)
01227 {
01228 output_message("%s(%d): %d errors loading importing %s into %s module", filename, linenum, -result, fname, modname);
01229 REJECT;
01230 }
01231 else if (result==0)
01232 {
01233 output_message("%s(%d): module %s load of %s failed; %s", filename, linenum, modname, fname, strerror(errno));
01234 REJECT;
01235 }
01236 else
01237 {
01238 output_verbose("%d objects loaded to %s from %s", result, modname, fname);
01239 ACCEPT;
01240 }
01241 }
01242 else
01243 {
01244 output_message("%s(%d): expected ; after module %s import from %s statement", filename, linenum, modname, fname);
01245 REJECT;
01246 }
01247 }
01248 else
01249 {
01250 output_message("%s(%d): expected filename after module %s import statement", filename, linenum, modname);
01251 REJECT;
01252 }
01253 }
01254 else
01255 {
01256 output_message("%s(%d): expected module name after import statement", filename, linenum);
01257 REJECT;
01258 }
01259 }
01260 DONE
01261 }
01262
01263 static int library(PARSER)
01264 {
01265 START;
01266 if WHITE ACCEPT;
01267 if LITERAL("library")
01268 {
01269 char libname[1024];
01270 if WHITE ACCEPT;
01271 if ( TERM(dotted_name(HERE,libname,sizeof(libname))) && WHITE,LITERAL(";"))
01272 {
01273 output_warning("%s(%d): libraries not yet supported", filename, linenum);
01274 ACCEPT;
01275 DONE;
01276 }
01277 else
01278 {
01279 output_message("%s(%d): library syntax error", filename, linenum);
01280 REJECT;
01281 }
01282 }
01283 REJECT;
01284 }
01285
01286 static int gridlabd_file(PARSER)
01287 {
01288 START;
01289 if WHITE ACCEPT;
01290 OR if TERM(object_block(HERE)) {ACCEPT; DONE;}
01291 OR if TERM(class_block(HERE)) {ACCEPT; DONE;}
01292 OR if TERM(module_block(HERE)) {ACCEPT; DONE;}
01293 OR if TERM(clock_block(HERE)) {ACCEPT; DONE;}
01294 OR if TERM(import(HERE)) {ACCEPT; DONE; }
01295 OR if TERM(library(HERE)) {ACCEPT; DONE; }
01296 OR if (*(HERE)=='\0') {ACCEPT; DONE;}
01297 else REJECT;
01298 DONE;
01299 }
01300
01301 static int suppress = 0;
01302 static int nesting = 0;
01303 static int macro_line[64];
01304 static int process_macro(char *buffer, int size, char *line, char *filename, int linenum);
01305 static int buffer_read(FILE *fp, char *buffer, char *filename, int size)
01306 {
01307 char line[1024];
01308 int n=0;
01309 int linenum=0;
01310 while (fgets(line,sizeof(line),fp)!=NULL)
01311 {
01312 int len;
01313 char *c = strchr(line,'#');
01314 linenum++;
01315 if (c!=NULL) /* truncate at comment */
01316 strcpy(c,"\n");
01317 len = (int)strlen(line);
01318 if (len>=size-1)
01319 return 0;
01320
01321 /* check for macros that affect reading */
01322 if (line[0]=='%')
01323 {
01324 /* macro disables reading */
01325 if (process_macro(buffer,size,line,filename,linenum)==FALSE)
01326 return 0;
01327 }
01328
01329 /* if reading is enabled */
01330 else if (suppress==0)
01331 {
01332 strcpy(buffer,line);
01333 buffer+=len;
01334 size -= len;
01335 n+=len;
01336 }
01337 }
01338 if (nesting>0)
01339 {
01340 output_message("%s(%d): missing %%endif for %%if at %s(%d)", filename,linenum,filename,macro_line[nesting-1]);
01341 return -1;
01342 }
01343 return n;
01344 }
01345
01346 static int include_file(char *filename, char *buffer, int size, char *offset)
01347 {
01348 STAT stat;
01349 char *ff = find_file(filename,NULL,R_OK);
01350 FILE *fp;
01351 fp = ff?fopen(ff,"r"):NULL;
01352 if (fp==NULL)
01353 {
01354 output_error("include file '%s' open failed: %s", filename, strerror(errno));
01355 errno = 0;
01356 return 0;
01357 }
01358 if (FSTAT(fileno(fp),&stat)==0 && stat.st_size<size)
01359 {
01361 /* buffer = realloc(buffer,size+stat.st_size); */
01362 output_error("unable to grow size of read buffer for include file '%s'", filename);
01363 errno = 0;
01364 return 0;
01365 }
01366 else
01367 {
01368 output_error("unable to get size of included file '%s'", filename);
01369 errno = 0;
01370 return 0;
01371 }
01372 output_verbose("included file '%s' is %d bytes long", filename,stat.st_size);
01373 if (buffer==NULL)
01374 {
01375 output_error("unable to expand buffer size for file '%s': %s", filename, strerror(errno));
01376 errno = 0;
01377 return 0;
01378 }
01379 output_error("%s: include files not supported", filename);
01380 return 0;
01381 }
01382
01383 static int process_macro(char *buffer, int size, char *line, char *filename, int linenum)
01384 {
01385 if (strncmp(line,"%endif",6)==0)
01386 {
01387 if (nesting>0)
01388 {
01389 nesting--;
01390 suppress &= ~(1<<nesting);
01391 return TRUE;
01392 }
01393 else
01394 output_error("%s(%d): %%endif is mismatched", filename, linenum);
01395 return TRUE;
01396 }
01397 else if (strncmp(line,"%else",5)==0)
01398 {
01399 if ( (suppress&(1<<nesting)) == (1<<nesting) )
01400 suppress &= ~(1<<nesting);
01401 else
01402 suppress |= (1<<nesting);
01403
01404 }
01405 else if (strncmp(line,"%ifdef",6)==0)
01406 {
01407 char *term = strchr(line+6,' ');
01408 char value[1024];
01409 if (term==NULL)
01410 {
01411 output_message("%s(%d): %%ifdef macro missing term",filename,linenum);
01412 return FALSE;
01413 }
01414 if (sscanf(term+1,"%[^\n]",value)==1 && global_getvar(value, NULL, 0)==NULL)
01415 suppress |= (1<<nesting);
01416 macro_line[nesting] = linenum;
01417 nesting++;
01418 return TRUE;
01419 }
01420 else if (strncmp(line,"%ifndef",7)==0)
01421 {
01422 char *term = strchr(line+7,' ');
01423 char value[1024];
01424 if (term==NULL)
01425 {
01426 output_message("%s(%d): %%ifndef macro missing term",filename,linenum);
01427 return FALSE;
01428 }
01429 if (sscanf(term+1,"%[^\n]",value)==1 && global_getvar(value, NULL, 0)!=NULL)
01430 suppress |= (1<<nesting);
01431 macro_line[nesting] = linenum;
01432 nesting++;
01433 return TRUE;
01434 }
01435 else if (strncmp(line,"%if",3)==0)
01436 {
01437 char var[32], op[4], *value;
01438 double val;
01439 /*output_message("%s(%d): %%if macros not supported yet", filename,linenum);
01440 return FALSE;*/
01441 if (sscanf(line+4,"%s %[!<>=] %lg",var,op,&val)!=3)
01442 {
01443 output_message("%s(%d): %%if macro statement syntax error", filename,linenum);
01444 return FALSE;
01445 }
01446 value = global_getvar(var, NULL, 0);
01447 if (value==NULL)
01448 {
01449 output_message("%s(%d): %s is not defined", filename,linenum,var);
01450 return FALSE;
01451 }
01452 if (strcmp(op,"<")==0) { if (!val<atof(value)) suppress|=(1<<nesting); }
01453 else if (strcmp(op,">")==0) { if (!val>atof(value)) suppress|=(1<<nesting); }
01454 else if (strcmp(op,">=")==0) { if (!val>=atof(value)) suppress|=(1<<nesting); }
01455 else if (strcmp(op,"<=")==0) { if (!val<=atof(value)) suppress|=(1<<nesting); }
01456 else if (strcmp(op,"==")==0) { if (!val==atof(value)) suppress|=(1<<nesting); }
01457 else if (strcmp(op,"!=")==0) { if (!val!=atof(value)) suppress|=(1<<nesting); }
01458 else
01459 {
01460 output_message("%s(%d): operator %s is not recognized", filename,linenum,op);
01461 return FALSE;
01462 }
01463 macro_line[nesting] = linenum;
01464 nesting++;
01465 return TRUE;
01466 }
01467
01468 /* handles suppressed macros */
01469 if (suppress!=0)
01470 return TRUE;
01471
01472 /* these macros can be suppressed */
01473 if (strncmp(line,"%include",8)==0)
01474 {
01475 char *term = strchr(line+8,' ');
01476 char value[1024];
01477 if (term==NULL)
01478 {
01479 output_message("%s(%d): %%include macro missing term",filename,linenum);
01480 return FALSE;
01481 }
01482 if (sscanf(term+1,"%[^\n]",value)==1 && include_file(value,buffer,size,line)<=0)
01483 {
01484 output_message("%s(%d): %%include failed",filename,linenum);
01485 return FALSE;
01486 }
01487 return TRUE;
01488 }
01489 else if (strncmp(line,"%define",7)==0)
01490 {
01491 char *term = strchr(line+7,' ');
01492 char value[1024];
01493 if (term==NULL)
01494 {
01495 output_message("%s(%d): %%define macro missing term",filename,linenum);
01496 return FALSE;
01497 }
01498 if (sscanf(term+1,"%[^\n]",value)==1 && global_setvar(value)==SUCCESS)
01499 return TRUE;
01500 else
01501 {
01502 output_message("%s(%d): %%define term not accepted",filename,linenum);
01503 return FALSE;
01504 }
01505 }
01506 else if (strncmp(line,"%print",6)==0)
01507 {
01508 char *term = strchr(line+6,' ');
01509 char value[1024];
01510 char *result;
01511 if (term==NULL)
01512 {
01513 output_message("%s(%d): %%print macro missing term",filename,linenum);
01514 return FALSE;
01515 }
01516 if (sscanf(term+1,"%[^\n]",value)==1 && (result=global_getvar(value, NULL, 0))!=NULL)
01517 {
01518 output_message("%s(%d): %s=%s", filename, linenum, value, result);
01519 return TRUE;
01520 }
01521 else
01522 {
01523 output_message("%s(%d): %%print term not found",filename,linenum);
01524 return FALSE;
01525 }
01526 }
01527 else
01528 return FALSE;
01529 }
01530
01531 STATUS loadall_glm(char *file) /**< a pointer to the first character in the file name string */
01532 {
01533 OBJECT *obj, *first = object_get_first();
01534 char *buffer = NULL, *p = NULL;
01535 int fsize = 0;
01536 STATUS status=FAILED;
01537 STAT stat;
01538 char *ext = strrchr(file,'.');
01539 FILE *fp;
01540 int move=0;
01541
01542 fp = fopen(file,"r");
01543 if (fp==NULL)
01544 goto Failed;
01545 if (FSTAT(fileno(fp),&stat)==0)
01546 buffer = malloc(fsize=stat.st_size+2);
01547 output_verbose("file '%s' is %d bytes long", file,fsize);
01548 if (buffer==NULL)
01549 {
01550 output_error("unable to allocate buffer for file '%s': %s", file, strerror(errno));
01551 errno = ENOMEM;
01552 goto Done;
01553 }
01554 else
01555 p=buffer;
01556 if (buffer_read(fp,buffer,file,fsize)==0)
01557 {
01558 fclose(fp);
01559 goto Failed;
01560 }
01561 fclose(fp);
01562
01563 /* reset line counter for parser */
01564 linenum = 1;
01565 while (*p!='\0')
01566 {
01567 move = gridlabd_file(p);
01568 if (move==0)
01569 break;
01570 p+=move;
01571 }
01572 status = (*p=='\0') ? SUCCESS : FAILED;
01573 if (status==FAILED)
01574 {
01575 output_message("%s(%d): load failed", file, linenum);
01576 if (p==0)
01577 output_error("%s doesn't appear to be a GLM file", file);
01578 goto Failed;
01579 }
01580 else if ((status=load_resolve_all())==FAILED)
01581 goto Failed;
01582
01583 /* establish ranks */
01584 for (obj=first?first:object_get_first(); obj!=NULL; obj=obj->next)
01585 object_set_parent(obj,obj->parent);
01586 output_verbose("%d object%s loaded", object_get_count(), object_get_count()>1?"s":"");
01587 goto Done;
01588 Failed:
01589 if (errno!=0){
01590 output_error("unable to load '%s': %s", file, strerror(errno));
01591 }
01592 Done:
01593 free(buffer);
01594 free_index();
01595 linenum=0;
01596 return status;
01597 }
01598
01604 STATUS loadall(char *file){
01605 char *buffer = NULL, *p = NULL;
01606 char *ext = strrchr(file,'.');
01607 unsigned int old_obj_count = object_get_count();
01608 unsigned int new_obj_count = 0;
01609 unsigned int i;
01610 STATUS load_status = FAILED;
01611
01612 if(old_obj_count > 1){
01613 output_error("loadall: only one file load is supported at this time.");
01614 return FAILED; /* not what they expected--do not proceed */
01615 }
01616
01617 /* handle default extension */
01618 strcpy(filename,file);
01619 if (ext==NULL || ext<file+strlen(file)-5)
01620 {
01621 ext = filename+strlen(filename);
01622 strcat(filename,".glm");
01623 }
01624
01625 if(ext==NULL || strcmp(ext, ".glm")==0)
01626 load_status = loadall_glm(filename);
01627 else if(strcmp(ext, ".xml")==0)
01628 load_status = loadall_xml(filename);
01629 else
01630 output_error("%s: unable to load unknown file type", filename, ext);
01631
01632 new_obj_count = object_get_count();
01633
01634 if((load_status == FAILED) && (old_obj_count < new_obj_count)){
01635 for(i = old_obj_count+1; i <= new_obj_count; ++i){
01636 object_remove_by_id(i);
01637 }
01638 }
01639 return load_status;
01640 }
01641