00001
00010 #include <ctype.h>
00011 #ifdef WIN32
00012 #include <io.h>
00013 #else
00014 #include <unistd.h>
00015 #endif
00016 #include "globals.h"
00017 #include "output.h"
00018 #include "find.h"
00019 #include "aggregate.h"
00020 #include "module.h"
00021
00022 static FINDTYPE invar_types[] = {FT_ID, FT_SIZE, FT_CLASS, FT_PARENT, FT_RANK, FT_NAME, FT_LAT, FT_LONG, FT_INSVC, FT_OUTSVC, FT_MODULE, 0};
00023
00024 static int compare_int(int64 a, FINDOP op, int64 b)
00025 {
00026 switch (op) {
00027 case EQ: return a==b;
00028 case LT: return a<b;
00029 case GT: return a>b;
00030 case LE: return a<=b;
00031 case GE: return a>=b;
00032 case NE: return a!=b;
00033 default:
00034 output_error("compare op %d not supported on integers", op);
00035 return 0;
00036 }
00037 }
00038
00039 static int compare_int64(int64 a, FINDOP op, int64 b){
00040 return compare_int(a, op, b);
00041 }
00042
00043 static int compare_int32(int32 a, FINDOP op, int64 b)
00044 {
00045 switch (op) {
00046 case EQ: return a==b;
00047 case LT: return a<b;
00048 case GT: return a>b;
00049 case LE: return a<=b;
00050 case GE: return a>=b;
00051 case NE: return a!=b;
00052 default:
00053 output_error("compare op %d not supported on integers", op);
00054 return 0;
00055 }
00056 }
00057
00058 static int compare_int16(int16 a, FINDOP op, int64 b)
00059 {
00060 switch (op) {
00061 case EQ: return a==b;
00062 case LT: return a<b;
00063 case GT: return a>b;
00064 case LE: return a<=b;
00065 case GE: return a>=b;
00066 case NE: return a!=b;
00067 default:
00068 output_error("compare op %d not supported on integers", op);
00069 return 0;
00070 }
00071 }
00072
00073 static int compare_double(double a, FINDOP op, double b)
00074 {
00075 switch (op) {
00076 case EQ: return a==b;
00077 case LT: return a<b;
00078 case GT: return a>b;
00079 case LE: return a<=b;
00080 case GE: return a>=b;
00081 case NE: return a!=b;
00082 default:
00083 output_error("compare op %d not supported on doubles", op);
00084 return 0;
00085 }
00086 }
00087
00088 static int compare_string(char *a, FINDOP op, char *b)
00089 {
00090 switch (op) {
00091 case SAME: op=EQ; goto CompareInt;
00092 case BEFORE: op=LT; goto CompareInt;
00093 case AFTER: op=GT; goto CompareInt;
00094 case DIFF: op=NE; goto CompareInt;
00095 case LIKE: return match(a, b);
00096 case EQ:
00097 case LT:
00098 case GT:
00099 case LE:
00100 case GE:
00101 case NE:
00102 if (!(isdigit(a[0])||a[0]=='+'||a[0]=='-')&&!(isdigit(b[0])||b[0]=='+'||b[0]=='-'))
00103 output_warning("compare of strings using numeric op usually does not work");
00104 return compare_double(atof(a),op,atof(b));
00105 default:
00106 output_error("compare op %d not supported on strings", op);
00107 return 0;
00108 }
00109 CompareInt:
00110 return compare_int((int64)strcmp(a,b),op,0);
00111
00112 }
00113
00114 static int compare_property(OBJECT *obj, char *propname, FINDOP op, void *value)
00115 {
00117 char *propval = object_property_to_string(obj,propname);
00118 if (propval==NULL) return 0;
00119 return compare_string(propval,op,(char*)value);
00120 }
00121
00125 static int compare_property_alt(OBJECT *obj, char *propname, FINDOP op, void *value){
00126 complex *complex_target = NULL;
00127 char *char_target = NULL;
00128 int16 *int16_target = NULL;
00129 int32 *int32_target = NULL;
00130 int64 *int64_target = NULL;
00131 PROPERTY *prop = object_get_property(obj, propname);
00132 switch(prop->ptype){
00133 case PT_void:
00134 return 0;
00135 case PT_double:
00136 break;
00137 case PT_complex:
00138 complex_target = object_get_complex(obj, prop);
00139 if(complex_target == NULL)
00140 return 0;
00141 break;
00142 case PT_enumeration:
00143 case PT_set:
00144 break;
00145 case PT_int16:
00146 int16_target = (int16 *)object_get_int16(obj, prop);
00147 if(int16_target == NULL)
00148 return 0;
00149 return compare_int16(*int16_target, op, *(int64 *)value);
00150 case PT_int32:
00151 int32_target = (int32 *)object_get_int32(obj, prop);
00152 return compare_int32(*int32_target, op, *(int64 *)value);
00153 break;
00154 case PT_int64:
00155 int64_target = (int64 *)object_get_int64(obj, prop);
00156 return compare_int64(*int64_target, op, *(int64 *)value);
00157 break;
00158 case PT_char8:
00159 case PT_char32:
00160 case PT_char256:
00161 case PT_char1024:
00162 char_target = (char *)object_get_string(obj, prop);
00163 if(char_target == NULL)
00164 return 0;
00165 return compare_string(char_target, op, value);
00166 break;
00167 case PT_object:
00168
00169 break;
00170 case PT_bool:
00171 break;
00172 case PT_timestamp:
00173 case PT_double_array:
00174 case PT_complex_array:
00175 break;
00176 #ifdef USE_TRIPLETS
00177 case PT_triple:
00178 case PT_triplex:
00179 break;
00180 #endif
00181 default:
00182 output_error("");
00183 return 0;
00184 }
00185 }
00186
00187 static int compare(OBJECT *obj, FINDTYPE ftype, FINDOP op, void *value, char *propname)
00188 {
00189 switch (ftype) {
00190 case FT_ID: return compare_int((int64)obj->id,op,(int64)*(OBJECTNUM*)value);
00191 case FT_SIZE: return compare_int((int64)obj->size,op,(int64)*(int*)value);
00192 case FT_CLASS: return compare_string((char*)obj->oclass->name,op,(char*)value);
00193 case FT_MODULE: return compare_string((char*)obj->oclass->module->name,op,(char*)value);
00194 case FT_RANK: return compare_int((int64)obj->rank,op,(int64)*(int*)value);
00195 case FT_CLOCK: return compare_int((int64)obj->clock,op,(int64)*(TIMESTAMP*)value);
00196 case FT_PROPERTY: return compare_property(obj,propname,op,value);
00197 default:
00198 output_error("findtype %s not supported", ftype);
00199 return 0;
00200 }
00201 }
00202
00203 FINDLIST *new_list(unsigned int n)
00204 {
00205 unsigned int size = (n>>3)+1;
00206 FINDLIST *list = malloc(sizeof(FINDLIST)+size-1);
00207 if (list==NULL)
00208 {
00209 errno=ENOMEM;
00210 return NULL;
00211 }
00212 memset(list->result,0,size);
00213 list->result_size = size;
00214 list->hit_count = 0;
00215 return list;
00216 }
00217 #define SIZE(L) ((L).result_size)
00218 #define COUNT(L) ((L).hit_count)
00219 #define FOUND(L,N) (((L).result[(N)>>3]&(1<<((N)&0x7)))!=0)
00220 #define ADDOBJ(L,N) (!FOUND((L),(N))?((L).result[(N)>>3]|=(1<<((N)&0x7)),++((L).hit_count)):(L).hit_count)
00221 #define DELOBJ(L,N) (FOUND((L),(N))?((L).result[(N)>>3]&=~(1<<((N)&0x7)),--((L).hit_count)):(L).hit_count)
00222 #define ADDALL(L) ((L).hit_count=object_get_count(),memset((L).result,0xff,(L).result_size))
00223 #define DELALL(L) ((L).hit_count=object_get_count(),memset((L).result,0x00,(L).result_size))
00224
00225 FINDLIST *find_runpgm(FINDLIST *list, FINDPGM *pgm);
00226 FINDPGM *find_mkpgm(char *expression);
00227
00282 FINDLIST *find_objects(FINDLIST *start, ...)
00283 {
00284 OBJECT *obj;
00285 FINDLIST *result = start;
00286 if (start==FL_NEW || start==FL_GROUP)
00287 {
00288 result=new_list(object_get_count());
00289 ADDALL(*result);
00290 }
00291
00292 if (start==FL_GROUP)
00293 {
00294 FINDPGM *pgm;
00295 va_list(ptr);
00296 va_start(ptr,start);
00297 pgm = find_mkpgm(va_arg(ptr,char*));
00298 if (pgm!=NULL){
00299 return find_runpgm(result,pgm);
00300 } else {
00301 va_end(ptr);
00302 DELALL(*result);
00303 return result;
00304 }
00305 }
00306
00307 for (obj=object_get_first(); obj!=NULL; obj=obj->next)
00308 {
00309 FINDTYPE ftype;
00310 va_list(ptr);
00311 va_start(ptr,start);
00312 while ((ftype=va_arg(ptr,FINDTYPE)) != FT_END)
00313 {
00314 int invert=0;
00315 int parent=0;
00316 FINDOP conj=AND;
00317 FINDOP op;
00318 char *propname = NULL;
00319 void *value;
00320 OBJECT *target=obj;
00321
00322
00323 if (ftype==AND || ftype==OR)
00324 {
00325 conj=ftype;
00326 ftype = va_arg(ptr, FINDTYPE);
00327 }
00328
00329
00330 while (ftype==FT_PARENT)
00331 {
00332 ftype=va_arg(ptr,FINDTYPE);
00333 parent++;
00334 }
00335
00336
00337 if (ftype==FT_PROPERTY)
00338 propname=va_arg(ptr,char*);
00339
00340
00341 op = va_arg(ptr,FINDOP);
00342
00343
00344 if (op==NOT)
00345 {
00346 invert=1;
00347 op = va_arg(ptr,FINDOP);
00348 }
00349
00350
00351 switch (ftype) {
00352 static int ival;
00353 static char *sval;
00354 static OBJECTNUM oval;
00355 static TIMESTAMP tval;
00356 static double rval;
00357 case FT_PARENT:
00358 case FT_ID:
00359 oval = va_arg(ptr,OBJECTNUM);
00360 value = &oval;
00361 break;
00362 case FT_SIZE:
00363 case FT_RANK:
00364 ival = va_arg(ptr,int);
00365 value = &ival;
00366 break;
00367 case FT_INSVC:
00368 case FT_OUTSVC:
00369 case FT_CLOCK:
00370 tval = va_arg(ptr,TIMESTAMP);
00371 value = &tval;
00372 break;
00373 case FT_LAT:
00374 case FT_LONG:
00375 rval = va_arg(ptr, double);
00376 value = &rval;
00377 break;
00378 case FT_CLASS:
00379 case FT_NAME:
00380 case FT_PROPERTY:
00381 case FT_MODULE:
00382 sval = va_arg(ptr,char*);
00383 value = sval;
00384 break;
00385 default:
00386 output_error("invalid findtype means search is specified incorrectly or FT_END is probably missing");
00387 if (start == FL_NEW) free(result);
00388 return NULL;
00389 }
00390
00391
00392 while (parent-- > 0 && target != NULL)
00393 target = target->parent;
00394
00395
00396 if (target != NULL)
00397 {
00398
00399 if (compare(target,ftype,op,value,propname)!=invert)
00400 {
00401 if (conj==OR)
00402 ADDOBJ(*result,obj->id);
00403 }
00404 else
00405 {
00406 if (conj==AND)
00407 DELOBJ(*result,obj->id);
00408 }
00409 }
00410 }
00411 va_end(ptr);
00412 }
00413 return result;
00414 }
00415
00420 int find_makearray(FINDLIST *list,
00421 OBJECT ***objs)
00422 {
00423 OBJECT *obj=find_first(list);
00424 int n = list->hit_count, i;
00425 if (n<=0 || obj==NULL)
00426 return 0;
00427 (*objs) = (OBJECT**)malloc(sizeof(OBJECT*)*(n+1));
00428 for ( i=0 ; i<n && obj!=NULL; obj=find_next(list,obj),i++)
00429 (*objs)[i] = obj;
00430 objs[n]=NULL;
00431 return n;
00432 }
00433
00438 OBJECT *find_first(FINDLIST *list)
00439 {
00440 return find_next(list,NULL);
00441 }
00442
00446 OBJECT *find_next(FINDLIST *list,
00447 OBJECT *obj)
00448 {
00449 if (obj==NULL)
00450 obj = object_get_first();
00451 else
00452 obj = obj->next;
00453 while (obj!=NULL && !FOUND(*list,obj->id))
00454 obj=obj->next;
00455
00456 return obj;
00457 }
00458
00459
00460
00461
00462
00463 #define VALUE(X,T,M) ((X).isconstant?(X).value.constant.M:*((X).value.ref.T))
00464
00465 int compare_pointer_eq(void *a, FINDVALUE b) { return *(void**)a==b.pointer;}
00466 int compare_pointer_ne(void *a, FINDVALUE b) { return *(void**)a!=b.pointer;}
00467 int compare_pointer_lt(void *a, FINDVALUE b) { return *(void**)a<b.pointer;}
00468 int compare_pointer_gt(void *a, FINDVALUE b) { return *(void**)a>b.pointer;}
00469 int compare_pointer_le(void *a, FINDVALUE b) { return *(void**)a<=b.pointer;}
00470 int compare_pointer_ge(void *a, FINDVALUE b) { return *(void**)a>=b.pointer;}
00471
00472 int compare_integer16_eq(void *a, FINDVALUE b) { return *(int16*)a==(int16)b.integer;}
00473 int compare_integer16_ne(void *a, FINDVALUE b) { return *(int16*)a!=(int16)b.integer;}
00474 int compare_integer16_lt(void *a, FINDVALUE b) { return *(int16*)a<(int16)b.integer;}
00475 int compare_integer16_gt(void *a, FINDVALUE b) { return *(int16*)a>(int16)b.integer;}
00476 int compare_integer16_le(void *a, FINDVALUE b) { return *(int16*)a<=(int16)b.integer;}
00477 int compare_integer16_ge(void *a, FINDVALUE b) { return *(int16*)a>=(int16)b.integer;}
00478
00479 int compare_integer32_eq(void *a, FINDVALUE b) { return *(int32*)a==(int32)b.integer;}
00480 int compare_integer32_ne(void *a, FINDVALUE b) { return *(int32*)a!=(int32)b.integer;}
00481 int compare_integer32_lt(void *a, FINDVALUE b) { return *(int32*)a<(int32)b.integer;}
00482 int compare_integer32_gt(void *a, FINDVALUE b) { return *(int32*)a>(int32)b.integer;}
00483 int compare_integer32_le(void *a, FINDVALUE b) { return *(int32*)a<=(int32)b.integer;}
00484 int compare_integer32_ge(void *a, FINDVALUE b) { return *(int32*)a>=(int32)b.integer;}
00485
00486 int compare_integer64_eq(void *a, FINDVALUE b) { return *(int64*)a==(int64)b.integer;}
00487 int compare_integer64_ne(void *a, FINDVALUE b) { return *(int64*)a!=(int64)b.integer;}
00488 int compare_integer64_lt(void *a, FINDVALUE b) { return *(int64*)a<(int64)b.integer;}
00489 int compare_integer64_gt(void *a, FINDVALUE b) { return *(int64*)a>(int64)b.integer;}
00490 int compare_integer64_le(void *a, FINDVALUE b) { return *(int64*)a<=(int64)b.integer;}
00491 int compare_integer64_ge(void *a, FINDVALUE b) { return *(int64*)a>=(int64)b.integer;}
00492
00493 int compare_integer_eq(void *a, FINDVALUE b) { return *(long*)a==(long)b.integer;}
00494 int compare_integer_ne(void *a, FINDVALUE b) { return *(long*)a!=(long)b.integer;}
00495 int compare_integer_lt(void *a, FINDVALUE b) { return *(long*)a<(long)b.integer;}
00496 int compare_integer_gt(void *a, FINDVALUE b) { return *(long*)a>(long)b.integer;}
00497 int compare_integer_le(void *a, FINDVALUE b) { return *(long*)a<=(long)b.integer;}
00498 int compare_integer_ge(void *a, FINDVALUE b) { return *(long*)a>=(long)b.integer;}
00499
00500 int compare_real_eq(void *a, FINDVALUE b) { return *(double*)a==b.real;}
00501 int compare_real_ne(void *a, FINDVALUE b) { return *(double*)a!=b.real;}
00502 int compare_real_lt(void *a, FINDVALUE b) { return *(double*)a<b.real;}
00503 int compare_real_gt(void *a, FINDVALUE b) { return *(double*)a>b.real;}
00504 int compare_real_le(void *a, FINDVALUE b) { return *(double*)a<=b.real;}
00505 int compare_real_ge(void *a, FINDVALUE b) { return *(double*)a>=b.real;}
00506
00507
00508 int compare_string_eq(void *a, FINDVALUE b) { return *(char **)a != NULL && strcmp(*(char**)a,b.string)==0;}
00509 int compare_string_ne(void *a, FINDVALUE b) { return *(char **)a != NULL && strcmp(*(char**)a,b.string)!=0;}
00510 int compare_string_lt(void *a, FINDVALUE b) { return *(char **)a != NULL && strcmp(*(char**)a,b.string)<0;}
00511 int compare_string_gt(void *a, FINDVALUE b) { return *(char **)a != NULL && strcmp(*(char**)a,b.string)>0;}
00512 int compare_string_le(void *a, FINDVALUE b) { return *(char **)a != NULL && strcmp(*(char**)a,b.string)<=0;}
00513 int compare_string_ge(void *a, FINDVALUE b) { return *(char **)a != NULL && strcmp(*(char**)a,b.string)>=0;}
00514
00515 int compare_pointer_li(void *a, FINDVALUE b) {return 0;}
00516
00517 int compare_integer_li(void *a, FINDVALUE b) {
00518 char temp[256];
00519 if(convert_from_int64(temp, 256, &(b.integer), NULL))
00520 return match(*(char **)a, temp);
00521 return 0;
00522 }
00523
00524 int compare_real_li(void *a, FINDVALUE b) {
00525 char temp[256];
00526 if(convert_from_double(temp, 256, &(b.real), NULL))
00527 return match(*(char **)a, temp);
00528 return 0;
00529 }
00530
00531 int compare_string_li(void *a, FINDVALUE b) {return match(*(char **)a, b.string);}
00532
00533 int compare_integer16_li(void *a, FINDVALUE b) {
00534 char temp[256];
00535 if(convert_from_int16(temp, 256, &(b.integer), NULL))
00536 return match(*(char **)a, temp);
00537 return 0;
00538 }
00539
00540 int compare_integer32_li(void *a, FINDVALUE b) {
00541 char temp[256];
00542 if(convert_from_int32(temp, 256, &(b.integer), NULL))
00543 return match(*(char **)a, temp);
00544 return 0;
00545 }
00546
00547 int compare_integer64_li(void *a, FINDVALUE b) {
00548 char temp[256];
00549 if(convert_from_int64(temp, 256, &(b.integer), NULL))
00550 return match(*(char **)a, temp);
00551 return 0;
00552 }
00553
00554 int compare_pointer_nl(void *a, FINDVALUE b) {return 1;}
00555
00556 int compare_integer_nl(void *a, FINDVALUE b) {
00557 char temp[256];
00558 if(convert_from_int64(temp, 256, &(b.integer), NULL))
00559 return 1 != match(*(char **)a, temp);
00560 return 0;
00561 }
00562
00563 int compare_real_nl(void *a, FINDVALUE b) {
00564 char temp[256];
00565 if(convert_from_double(temp, 256, &(b.real), NULL))
00566 return 1 != match(*(char **)a, temp);
00567 return 0;
00568 }
00569
00570 int compare_string_nl(void *a, FINDVALUE b) {
00571 return 1 != match(*(char **)a, b.string);
00572 }
00573
00574 int compare_integer16_nl(void *a, FINDVALUE b) {
00575 char temp[256];
00576 if(convert_from_int16(temp, 256, &(b.integer), NULL))
00577 return 1 != match(*(char **)a, temp);
00578 return 0;
00579 }
00580
00581 int compare_integer32_nl(void *a, FINDVALUE b) {
00582 char temp[256];
00583 if(convert_from_int32(temp, 256, &(b.integer), NULL))
00584 return 1 != match(*(char **)a, temp);
00585 return 0;
00586 }
00587
00588 int compare_integer64_nl(void *a, FINDVALUE b) {
00589 char temp[256];
00590 if(convert_from_int64(temp, 256, &(b.integer), NULL))
00591 return 1 != match(*(char **)a, temp);
00592 return 0;
00593 }
00594
00595 static void findlist_add(FINDLIST *list, OBJECT *obj)
00596 {
00597 ADDOBJ(*list,obj->id);
00598 }
00599 static void findlist_del(FINDLIST *list, OBJECT *obj)
00600 {
00601 DELOBJ(*list,obj->id);
00602 }
00603 static void findlist_nop(FINDLIST *list, OBJECT *obj)
00604 {
00605 }
00606
00607 PGMCONSTFLAGS find_pgmconstants(FINDPGM *pgm)
00608 {
00609 if (pgm==NULL)
00610 return 0;
00611
00612
00613 while (pgm->next!=NULL) pgm=pgm->next;
00614 return pgm->constflags;
00615
00616 }
00617
00618 static FINDPGM *add_pgm(FINDPGM **pgm, COMPAREFUNC op, unsigned short target, FINDVALUE value, FOUNDACTION pos, FOUNDACTION neg)
00619 {
00620
00621 FINDPGM *item = (FINDPGM*)malloc(sizeof(FINDPGM));
00622 if (item!=NULL)
00623 {
00624 item->constflags = CF_CONSTANT;
00625 item->op = op;
00626 item->target = target;
00627 item->value = value;
00628 item->pos = pos;
00629 item->neg = neg;
00630 item->next = NULL;
00631
00632
00633 if (*pgm!=NULL)
00634 {
00635 FINDPGM *tail = *pgm;
00636
00637 item->constflags = tail->constflags;
00638
00639
00640 while (tail->next!=NULL) tail=tail->next;
00641 tail->next = item;
00642 }
00643 else
00644 *pgm = item;
00645 }
00646 else
00647 errno = ENOMEM;
00648
00649 return item;
00650 }
00651 FINDLIST *find_runpgm(FINDLIST *list, FINDPGM *pgm)
00652 {
00653 if (list==NULL)
00654 {
00655 list=new_list(object_get_count());
00656 ADDALL(*list);
00657 }
00658 if (pgm!=NULL)
00659 {
00660 OBJECT *obj;
00661 for (obj=find_first(list); obj!=NULL; obj=find_next(list,obj))
00662 {
00663 if ((*pgm->op)((void*)(((char*)obj)+pgm->target),pgm->value))
00664 { if (pgm->pos) (*pgm->pos)(list,obj); }
00665 else
00666 { if (pgm->neg) (*pgm->neg)(list,obj); }
00667 }
00668 find_runpgm(list,pgm->next);
00669 }
00670 return list;
00671 }
00672
00673 #define PARSER char *_p
00674 #define START int _m=0, _n=0;
00675 #define ACCEPT { _n+=_m; _p+=_m; _m=0; }
00676 #define HERE (_p+_m)
00677 #define OR {_m=0;}
00678 #define REJECT { return 0; }
00679 #define WHITE (_m+=white(HERE))
00680 #define LITERAL(X) ((_m+=literal(HERE,(X)))>0)
00681 #define TERM(X) ((_m+=(X))>0)
00682 #define COPY(X) {size--; (X)[_n++]=*_p++;}
00683 #define DONE return _n;
00684
00685 void syntax_error(char *p)
00686 {
00687 char context[16], *nl;
00688 strncpy(context,p,15);
00689 nl = strchr(context,'\n');
00690 if (nl!=NULL) *nl='\0'; else context[15]='\0';
00691 if (strlen(context)>0)
00692 output_message("find expression syntax error at '%s...'", context);
00693 else
00694 output_message("find expression syntax error");
00695 }
00696
00697 static int white(PARSER)
00698 {
00699 if (*_p=='\0' || !isspace(*_p))
00700 return 0;
00701
00702 return white(_p+1)+1;
00703 }
00704
00705 static int comment(PARSER)
00706 {
00707 int _n = white(_p);
00708 if (_p[_n]=='#')
00709 {
00710 while (_p[_n]!='\n')
00711 _n++;
00712 }
00713 return _n;
00714 }
00715
00716 static int literal(PARSER, char *text)
00717 {
00718 if (strncmp(_p,text,strlen(text))==0)
00719 return (int)strlen(text);
00720 return 0;
00721 }
00722
00723 static int name(PARSER, char *result, int size)
00724 {
00725 START;
00726 while (size>1 && isalpha(*_p) || isdigit(*_p) || *_p=='_') COPY(result);
00727 result[_n]='\0';
00728 DONE;
00729 }
00730
00731 static int value(PARSER, char *result, int size)
00732 {
00733 START;
00734 while (size>1 && *_p!='\0' && *_p!=';' && *_p!='\n') COPY(result);
00735 result[_n]='\0';
00736 return _n;
00737 }
00738
00739 static int integer(PARSER, int64 *value)
00740 {
00741 char result[256];
00742 int size=sizeof(result);
00743 START;
00744 while (size>1 && isdigit(*_p)) COPY(result);
00745 result[_n]='\0';
00746 *value=atoi64(result);
00747 return _n;
00748 }
00749
00750 static int real(PARSER, double *value)
00751 {
00752 char result[256];
00753 int size=sizeof(result);
00754 START;
00755 if (*_p=='+' || *_p=='-') COPY(result);
00756 while (size>1 && isdigit(*_p)) COPY(result);
00757 if (*_p=='.') COPY(result);
00758 while (size>1 && isdigit(*_p)) COPY(result);
00759 if (*_p=='E' || *_p=='e') COPY(result);
00760 if (*_p=='+' || *_p=='-') COPY(result);
00761 while (size>1 && isdigit(*_p)) COPY(result);
00762 result[_n]='\0';
00763 *value=atof(result);
00764 return _n;
00765 }
00766
00767 static int time_value_seconds(PARSER, TIMESTAMP *t)
00768 {
00769 START;
00770 if WHITE ACCEPT;
00771 if (TERM(integer(HERE,t)) && LITERAL("s")) { *t *= TS_SECOND; ACCEPT; DONE;}
00772 OR
00773 if (TERM(integer(HERE,t)) && LITERAL("S")) { *t *= TS_SECOND; ACCEPT; DONE;}
00774 REJECT;
00775 }
00776
00777 static int time_value_minutes(PARSER, TIMESTAMP *t)
00778 {
00779 START;
00780 if WHITE ACCEPT;
00781 if (TERM(integer(HERE,t)) && LITERAL("m")) { *t *= 60*TS_SECOND; ACCEPT; DONE;}
00782 OR
00783 if (TERM(integer(HERE,t)) && LITERAL("M")) { *t *= 60*TS_SECOND; ACCEPT; DONE;}
00784 REJECT;
00785 }
00786
00787 static int time_value_hours(PARSER, TIMESTAMP *t)
00788 {
00789 START;
00790 if WHITE ACCEPT;
00791 if (TERM(integer(HERE,t)) && LITERAL("h")) { *t *= 3600*TS_SECOND; ACCEPT; DONE;}
00792 OR
00793 if (TERM(integer(HERE,t)) && LITERAL("H")) { *t *= 3600*TS_SECOND; ACCEPT; DONE;}
00794 REJECT;
00795 }
00796
00797 static int time_value_days(PARSER, TIMESTAMP *t)
00798 {
00799 START;
00800 if WHITE ACCEPT;
00801 if (TERM(integer(HERE,t)) && LITERAL("d")) { *t *= 86400*TS_SECOND; ACCEPT; DONE;}
00802 OR
00803 if (TERM(integer(HERE,t)) && LITERAL("D")) { *t *= 86400*TS_SECOND; ACCEPT; DONE;}
00804 REJECT;
00805 }
00806
00807 static int time_value_datetime(PARSER, TIMESTAMP *t)
00808 {
00809 int64 Y,m,d,H,M,S;
00810 START;
00811 if WHITE ACCEPT;
00812 if (LITERAL("'")
00813 && TERM(integer(HERE,&Y)) && LITERAL("-")
00814 && TERM(integer(HERE,&m)) && LITERAL("-")
00815 && TERM(integer(HERE,&d)) && LITERAL(" ")
00816 && TERM(integer(HERE,&H)) && LITERAL(":")
00817 && TERM(integer(HERE,&M)) && LITERAL(":")
00818 && TERM(integer(HERE,&S)) && LITERAL("'"))
00819 {
00820 struct tm dt = {(int)S,(int)M,(int)H,(int)d,(int)m-1,(int)Y-1900,0,0,0};
00821 int64 tt = mktime(&dt);
00822 if (tt!=-1) {*t=(int64)tt*TS_SECOND; ACCEPT; DONE;}
00823 }
00824 REJECT;
00825 }
00826
00827 static int time_value(PARSER, TIMESTAMP *t)
00828 {
00829 START;
00830 if WHITE ACCEPT;
00831 if TERM(time_value_seconds(HERE,t)) {ACCEPT; DONE; }
00832 OR
00833 if TERM(time_value_minutes(HERE,t)) {ACCEPT; DONE; }
00834 OR
00835 if TERM(time_value_hours(HERE,t)) {ACCEPT; DONE; }
00836 OR
00837 if TERM(time_value_days(HERE,t)) {ACCEPT; DONE; }
00838 OR
00839 if TERM(time_value_datetime(HERE,t)) {ACCEPT; DONE; }
00840 OR
00841 if TERM(integer(HERE,t)) { ACCEPT; DONE; }
00842 else REJECT;
00843 DONE;
00844 }
00845
00846 static int compare_op(PARSER, FINDOP *op)
00847 {
00848
00849 if (strncmp(_p,"!=", 2)==0) {*op=NE; return 2;}
00850 if (strncmp(_p,"<=", 2)==0) {*op=LE; return 2;}
00851 if (strncmp(_p,">=", 2)==0) {*op=GE; return 2;}
00852 if (strncmp(_p,"!~", 2)==0) {*op=UNLIKE; return 2;}
00853
00854 if (strncmp(_p,"=", 1)==0) {*op=EQ; return 1;}
00855 if (strncmp(_p,"<", 1)==0) {*op=LT; return 1;}
00856 if (strncmp(_p,">", 1)==0) {*op=GT; return 1;}
00857 if (strncmp(_p,"~", 1)==0) {*op=LIKE; return 1;}
00858 return 0;
00859 }
00860
00861 struct {
00862 COMPAREFUNC pointer, integer, real, string;
00863 } comparemap[] =
00864 { {compare_pointer_eq, compare_integer_eq, compare_real_eq, compare_string_eq},
00865 {compare_pointer_lt, compare_integer_lt, compare_real_lt, compare_string_lt},
00866 {compare_pointer_gt, compare_integer_gt, compare_real_gt, compare_string_gt},
00867 {compare_pointer_ne, compare_integer_ne, compare_real_ne, compare_string_ne},
00868 {compare_pointer_le, compare_integer_le, compare_real_le, compare_string_le},
00869 {compare_pointer_ge, compare_integer_ge, compare_real_ge, compare_string_ge},
00870 {compare_pointer_li, compare_integer_li, compare_real_li, compare_string_li},
00871 {compare_pointer_nl, compare_integer_nl, compare_real_nl, compare_string_nl}
00872 };
00873
00874 struct {
00875 COMPAREFUNC pointer, integer, real, string, int_16, int_32, int_64;
00876 } comparemap_ext[] =
00877 { {compare_pointer_eq, compare_integer_eq, compare_real_eq, compare_string_eq, compare_integer16_eq, compare_integer32_eq, compare_integer64_eq},
00878 {compare_pointer_lt, compare_integer_lt, compare_real_lt, compare_string_lt, compare_integer16_lt, compare_integer32_lt, compare_integer64_lt},
00879 {compare_pointer_gt, compare_integer_gt, compare_real_gt, compare_string_gt, compare_integer16_gt, compare_integer32_gt, compare_integer64_gt},
00880 {compare_pointer_ne, compare_integer_ne, compare_real_ne, compare_string_ne, compare_integer16_ne, compare_integer32_ne, compare_integer64_ne},
00881 {compare_pointer_le, compare_integer_le, compare_real_le, compare_string_le, compare_integer16_le, compare_integer32_le, compare_integer64_le},
00882 {compare_pointer_ge, compare_integer_ge, compare_real_ge, compare_string_ge, compare_integer16_ge, compare_integer32_ge, compare_integer64_ge},
00883 {compare_pointer_li, compare_integer_li, compare_real_li, compare_string_li, compare_integer16_li, compare_integer32_li, compare_integer64_li},
00884 {compare_pointer_nl, compare_integer_nl, compare_real_nl, compare_string_nl, compare_integer16_nl, compare_integer32_nl, compare_integer64_nl},
00885 };
00886
00887
00888
00889 static int expression(PARSER, FINDPGM **pgm)
00890 {
00891 char32 pname;
00892 char256 pvalue;
00893 FINDOP op = EQ;
00894 START;
00895 if WHITE ACCEPT;
00896 if (TERM(name(HERE,pname,sizeof(pname))) && WHITE,TERM(compare_op(HERE,&op)) && WHITE,TERM(value(HERE,pvalue,sizeof(pvalue))))
00897 {
00898
00899 OBJECT _t;
00900 #define OFFSET(X) (unsigned short)((char*)&(_t.X) - (char*)&_t)
00901 if WHITE ACCEPT;
00902 if(op < 0 || op >= FINDOP_END){
00903 output_error("expression(): invalid find op!");
00904 REJECT;
00905 }
00906 if (strcmp(pname,"class")==0)
00907 {
00908 FINDVALUE v;
00909 CLASS *oclass = class_get_class_from_classname(pvalue);
00910 if (oclass==NULL)
00911 output_error("class '%s' not found", pvalue);
00912 else
00913 {
00914 v.pointer=(void*)oclass;
00915 add_pgm(pgm,comparemap[op].pointer,OFFSET(oclass),v,NULL,findlist_del);
00916 (*pgm)->constflags |= CF_CLASS;
00917 ACCEPT; DONE;
00918 }
00919 }
00920 if (strcmp(pname,"module")==0)
00921 {
00922 FINDVALUE v;
00923 MODULE *mod = module_find(pvalue);
00924 if (mod==NULL)
00925 output_error("module '%s' not found", pvalue);
00926 else
00927 {
00928 v.pointer=(void*)mod;
00929 add_pgm(pgm,comparemap[op].pointer,OFFSET(oclass),v,NULL,findlist_del);
00930 (*pgm)->constflags |= CF_MODULE;
00931 ACCEPT; DONE;
00932 }
00933 }
00934 else if (strcmp(pname,"id")==0)
00935 {
00936 FINDVALUE v;
00937 int idnum = atoi(pvalue);
00938 if(idnum < 0){
00939 output_error("ID '#%i' not found", idnum);
00940 } else {
00941 v.integer = idnum;
00942 add_pgm(pgm,comparemap[op].integer,OFFSET(id),v,NULL,findlist_del);
00943 (*pgm)->constflags |= CF_ID;
00944 ACCEPT;
00945 DONE;
00946 }
00947 }
00948 else if (strcmp(pname, "name") == 0)
00949 {
00950
00951 FINDVALUE v;
00952 strcpy(v.string, pvalue);
00953 printf("find(): v.string=\"%s\", pvalue=\"%s\"\n", v.string, pvalue);
00954 add_pgm(pgm, comparemap[op].string, OFFSET(name), v, NULL, findlist_del);
00955 (*pgm)->constflags |= CF_NAME;
00956 ACCEPT;
00957 DONE;
00958 }
00959 else if (strcmp(pname,"parent")==0)
00960 {
00961 FINDVALUE v;
00962 OBJECT *parent = object_find_name(pvalue);
00963 if (parent==NULL && strcmp(pvalue, "root") != 0 && strcmp(pvalue, "ROOT") != 0)
00964 output_error("parent '%s' not found", pvalue);
00965 else
00966 {
00967 v.pointer = (void*)parent;
00968 add_pgm(pgm,comparemap[op].pointer,OFFSET(parent),v,NULL,findlist_del);
00969 (*pgm)->constflags |= CF_PARENT;
00970 ACCEPT; DONE;
00971 }
00972 }
00973 else if (strcmp(pname,"rank")==0)
00974 {
00975 FINDVALUE v;
00976 int rank = atoi(pvalue);
00977 if (rank<0)
00978 output_error("rank %s is invalid", pvalue);
00979 else
00980 {
00981 v.integer = rank;
00982 add_pgm(pgm,comparemap[op].integer,OFFSET(rank),v,NULL,findlist_del);
00983 (*pgm)->constflags |= CF_RANK;
00984 ACCEPT; DONE;
00985 }
00986 }
00987 else if (strcmp(pname, "latitude") == 0)
00988 {
00989
00990 FINDVALUE v;
00991 int32 d = 0, m = 0;
00992 double s = 0.0, val = 0.0;
00993 char ns;
00994 if (sscanf(pvalue, "%d%c%d'%lf\"", &d, &ns, &m, &s) > 0)
00995 {
00996 val = (double)d+(double)m/60+s/3600;
00997 if (val >= 0 && val <= 90)
00998 {
00999 if (ns=='S')
01000 val = -val;
01001 else if (ns=='N')
01002 ;
01003 else
01004 REJECT;
01005 } else {
01006 REJECT;
01007 }
01008 v.real = val;
01009 add_pgm(pgm, comparemap[op].real, OFFSET(latitude), v, NULL, findlist_del);
01010 (*pgm)->constflags |= CF_LAT;
01011 ACCEPT; DONE;
01012 }
01013 }
01014 else if (strcmp(pname, "longitude") == 0)
01015 {
01016
01017 FINDVALUE v;
01018 int32 d = 0, m = 0;
01019 double s = 0.0, val = 0.0;
01020 char ns;
01021 if (sscanf(pvalue, "%d%c%d'%lf\"", &d, &ns, &m, &s) > 0)
01022 {
01023 val = (double)d+(double)m/60+s/3600;
01024 if (val >= 0 && val <= 180)
01025 {
01026 if (ns=='W')
01027 val = -val;
01028 else if (ns=='E')
01029 ;
01030 else
01031 REJECT;
01032 } else {
01033 REJECT;
01034 }
01035 v.real = val;
01036 add_pgm(pgm, comparemap[op].real, OFFSET(longitude), v, NULL, findlist_del);
01037 (*pgm)->constflags |= CF_LONG;
01038 ACCEPT; DONE;
01039 }
01040 }
01041 else if (strcmp(pname, "clock") == 0)
01042 {
01043 FINDVALUE v;
01044 v.integer = convert_to_timestamp(pvalue);
01045 if(v.integer == TS_NEVER)
01046 REJECT;
01047 add_pgm(pgm, comparemap[op].integer, OFFSET(clock), v, NULL, findlist_del);
01048 (*pgm)->constflags |= CF_CLOCK;
01049 ACCEPT; DONE;
01050 }
01051 else if (strcmp(pname, "insvc") == 0)
01052 {
01053 FINDVALUE v;
01054 v.integer = convert_to_timestamp(pvalue);
01055 printf("find insvc=%i\n", v.integer);
01056 if(v.integer == TS_NEVER)
01057 REJECT;
01058 add_pgm(pgm, comparemap[op].integer, OFFSET(in_svc), v, NULL, findlist_del);
01059 (*pgm)->constflags |= CF_INSVC;
01060 ACCEPT; DONE;
01061 }
01062 else if (strcmp(pname, "outsvc") == 0)
01063 {
01064 FINDVALUE v;
01065 v.integer = convert_to_timestamp(pvalue);
01066 if(v.integer == TS_NEVER)
01067 REJECT;
01068 add_pgm(pgm, comparemap[op].integer, OFFSET(out_svc), v, NULL, findlist_del);
01069 (*pgm)->constflags |= CF_OUTSVC;
01070 ACCEPT; DONE;
01071 }
01072 else if (strcmp(pname, "flags") == 0)
01073 {
01075
01076 output_error("find expression on %s not supported", pname);
01077 }
01078 else
01079 output_error("find expression refers to unknown or unsupported property '%s'", pname);
01080 }
01081 REJECT;
01082 }
01083
01084 static int expression_list(PARSER, FINDPGM **pgm)
01085 {
01086 START;
01087 if TERM(expression(HERE,pgm)) ACCEPT;
01088 if (WHITE,LITERAL(";") && TERM(expression_list(HERE,pgm))) { ACCEPT; DONE; }
01089 DONE;
01090 }
01091
01092 FINDPGM *find_mkpgm(char *search)
01093 {
01094 STATUS status=FAILED;
01095 FINDPGM *pgm = NULL;
01096 char *p = search;
01097 while (*p!='\0')
01098 {
01099 int move = expression_list(p,&pgm);
01100 if (move==0)
01101 break;
01102 p+=move;
01103 }
01104 return pgm;
01105 }
01106
01113 char *find_file(char *name,
01114 char *path,
01115 int mode)
01116 {
01117 static char filepath[1024];
01118 static char tempfp[1024];
01119 char *glpath = path?path:getenv("GLPATH");
01120 int found;
01121 char *dir = NULL;
01122
01123
01124
01125
01126
01127
01128 if(access(name, mode) == 0){
01129 strncpy(filepath, name, 1024);
01130 return filepath;
01131 }
01132 #ifdef WIN32
01133 if(module_get_exe_path(filepath, 1024)){
01134 sprintf(tempfp, "%s%s", filepath, name);
01135 if(access(tempfp, mode) == 0)
01136 return tempfp;
01137 sprintf(tempfp, "%setc\\%s", filepath, name);
01138 if(access(tempfp, mode) == 0)
01139 return tempfp;
01140 sprintf(tempfp, "%slib\\%s", filepath, name);
01141 if(access(tempfp, mode) == 0)
01142 return tempfp;
01143 }
01144 #else
01145 sprintf(tempfp, "/usr/lib/gridlabd/%s", name);
01146 if(access(tempfp, mode) == 0){
01147 return tempfp;
01148 }
01149 sprintf(tempfp, "/usr/etc/gridlabd/%s", name);
01150 if(access(tempfp, mode) == 0){
01151 return tempfp;
01152 }
01153 #endif
01154 strncpy(filepath,name,sizeof(filepath));
01155
01156
01157 while (!(found=(access(filepath,mode)==0)) && glpath!=NULL)
01158 {
01159 char envbuf[1024];
01160 #ifdef WIN32
01161 char *delim = ";";
01162 #else
01163 char *delim = ":";
01164 #endif
01165 strcpy(envbuf,glpath);
01166 dir = strtok(dir?NULL:envbuf,delim);
01167 if (dir==NULL)
01168 break;
01169 strcpy(filepath,dir);
01170 strcat(filepath,"/");
01171 strcat(filepath,name);
01172 }
01173 return found?filepath:NULL;
01174 }
01175