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