00001
00002 #include "drms.h"
00003 #include "drms_priv.h"
00004 #include "ctype.h"
00005 #include "xmem.h"
00006 #include "atoinc.h"
00007 #include "fitsexport.h"
00008
00009
00010 static int getstring(char **inn, char *out, int maxlen);
00011 static int getvalstring(char **inn, char *out, int maxlen);
00012
00013 static int getshort(char **in, int16_t *val, int parserline);
00014 static int getint(char **in, int *val, int parserline);
00015 static inline int prefixmatch(char *token, const char *pattern);
00016 static int gettoken(char **in, char *copy, int maxlen, int parserline);
00017 static int getvaltoken(char **in, DRMS_Type_t type, char *copy, int maxlen, int parserline);
00018
00019
00020 int getkeyword(char **line, int parserline);
00021 static int getnextline(char **start);
00022 static int parse_seriesinfo(char *desc, DRMS_Record_t *template);
00023 static int parse_segments(char *desc, DRMS_Record_t *template, HContainer_t *cparmkeys, int *keynum);
00024 static int parse_segment(char **in, DRMS_Record_t *template, int segnum, HContainer_t *cparmkeys, int *keynum);
00025 static int parse_keyword(char **in,
00026 DRMS_Record_t *ds,
00027 HContainer_t *slotted,
00028 int *keynum);
00029 static int parse_links(char *desc, DRMS_Record_t *template);
00030 static int parse_link(char **in, DRMS_Record_t *template, int linknum);
00031 static int parse_primaryindex(char *desc, DRMS_Record_t *template);
00032 static int parse_dbindex(char *desc, DRMS_Record_t *template);
00033
00034 static int keywordname_isreserved(const char *name);
00035
00036
00037
00038
00039
00040
00041 #define SKIPWS(p) {while(*p && ISBLANK(*p)) { ++p; }}
00042
00043 #define ISBLANK(c) (c==' ' || c=='\t' || c=='\r')
00044 #define TRY(__code__) {if ((__code__)) return 1;}
00045
00046
00047
00048
00049 #define GETDOUBLE(p, v) getdouble(p, v, __LINE__)
00050 #define GETSHORT(p, v) getshort(p, v, __LINE__)
00051 #define GETINT(p, v) getint(p, v, __LINE__)
00052 #define GETTOKEN(p, c, m) gettoken(p, c, m, __LINE__)
00053 #define GETVALTOKEN(p, t, c, m) getvaltoken(p, t, c, m, __LINE__)
00054 #define GETKEYWORD(p) getkeyword(p, __LINE__)
00055 #define GOTOFAILURE { parserline = __LINE__; goto failure; }
00056
00057 static int lineno;
00058
00059 static void FreeCparmKey(const void *v)
00060 {
00061
00062 void **vv = (void **)v;
00063 if (vv && *vv)
00064 {
00065 DRMS_Keyword_t *key = (DRMS_Keyword_t *)(*vv);
00066 drms_free_keyword_struct(key);
00067 free(key);
00068 }
00069 }
00070
00071 DRMS_Record_t *drms_parse_description(DRMS_Env_t *env, char *desc)
00072 {
00073 DRMS_Record_t *template = NULL;
00074 int keynum = 0;
00075 HContainer_t *cparmkeys = NULL;
00076
00077
00078 char *pc = desc;
00079 int winle = 0;
00080 int macle = 0;
00081 int crseen = 0;
00082
00083 while (pc && *pc)
00084 {
00085 if (!crseen)
00086 {
00087 if (*pc == '\r')
00088 {
00089 crseen = 1;
00090 }
00091 else if (*pc == '\n')
00092 {
00093
00094 break;
00095 }
00096 }
00097 else
00098 {
00099 if (*pc != '\n')
00100 {
00101 macle = 1;
00102 break;
00103 }
00104 else
00105 {
00106 winle = 1;
00107 break;
00108 }
00109 }
00110
00111 pc++;
00112 }
00113
00114 if (macle)
00115 {
00116 fprintf(stderr, "DRMS does not support JSD files with Mac line endings.\n");
00117 goto bailout;
00118 }
00119 else if (winle)
00120 {
00121 fprintf(stderr, "DRMS does not support JSD files with Windows line endings.\n");
00122 goto bailout;
00123 }
00124
00125 template = calloc(1, sizeof(DRMS_Record_t));
00126 XASSERT(template);
00127 template->seriesinfo = calloc(1, sizeof(DRMS_SeriesInfo_t));
00128 XASSERT(template->seriesinfo);
00129 template->env = env;
00130 template->init = 1;
00131 template->recnum = 0;
00132 template->sunum = -1;
00133 template->sessionid = 0;
00134 template->sessionns = NULL;
00135 template->su = NULL;
00136 template->seriesinfo->hasshadow = -1;
00137 template->seriesinfo->createshadow = 0;
00138
00139
00140 hcon_init(&template->segments, sizeof(DRMS_Segment_t), DRMS_MAXHASHKEYLEN,
00141 (void (*)(const void *)) drms_free_segment_struct,
00142 (void (*)(const void *, const void *)) drms_copy_segment_struct);
00143
00144 hcon_init(&template->links, sizeof(DRMS_Link_t), DRMS_MAXHASHKEYLEN,
00145 (void (*)(const void *)) drms_free_link_struct,
00146 (void (*)(const void *, const void *)) drms_copy_link_struct);
00147
00148 hcon_init(&template->keywords, sizeof(DRMS_Keyword_t), DRMS_MAXHASHKEYLEN,
00149 (void (*)(const void *)) drms_free_keyword_struct,
00150 (void (*)(const void *, const void *)) drms_copy_keyword_struct);
00151
00152
00153
00154 template->seriesinfo->pidx_num = 0;
00155
00156 template->seriesinfo->dbidx_num = 0;
00157
00158
00159
00160
00161 cparmkeys = hcon_create(sizeof(DRMS_Keyword_t *),
00162 DRMS_MAXKEYNAMELEN,
00163 FreeCparmKey,
00164 NULL,
00165 NULL,
00166 NULL,
00167 0);
00168
00169 lineno = 0;
00170 if (parse_seriesinfo(desc, template))
00171 {
00172 fprintf(stderr,"Failed to parse series info.\n");
00173 goto bailout;
00174 }
00175
00176 if (env->session->db_direct) {
00177 strcpy(template->seriesinfo->owner, env->session->db_handle->dbuser);
00178 }
00179
00180 lineno = 0;
00181 if (parse_segments(desc, template, cparmkeys, &keynum))
00182 {
00183 fprintf(stderr,"Failed to parse segment info.\n");
00184 goto bailout;
00185 }
00186
00187 if (template->seriesinfo->unitsize < 1 && (template->segments).num_total > 0)
00188 {
00189 fprintf(stderr,
00190 "The series unit size must be at least 1, but it is %d.\n",
00191 template->seriesinfo->unitsize);
00192 goto bailout;
00193 }
00194
00195
00196 lineno = 0;
00197 if (parse_links(desc, template))
00198 {
00199 fprintf(stderr,"Failed to parse links info.\n");
00200 goto bailout;
00201 }
00202
00203 lineno = 0;
00204 if (parse_keywords(desc, template, cparmkeys, &keynum))
00205 {
00206 fprintf(stderr,"Failed to parse keywords info.\n");
00207 goto bailout;
00208 }
00209
00210 lineno = 0;
00211
00212 if (parse_primaryindex(desc, template))
00213 {
00214 fprintf(stderr,"Failed to parse series info.\n");
00215 goto bailout;
00216 }
00217
00218 lineno = 0;
00219 if (parse_dbindex(desc, template))
00220 {
00221 fprintf(stderr,"Failed to parse series info.\n");
00222 goto bailout;
00223 }
00224
00225 if (cparmkeys)
00226 {
00227 hcon_destroy(&cparmkeys);
00228 }
00229
00230 #ifdef DEBUG
00231 printf("SERIES TEMPLATE ASSEMBLED FROM SERIES DEFINITION:\n");
00232 drms_print_record(template);
00233 #endif
00234 return template;
00235
00236 bailout:
00237 if (template)
00238 {
00239 hcon_free(&template->segments);
00240 hcon_free(&template->links);
00241 hcon_free(&template->keywords);
00242 free(template);
00243 }
00244
00245 if (cparmkeys)
00246 {
00247 hcon_destroy(&cparmkeys);
00248 }
00249 return NULL;
00250 }
00251
00252
00253 HContainer_t *drms_parse_keyworddesc(DRMS_Env_t *env, const char *desc, int *status)
00254 {
00255 DRMS_Record_t *fauxtemplate = NULL;
00256 char *copy = NULL;
00257 char *start = NULL;
00258 char *p = NULL;
00259 char *q = NULL;
00260 int keynum = 0;
00261 HContainer_t *keys = NULL;
00262 int len;
00263 HContainer_t *slotted = NULL;
00264 int rv = DRMS_SUCCESS;
00265
00266 lineno = 0;
00267
00268 slotted = hcon_create(sizeof(DRMS_Keyword_t *),
00269 DRMS_MAXKEYNAMELEN,
00270 NULL,
00271 NULL,
00272 NULL,
00273 NULL,
00274 0);
00275
00276 if (slotted)
00277 {
00278
00279
00280 start = copy = strdup(desc);
00281 if (copy)
00282 {
00283 len = getnextline(&start);
00284 while (*start)
00285 {
00286 p = start;
00287 SKIPWS(p);
00288
00289 if (*p == '\n')
00290 {
00291 p++;
00292 start = p;
00293 len = getnextline(&start);
00294 continue;
00295 }
00296
00297 q = p;
00298
00299
00300 if (GETKEYWORD(&q))
00301 {
00302 rv = DRMS_ERROR_BADJSD;
00303 break;
00304 }
00305
00306 if (prefixmatch(p, "Keyword:"))
00307 {
00308 if (!fauxtemplate)
00309 {
00310
00311 fauxtemplate = calloc(1, sizeof(DRMS_Record_t));
00312
00313 if (fauxtemplate)
00314 {
00315 XASSERT(fauxtemplate);
00316 fauxtemplate->seriesinfo = calloc(1, sizeof(DRMS_SeriesInfo_t));
00317 XASSERT(fauxtemplate->seriesinfo);
00318 fauxtemplate->env = env;
00319 fauxtemplate->init = 1;
00320 fauxtemplate->recnum = 0;
00321 fauxtemplate->sunum = -1;
00322 fauxtemplate->sessionid = 0;
00323 fauxtemplate->sessionns = NULL;
00324 fauxtemplate->su = NULL;
00325 fauxtemplate->seriesinfo->hasshadow = -1;
00326 fauxtemplate->seriesinfo->createshadow = 0;
00327
00328
00329
00330
00331 hcon_init(&fauxtemplate->keywords, sizeof(DRMS_Keyword_t), DRMS_MAXHASHKEYLEN,
00332 (void (*)(const void *)) drms_free_keyword_struct,
00333 (void (*)(const void *, const void *)) drms_copy_keyword_struct);
00334 }
00335 else
00336 {
00337 rv = DRMS_ERROR_OUTOFMEMORY;
00338 }
00339 }
00340
00341
00342
00343 if (rv == DRMS_SUCCESS)
00344 {
00345
00346
00347
00348
00349
00350 if (parse_keyword(&q, fauxtemplate, slotted, &keynum))
00351 {
00352 rv = DRMS_ERROR_BADJSD;
00353 break;
00354 }
00355 }
00356 }
00357 else
00358 {
00359 fprintf(stderr, "Warning: Unexpected line '%s', skipping and continuing.\n", p);
00360 }
00361
00362
00363 if (start[len] == '\n')
00364 {
00365 start += len + 1;
00366 }
00367 else
00368 {
00369 start += len;
00370 }
00371
00372 len = getnextline(&start);
00373 }
00374
00375 if (rv == DRMS_SUCCESS)
00376 {
00377 if (hcon_size(&fauxtemplate->keywords) > 0)
00378 {
00379
00380 keys = (HContainer_t *)malloc(sizeof(HContainer_t));
00381 if (keys)
00382 {
00383 HIterator_t *hit = NULL;
00384 DRMS_Keyword_t *key = NULL;
00385
00386
00387
00388 hcon_copy(keys, &fauxtemplate->keywords);
00389
00390
00391
00392 hit = hiter_create(keys);
00393 if (hit)
00394 {
00395 while ((key = hiter_getnext(hit)) != NULL)
00396 {
00397 key->record = NULL;
00398 }
00399
00400 hiter_destroy(&hit);
00401 }
00402 else
00403 {
00404 rv = DRMS_ERROR_OUTOFMEMORY;
00405 }
00406 }
00407 else
00408 {
00409 rv = DRMS_ERROR_OUTOFMEMORY;
00410 }
00411 }
00412 }
00413
00414
00415
00416
00417 if (fauxtemplate)
00418 {
00419 drms_free_record_struct(fauxtemplate);
00420 free(fauxtemplate->seriesinfo);
00421 free(fauxtemplate);
00422 fauxtemplate = NULL;
00423 }
00424
00425 if (keys)
00426 {
00427
00428
00429 keys->deep_free = (void (*)(const void *))drms_free_template_keyword_struct;
00430 }
00431
00432 free(copy);
00433 }
00434 else
00435 {
00436 rv = DRMS_ERROR_OUTOFMEMORY;
00437 }
00438 }
00439 else
00440 {
00441 rv = DRMS_ERROR_OUTOFMEMORY;
00442 }
00443
00444 if (slotted)
00445 {
00446 hcon_destroy(&slotted);
00447 }
00448
00449 if (status)
00450 {
00451 *status = rv;
00452 }
00453
00454 return keys;
00455 }
00456
00457
00458
00459
00460
00461
00462 static int parse_seriesinfo (char *desc, DRMS_Record_t *template)
00463 {
00464 int len;
00465 char *start, *p, *q;
00466 int iStat = 0;
00467 int16_t newSuRetention = 0;
00468 int16_t stagingRetention = 0;
00469
00470
00471 start = desc;
00472 len = getnextline (&start);
00473 while (*start) {
00474
00475 p = start;
00476 SKIPWS(p);
00477
00478 if (*p == '\n')
00479 {
00480 p++;
00481 start = p;
00482 len = getnextline (&start);
00483 continue;
00484 }
00485
00486 q = p;
00487
00488
00489 if (GETKEYWORD(&q)) return 1;
00490
00491 if (prefixmatch (p, "Seriesname"))
00492 {
00493 TRY(getstring (&q, template->seriesinfo->seriesname, DRMS_MAXSERIESNAMELEN) <= 0)
00494 }
00495 if (prefixmatch (p, "Version"))
00496 {
00497 TRY(getstring (&q, template->seriesinfo->version, DRMS_MAXSERIESVERSION) <= 0)
00498 }
00499 else if (prefixmatch (p, "Description"))
00500 {
00501 TRY(getstring (&q, template->seriesinfo->description, DRMS_MAXCOMMENTLEN) < 0)
00502 }
00503 else if (prefixmatch (p, "Owner"))
00504 {
00505 TRY(getstring (&q, template->seriesinfo->owner, DRMS_MAXOWNERLEN) <= 0)
00506 }
00507 else if (prefixmatch (p, "Author"))
00508 {
00509 TRY(getstring (&q, template->seriesinfo->author, DRMS_MAXCOMMENTLEN) <= 0)
00510 }
00511 else if (prefixmatch (p, "Archive"))
00512 {
00513 TRY(GETINT(&q, &(template->seriesinfo->archive)))
00514 }
00515 else if (prefixmatch (p, "Unitsize"))
00516 {
00517 TRY(GETINT (&q, &(template->seriesinfo->unitsize)))
00518 }
00519 else if (prefixmatch (p, "Tapegroup"))
00520 {
00521 TRY(GETINT (&q, &(template->seriesinfo->tapegroup)))
00522 }
00523 else if (prefixmatch (p, "Retention"))
00524 {
00525 TRY(GETSHORT(&q, &newSuRetention))
00526 }
00527 else if (prefixmatch (p, "StagingRetention"))
00528 {
00529 TRY(GETSHORT(&q, &stagingRetention))
00530 }
00531 else if (prefixmatch (p, "CreateShadow"))
00532 {
00533 TRY(GETINT (&q, &(template->seriesinfo->createshadow)));
00534 }
00535 start += len + 1;
00536
00537 len = getnextline (&start);
00538 }
00539
00540 template->seriesinfo->retention = newSuRetention + (stagingRetention << 16);
00541
00542 if (template->seriesinfo->archive != -1 &&
00543 template->seriesinfo->archive != 0 &&
00544 template->seriesinfo->archive != 1)
00545 {
00546 fprintf(stderr, "WARNING: Invalid archive value '%d' - setting to 0.\n", template->seriesinfo->archive);
00547 template->seriesinfo->archive = 0;
00548 }
00549
00550
00551
00552
00553
00554
00555
00556 snprintf(template->seriesinfo->version, DRMS_MAXSERIESVERSION, "%s", drms_series_getvers());
00557
00558
00559 #ifdef DEBUG
00560 printf("Seriesname = '%s'\n",template->seriesinfo->seriesname);
00561 printf("Description = '%s'\n",template->seriesinfo->description);
00562 printf("Owner = '%s'\n",template->seriesinfo->owner);
00563 printf("Author = '%s'\n",template->seriesinfo->author);
00564 printf("Archive = %d\n",template->seriesinfo->archive);
00565 printf("Unitsize = %d\n",template->seriesinfo->unitsize);
00566 printf("Tapegroup = %d\n",template->seriesinfo->tapegroup);
00567 printf("Retention = %hd\n", newSuRetention);
00568 printf("StagingRetention = %hd\n", stagingRetention);
00569 #endif
00570
00571 return iStat;
00572 }
00573
00574
00575 static int parse_segments (char *desc, DRMS_Record_t *template, HContainer_t *cparmkeys, int *keynum) {
00576 int len, segnum;
00577 char *start, *p, *q;
00578
00579
00580
00581 start = desc;
00582 len = getnextline(&start);
00583 segnum = 0;
00584 while(*start)
00585 {
00586 p = start;
00587 SKIPWS(p);
00588
00589 if (*p == '\n')
00590 {
00591 p++;
00592 start = p;
00593 len = getnextline (&start);
00594 continue;
00595 }
00596
00597 q = p;
00598 if (GETKEYWORD(&q))
00599 return 1;
00600
00601 if (prefixmatch(p,"Data:"))
00602 {
00603 if (parse_segment(&q, template, segnum, cparmkeys, keynum))
00604 return 1;
00605 ++segnum;
00606 }
00607 start += len+1;
00608
00609 len = getnextline(&start);
00610 }
00611 return 0;
00612 }
00613
00614
00615
00616 static int parse_segment(char **in, DRMS_Record_t *template, int segnum, HContainer_t *cparmkeys, int *keynum)
00617 {
00618 int i,status,count,tempval;
00619 char *p,*q,*endptr;
00620 char name[DRMS_MAXSEGNAMELEN]={0}, scope[DRMS_MAXNAMELEN]={0};
00621 char type[DRMS_MAXNAMELEN]={0}, naxis[24]={0}, axis[24]={0}, protocol[DRMS_MAXNAMELEN]={0};
00622 char cparms[DRMS_MAXCPARMS]={0};
00623 char unit[DRMS_MAXUNITLEN]={0};
00624 char bzero[64];
00625 char bscale[64];
00626 DRMS_Segment_t *seg;
00627 int parserline = -1;
00628 DRMS_Type_Value_t nval,myval;
00629 p = q = *in;
00630 SKIPWS(p);
00631 q = p;
00632
00633
00634 if (GETTOKEN(&q,name,sizeof(name)) <= 0) GOTOFAILURE;
00635 seg = hcon_allocslot_lower(&template->segments, name);
00636 XASSERT(seg);
00637 memset(seg,0,sizeof(DRMS_Segment_t));
00638 seg->info = malloc(sizeof(DRMS_SegmentInfo_t));
00639 XASSERT(seg->info);
00640 memset(seg->info,0,sizeof(DRMS_SegmentInfo_t));
00641 seg->record = template;
00642
00643 strcpy(seg->info->name, name);
00644
00645 seg->info->segnum = segnum;
00646
00647 if (GETTOKEN(&q,scope,sizeof(scope)) <= 0) GOTOFAILURE;
00648 if ( !strcasecmp(scope,"link") )
00649 {
00650
00651 seg->info->islink = 1;
00652 seg->info->scope= DRMS_VARIABLE;
00653 seg->info->type = DRMS_TYPE_INT;
00654 seg->info->protocol = DRMS_GENERIC;
00655
00656 if(GETTOKEN(&q,seg->info->linkname,sizeof(seg->info->linkname)) <= 0) GOTOFAILURE;
00657 if(GETTOKEN(&q,seg->info->target_seg,sizeof(seg->info->target_seg)) <= 0) GOTOFAILURE;
00658
00659 if (GETTOKEN(&q,naxis,sizeof(naxis)) <= 0) GOTOFAILURE;
00660 strtoll(naxis,&endptr,10);
00661 nval.string_val = naxis;
00662 if (endptr != naxis + strlen(naxis))
00663 { GOTOFAILURE; }
00664 else
00665 {
00666 tempval = drms2int(DRMS_TYPE_STRING, &nval, &status);
00667 if (status == DRMS_RANGE || tempval < 0 )
00668 {GOTOFAILURE;}
00669 else
00670 seg->info->naxis = drms2int(DRMS_TYPE_STRING, &nval, &status);
00671 }
00672
00673 for (i=0; i<seg->info->naxis; i++)
00674 {
00675 if (GETTOKEN(&q,axis,sizeof(axis)) <= 0) GOTOFAILURE;
00676 myval.string_val = axis;
00677 strtoll(axis,&endptr,10);
00678 if (endptr != axis + strlen(axis))
00679 {GOTOFAILURE;}
00680 else
00681 {
00682 tempval = drms2int(DRMS_TYPE_STRING, &myval, &status);
00683
00684 if (status == DRMS_RANGE || tempval < 0 )
00685 {GOTOFAILURE;}
00686 else
00687 seg->axis[i] = drms2int(DRMS_TYPE_STRING, &myval, &status);
00688 }
00689 }
00690
00691 if (getstring(&q,seg->info->description,sizeof(seg->info->description))<0) GOTOFAILURE;
00692 }
00693 else
00694 {
00695
00696 seg->info->islink = 0;
00697
00698 if (!strcmp(scope, "constant"))
00699 seg->info->scope = DRMS_CONSTANT;
00700 else if (!strcmp(scope, "variable"))
00701 seg->info->scope = DRMS_VARIABLE;
00702 else if (!strcmp(scope, "vardim"))
00703 seg->info->scope = DRMS_VARDIM;
00704 else GOTOFAILURE;
00705
00706
00707 if (GETTOKEN(&q,type,sizeof(type)) <= 0) GOTOFAILURE;
00708 seg->info->type = drms_str2type(type);
00709
00710 if (GETTOKEN(&q,naxis,sizeof(naxis)) <= 0) GOTOFAILURE;
00711 strtoll(naxis,&endptr,10);
00712 nval.string_val = naxis;
00713 if (endptr != naxis + strlen(naxis))
00714 { GOTOFAILURE; }
00715 else
00716 {
00717
00718 tempval = drms2int(DRMS_TYPE_STRING, &nval, &status);
00719 if (status == DRMS_RANGE || tempval < 0 )
00720 { GOTOFAILURE;}
00721 else
00722 seg->info->naxis = drms2int(DRMS_TYPE_STRING, &nval, &status);
00723 }
00724
00725 if ( !strcasecmp(scope, "vardim"))
00726 {
00727 for(i=0; i<seg->info->naxis; i++)
00728 {
00729 if (GETTOKEN(&q,axis,sizeof(axis)) <= 0) GOTOFAILURE;
00730 if( !strcasecmp(axis, "*") || !strcasecmp(axis, "NA"))
00731 {
00732 seg->axis[i] = 0;
00733 }
00734 else
00735 {
00736 myval.string_val = axis;
00737 strtoll(axis,&endptr,10);
00738 if (endptr != axis + strlen(axis))
00739 { GOTOFAILURE;}
00740 else
00741 {
00742 tempval = drms2int(DRMS_TYPE_STRING,&myval, &status);
00743 if (status == DRMS_RANGE || tempval < 0 )
00744 { GOTOFAILURE;}
00745 else
00746 seg->axis[i] = drms2int(DRMS_TYPE_STRING,&myval, &status);
00747 }
00748 }
00749 }
00750 if (GETTOKEN(&q,unit,sizeof(unit)) < 0) GOTOFAILURE;
00751 strcpy(seg->info->unit, unit);
00752 if (GETTOKEN(&q,protocol,sizeof(protocol)) <= 0) GOTOFAILURE;
00753 seg->info->protocol = drms_str2prot(protocol);
00754 }
00755 else if( (!strcasecmp(scope, "variable")) || (!strcasecmp(scope, "constant")))
00756 {
00757
00758 count=0;
00759 for(i=0; i<seg->info->naxis; i++)
00760 {
00761 if (GETTOKEN(&q,axis,sizeof(axis)) <= 0) GOTOFAILURE;
00762 if( !strcasecmp(axis, "*") || !strcasecmp(axis, "NA"))
00763 {
00764 seg->axis[i] = 0;
00765 count=1;
00766 }
00767 else
00768 {
00769 myval.string_val = axis;
00770 strtoll(axis,&endptr,10);
00771 if (endptr != axis + strlen(axis))
00772 { GOTOFAILURE;}
00773 else
00774 {
00775 tempval = drms2int(DRMS_TYPE_STRING,&myval, &status);
00776
00777 if (status == DRMS_RANGE || tempval <0 )
00778 {GOTOFAILURE; }
00779 else
00780 seg->axis[i] = drms2int(DRMS_TYPE_STRING,&myval, &status);
00781 }
00782 }
00783 }
00784 if (GETTOKEN(&q,unit,sizeof(unit)) < 0) GOTOFAILURE;
00785 strcpy(seg->info->unit, unit);
00786 if (GETTOKEN(&q,protocol,sizeof(protocol)) <= 0) GOTOFAILURE;
00787 if (count==1)
00788 {
00789 if(!strcasecmp(protocol,"generic"))
00790 seg->info->protocol = drms_str2prot(protocol);
00791 else
00792 GOTOFAILURE;
00793 }
00794 else
00795 seg->info->protocol = drms_str2prot(protocol);
00796 }
00797
00798
00799
00800
00801
00802
00803 if ((seg->info->protocol == DRMS_FITS ||
00804 seg->info->protocol == DRMS_FITZ ||
00805 seg->info->protocol == DRMS_TAS) && seg->info->type != DRMS_TYPE_LONGLONG)
00806 {
00807
00808
00809
00810
00811
00812
00813
00814 char buf[DRMS_MAXKEYNAMELEN];
00815
00816
00817 if (seg->info->protocol != DRMS_FITZ)
00818 {
00819 if (GETVALTOKEN(&q, DRMS_TYPE_STRING, cparms, sizeof(cparms)) < 0) GOTOFAILURE;
00820 }
00821
00822 snprintf(buf, sizeof(buf), "cparms_sg%03d", segnum);
00823
00824 DRMS_Keyword_t *cpkey = calloc(1, sizeof(DRMS_Keyword_t));
00825 XASSERT(cpkey);
00826 int chused = 0;
00827
00828 cpkey->info = malloc(sizeof(DRMS_KeywordInfo_t));
00829 XASSERT(cpkey->info);
00830 memset(cpkey->info, 0, sizeof(DRMS_KeywordInfo_t));
00831 snprintf(cpkey->info->name, DRMS_MAXKEYNAMELEN, "%s", buf);
00832 cpkey->record = template;
00833 drms_keyword_unsetperseg(cpkey);
00834 cpkey->info->islink = 0;
00835 cpkey->info->linkname[0] = 0;
00836 cpkey->info->target_key[0] = 0;
00837 cpkey->info->type = DRMS_TYPE_STRING;
00838
00839
00840 if (seg->info->protocol != DRMS_FITZ)
00841 {
00842 drms_sscanf_str("", NULL, &cpkey->value);
00843 }
00844 else
00845 {
00846
00847 drms_sscanf_str("compress Rice", NULL, &cpkey->value);
00848 }
00849
00850 if (strlen(cparms) > 0 && strcasecmp(cparms, "none"))
00851 {
00852
00853
00854
00855 chused = drms_sscanf_str(cparms, NULL, &cpkey->value);
00856 if (chused < 0)
00857 GOTOFAILURE;
00858 }
00859
00860 snprintf(cpkey->info->format, DRMS_MAXFORMATLEN, "%s", "%s");
00861 snprintf(cpkey->info->unit, DRMS_MAXUNITLEN, "%s", "none");
00862 cpkey->info->recscope = kRecScopeType_Variable;
00863 snprintf(cpkey->info->description, DRMS_MAXCOMMENTLEN, "%s", "");
00864 drms_keyword_unsetintprime(cpkey);
00865 drms_keyword_unsetextprime(cpkey);
00866 drms_keyword_setimplicit(cpkey);
00867
00868
00869 cpkey->info->rank = (*keynum)++;
00870 cpkey->info->kwflags |= (cpkey->info->rank + 1) << 16;
00871
00872 if (cparmkeys)
00873 {
00874 hcon_insert(cparmkeys, buf, &cpkey);
00875 }
00876 }
00877
00878 if (seg->info->protocol == DRMS_TAS ||
00879 seg->info->protocol == DRMS_FITS ||
00880 seg->info->protocol == DRMS_FITZ ||
00881 seg->info->protocol == DRMS_BINARY ||
00882 seg->info->protocol == DRMS_BINZIP)
00883 {
00884 DRMS_Value_t vholder;
00885
00886 if (seg->info->type != DRMS_TYPE_FLOAT && seg->info->type != DRMS_TYPE_DOUBLE)
00887 {
00888
00889 if (GETTOKEN(&q, bzero, sizeof(bzero)) <= 0) GOTOFAILURE;
00890 if (GETTOKEN(&q, bscale, sizeof(bscale)) <= 0) GOTOFAILURE;
00891 }
00892 else
00893 {
00894 snprintf(bzero, sizeof(bzero), "0.0");
00895 snprintf(bscale, sizeof(bscale), "1.0");
00896 }
00897
00898 char buf[DRMS_MAXKEYNAMELEN];
00899 snprintf(buf, sizeof(buf), "%s_bzero", name);
00900
00901 DRMS_Keyword_t *sckey = calloc(1, sizeof(DRMS_Keyword_t));
00902 XASSERT(sckey);
00903
00904 sckey->info = malloc(sizeof(DRMS_KeywordInfo_t));
00905 XASSERT(sckey->info);
00906 memset(sckey->info, 0, sizeof(DRMS_KeywordInfo_t));
00907 snprintf(sckey->info->name, DRMS_MAXKEYNAMELEN, "%s", buf);
00908 sckey->record = template;
00909 drms_keyword_unsetperseg(sckey);
00910 sckey->info->islink = 0;
00911 sckey->info->linkname[0] = 0;
00912 sckey->info->target_key[0] = 0;
00913 sckey->info->type = DRMS_TYPE_DOUBLE;
00914 memset(&vholder, 0, sizeof(DRMS_Value_t));
00915 drms_sscanf2(bzero, NULL, 0, DRMS_TYPE_DOUBLE, &vholder);
00916 sckey->value = vholder.value;
00917 snprintf(sckey->info->format, DRMS_MAXFORMATLEN, "%s", "%g");
00918 snprintf(sckey->info->unit, DRMS_MAXUNITLEN, "%s", "none");
00919 sckey->info->recscope = kRecScopeType_Variable;
00920 snprintf(sckey->info->description, DRMS_MAXCOMMENTLEN, "%s", "");
00921 drms_keyword_unsetintprime(sckey);
00922 drms_keyword_unsetextprime(sckey);
00923 drms_keyword_setimplicit(sckey);
00924
00925
00926 sckey->info->rank = (*keynum)++;
00927 sckey->info->kwflags |= (sckey->info->rank + 1) << 16;
00928
00929
00930
00931
00932
00933 if (cparmkeys)
00934 {
00935 hcon_insert(cparmkeys, buf, &sckey);
00936 }
00937
00938 snprintf(buf, sizeof(buf), "%s_bscale", name);
00939
00940 sckey = calloc(1, sizeof(DRMS_Keyword_t));
00941 XASSERT(sckey);
00942
00943 sckey->info = malloc(sizeof(DRMS_KeywordInfo_t));
00944 XASSERT(sckey->info);
00945 memset(sckey->info, 0, sizeof(DRMS_KeywordInfo_t));
00946 snprintf(sckey->info->name, DRMS_MAXKEYNAMELEN, "%s", buf);
00947 sckey->record = template;
00948 drms_keyword_unsetperseg(sckey);;
00949 sckey->info->islink = 0;
00950 sckey->info->linkname[0] = 0;
00951 sckey->info->target_key[0] = 0;
00952 sckey->info->type = DRMS_TYPE_DOUBLE;
00953 memset(&vholder, 0, sizeof(DRMS_Value_t));
00954 drms_sscanf2(bscale, NULL, 0, DRMS_TYPE_DOUBLE, &vholder);
00955 sckey->value = vholder.value;
00956 snprintf(sckey->info->format, DRMS_MAXFORMATLEN, "%s", "%g");
00957 snprintf(sckey->info->unit, DRMS_MAXUNITLEN, "%s", "none");
00958 sckey->info->recscope = kRecScopeType_Variable;
00959 snprintf(sckey->info->description, DRMS_MAXCOMMENTLEN, "%s", "");
00960 drms_keyword_unsetintprime(sckey);
00961 drms_keyword_unsetextprime(sckey);
00962 drms_keyword_setimplicit(sckey);
00963
00964
00965 sckey->info->rank = (*keynum)++;
00966 sckey->info->kwflags |= (sckey->info->rank + 1) << 16;
00967
00968
00969
00970
00971
00972 if (cparmkeys)
00973 {
00974 hcon_insert(cparmkeys, buf, &sckey);
00975 }
00976 }
00977
00978 if (getstring(&q,seg->info->description,sizeof(seg->info->description))<0) GOTOFAILURE;
00979 }
00980 p = ++q;
00981 *in = q;
00982
00983 return 0;
00984 failure:
00985 fprintf(stderr,"%s, line %d: Invalid segment descriptor on line %d.\n",
00986 __FILE__, parserline, lineno);
00987 return 1;
00988 }
00989
00990
00991
00992 static int parse_links(char *desc, DRMS_Record_t *template)
00993 {
00994 int len;
00995 char *start, *p, *q;
00996 int linknum;
00997
00998
00999
01000 start = desc;
01001 len = getnextline(&start);
01002 linknum = 0;
01003 while(*start)
01004 {
01005 p = start;
01006 SKIPWS(p);
01007
01008 if (*p == '\n')
01009 {
01010 p++;
01011 start = p;
01012 len = getnextline (&start);
01013 continue;
01014 }
01015
01016 q = p;
01017 if (GETKEYWORD(&q))
01018 return 1;
01019
01020 if (prefixmatch(p,"Link:"))
01021 {
01022 if (parse_link(&q,template, linknum))
01023 return 1;
01024 linknum++;
01025 }
01026 start += len+1;
01027 len = getnextline(&start);
01028 }
01029 return 0;
01030 }
01031
01032
01033
01034 static int parse_link(char **in, DRMS_Record_t *template, int linknum)
01035 {
01036 char *p,*q;
01037 char name[DRMS_MAXLINKNAMELEN]={0}, target[DRMS_MAXSERIESNAMELEN]={0}, type[DRMS_MAXNAMELEN]={0},
01038 description[DRMS_MAXCOMMENTLEN]={0};
01039 DRMS_Link_t *link;
01040 int parserline = -1;
01041
01042 p = q = *in;
01043 SKIPWS(p);
01044 q = p;
01045
01046
01047 if (GETTOKEN(&q,name,sizeof(name)) <= 0) GOTOFAILURE;
01048 if (GETTOKEN(&q,target,sizeof(target)) <= 0) GOTOFAILURE;
01049 if (GETTOKEN(&q,type,sizeof(type)) <= 0) GOTOFAILURE;
01050 if (getstring(&q,description,sizeof(description))<0) GOTOFAILURE;
01051
01052 link = hcon_allocslot_lower(&template->links, name);
01053 XASSERT(link);
01054 memset(link,0,sizeof(DRMS_Link_t));
01055 link->info = malloc(sizeof(DRMS_LinkInfo_t));
01056 XASSERT(link->info);
01057 memset(link->info,0,sizeof(DRMS_LinkInfo_t));
01058 link->record = template;
01059 strcpy(link->info->name, name);
01060 strcpy(link->info->target_series,target);
01061 if (!strcasecmp(type,"static"))
01062 link->info->type = STATIC_LINK;
01063 else if (!strcasecmp(type,"dynamic")) {
01064 link->info->type = DYNAMIC_LINK;
01065 link->info->pidx_num = -1;
01066 }
01067 else
01068 GOTOFAILURE;
01069 link->info->rank = linknum;
01070 strncpy(link->info->description, description, DRMS_MAXCOMMENTLEN);
01071 link->isset = 0;
01072 link->recnum = -1;
01073
01074 p = ++q;
01075 *in = q;
01076
01077 return 0;
01078 failure:
01079 fprintf(stderr,"%s, line %d: Invalid Link descriptor on line %d.\n",
01080 __FILE__, parserline, lineno);
01081 return 1;
01082 }
01083
01084 int parse_keywords(char *desc, DRMS_Record_t *template, HContainer_t *cparmkeys, int *keynum)
01085 {
01086 int len;
01087 char *start, *p, *q;
01088
01089 HContainer_t *slotted = hcon_create(sizeof(DRMS_Keyword_t *),
01090 DRMS_MAXKEYNAMELEN,
01091 NULL,
01092 NULL,
01093 NULL,
01094 NULL,
01095 0);
01096
01097 if (!slotted)
01098 {
01099 fprintf(stderr, "Couldn't create container in drms_parse_description().\n");
01100 return 1;
01101 }
01102 else
01103 {
01104
01105
01106 start = desc;
01107 len = getnextline(&start);
01108 while(*start)
01109 {
01110 p = start;
01111 SKIPWS(p);
01112
01113 if (*p == '\n')
01114 {
01115 p++;
01116 start = p;
01117 len = getnextline (&start);
01118 continue;
01119 }
01120
01121 q = p;
01122 if (GETKEYWORD(&q))
01123 return 1;
01124
01125 if (prefixmatch(p,"Keyword:"))
01126 {
01127
01128
01129 if (parse_keyword(&q,template, slotted, keynum))
01130 return 1;
01131 }
01132 start += len+1;
01133 len = getnextline(&start);
01134 }
01135
01136 if (slotted->num_total > 0)
01137 {
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148 HIterator_t *hit = hiter_create(slotted);
01149
01150 if (hit)
01151 {
01152 DRMS_Keyword_t **pSlotKey = NULL;
01153 const char *slotKeyname = NULL;
01154 char keyname[DRMS_MAXKEYNAMELEN];
01155 DRMS_Keyword_t *newkey = NULL;
01156 DRMS_Keyword_t *existkey = NULL;
01157
01158 while ((pSlotKey =
01159 (DRMS_Keyword_t **)hiter_extgetnext(hit, &slotKeyname)) != NULL)
01160 {
01161 snprintf(keyname, sizeof(keyname), "%s%s", slotKeyname, kSlotAncKey_Index);
01162 if ((existkey =
01163 (DRMS_Keyword_t *)hcon_lookup_lower(&(template->keywords), keyname))
01164 == NULL)
01165 {
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175 newkey = hcon_allocslot_lower(&(template->keywords), keyname);
01176 XASSERT(newkey);
01177 memset(newkey,0,sizeof(DRMS_Keyword_t));
01178 newkey->info = malloc(sizeof(DRMS_KeywordInfo_t));
01179 XASSERT(newkey->info);
01180 memset(newkey->info,0,sizeof(DRMS_KeywordInfo_t));
01181 strcpy(newkey->info->name, keyname);
01182 newkey->record = template;
01183 drms_keyword_unsetperseg(newkey);
01184 drms_keyword_setimplicit(newkey);
01185 newkey->info->islink = 0;
01186 newkey->info->linkname[0] = 0;
01187 newkey->info->target_key[0] = 0;
01188 newkey->info->type = kIndexKWType;
01189 strcpy(newkey->info->format, kIndexKWFormat);
01190 strcpy(newkey->info->unit, "none");
01191 newkey->info->recscope = kRecScopeType_Index;
01192 snprintf(newkey->info->description, DRMS_MAXCOMMENTLEN, "Index keyword associated with %s", slotKeyname);
01193
01194
01195
01196
01197 drms_keyword_setintprime(newkey);
01198 drms_keyword_unsetextprime(newkey);
01199
01200
01201 newkey->info->rank = (*keynum)++;
01202 newkey->info->kwflags |= (newkey->info->rank + 1) << 16;
01203
01204
01205
01206
01207 }
01208 else
01209 {
01210
01211
01212
01213
01214
01215
01216
01217 fprintf(stderr, "Keywords with the suffix '_index' are reserved; cannot specify '%s' in a jsd file\n", existkey->info->name);
01218 return 1;
01219 }
01220
01221
01222
01223 int failure = 0;
01224 switch ((int)drms_keyword_getrecscope(*pSlotKey))
01225 {
01226 case kRecScopeType_TS_SLOT:
01227 {
01228 DRMS_Keyword_t *anckey = NULL;
01229 snprintf(keyname, sizeof(keyname), "%s%s", slotKeyname, kSlotAncKey_Round);
01230 anckey = (DRMS_Keyword_t *)hcon_lookup_lower(&(template->keywords), keyname);
01231 if (anckey)
01232 {
01233
01234 if (!drms_keyword_isconstant(anckey))
01235 {
01236 fprintf(stderr, "Ancillary keyword '%s' must be constant.\n",
01237 keyname);
01238 failure = 1;
01239 }
01240 }
01241 }
01242
01243 if (failure)
01244 {
01245 break;
01246 }
01247
01248 case kRecScopeType_TS_EQ:
01249 {
01250 DRMS_Keyword_t *anckey = NULL;
01251 snprintf(keyname,
01252 sizeof(keyname), "%s%s",
01253 slotKeyname,
01254 kSlotAncKey_Epoch);
01255 anckey = (DRMS_Keyword_t *)hcon_lookup_lower(&(template->keywords),
01256 keyname);
01257 if (anckey)
01258 {
01259
01260 if (drms_keyword_isconstant(anckey) &&
01261 (drms_keyword_gettype(anckey) == DRMS_TYPE_TIME ||
01262 drms_keyword_gettype(anckey) == DRMS_TYPE_STRING))
01263 {
01264 snprintf(keyname,
01265 sizeof(keyname), "%s%s",
01266 slotKeyname,
01267 kSlotAncKey_Step);
01268 anckey = (DRMS_Keyword_t *)hcon_lookup_lower(&(template->keywords),
01269 keyname);
01270 }
01271 else
01272 {
01273 fprintf(stderr, "Ancillary keyword '%s' must be constant"
01274 " and of data type 'time' or 'string'.\n", keyname);
01275 failure = 1;
01276 }
01277 }
01278
01279 if (!anckey)
01280 {
01281 fprintf(stderr,
01282 "Missing required ancillary keyword '%s'.\n",
01283 keyname);
01284 failure = 1;
01285 }
01286
01287 if (!failure && anckey)
01288 {
01289
01290 if (drms_keyword_isconstant(anckey))
01291 {
01292
01293 snprintf(keyname,
01294 sizeof(keyname), "%s%s",
01295 slotKeyname,
01296 kSlotAncKey_Unit);
01297 anckey = (DRMS_Keyword_t *)hcon_lookup_lower(&(template->keywords),
01298 keyname);
01299 }
01300 else
01301 {
01302 fprintf(stderr,
01303 "Ancillary keyword '%s' must be constant.\n",
01304 keyname);
01305 failure = 1;
01306 }
01307 }
01308
01309 if (!failure && anckey)
01310 {
01311
01312 if (drms_keyword_gettype(anckey) == DRMS_TYPE_STRING &&
01313 drms_keyword_isconstant(anckey))
01314 {
01315 DRMS_SlotKeyUnit_t utype = drms_keyword_getunit(anckey, NULL);
01316
01317 if (utype == kSlotKeyUnit_Invalid)
01318 {
01319 fprintf(stderr,
01320 "Slot keyword unit '%s' is not valid.\n",
01321 drms_keyword_getvalue(anckey)->string_val);
01322 failure = 1;
01323 }
01324 }
01325 else
01326 {
01327 fprintf(stderr,
01328 "Ancillary keyword '%s' must be constant"
01329 " and of data type 'string'.\n",
01330 keyname);
01331 failure = 1;
01332 }
01333 }
01334 }
01335 break;
01336 case kRecScopeType_SLOT:
01337 {
01338 snprintf(keyname,
01339 sizeof(keyname), "%s%s",
01340 slotKeyname,
01341 kSlotAncKey_Base);
01342 DRMS_Keyword_t *anckey =
01343 (DRMS_Keyword_t *)hcon_lookup_lower(&(template->keywords),
01344 keyname);
01345
01346 if (anckey)
01347 {
01348
01349 if (drms_keyword_isconstant(anckey) &&
01350 (drms_keyword_gettype(anckey) == DRMS_TYPE_DOUBLE ||
01351 drms_keyword_gettype(anckey) == DRMS_TYPE_FLOAT ||
01352 drms_keyword_gettype(anckey) == DRMS_TYPE_TIME))
01353
01354 {
01355 snprintf(keyname,
01356 sizeof(keyname), "%s%s",
01357 slotKeyname,
01358 kSlotAncKey_Step);
01359 anckey =
01360 (DRMS_Keyword_t *)hcon_lookup_lower(&(template->keywords),
01361 keyname);
01362 }
01363 else
01364 {
01365 fprintf(stderr, "Ancillary keyword '%s' must be constant"
01366 " and of data type 'double', 'float', or 'time'.\n",
01367 keyname);
01368 failure = 1;
01369 }
01370 }
01371
01372 if (!anckey)
01373 {
01374 fprintf(stderr,
01375 "Missing required ancillary keyword '%s'.\n",
01376 keyname);
01377 failure = 1;
01378 }
01379
01380 if (!failure && anckey)
01381 {
01382
01383 if (drms_keyword_isconstant(anckey))
01384 {
01385
01386 snprintf(keyname,
01387 sizeof(keyname), "%s%s",
01388 slotKeyname,
01389 kSlotAncKey_Unit);
01390 anckey =
01391 (DRMS_Keyword_t *)hcon_lookup_lower(&(template->keywords),
01392 keyname);
01393 }
01394 else
01395 {
01396 fprintf(stderr,
01397 "Ancillary keyword '%s' must be constant.\n",
01398 keyname);
01399 failure = 1;
01400 }
01401 }
01402
01403 if (!failure && anckey)
01404 {
01405
01406
01407 if (drms_keyword_gettype(anckey) != DRMS_TYPE_STRING ||
01408 !drms_keyword_isconstant(anckey))
01409 {
01410 fprintf(stderr,
01411 "Ancillary keyword '%s' must be constant"
01412 " and of data type 'string'.\n",
01413 keyname);
01414 failure = 1;
01415 }
01416 }
01417 }
01418 break;
01419 case kRecScopeType_ENUM:
01420 break;
01421 case kRecScopeType_CARR:
01422 {
01423 snprintf(keyname,
01424 sizeof(keyname), "%s%s",
01425 slotKeyname,
01426 kSlotAncKey_Step);
01427 DRMS_Keyword_t *anckey =
01428 (DRMS_Keyword_t *)hcon_lookup_lower(&(template->keywords),
01429 keyname);
01430
01431 if (!anckey)
01432 {
01433 fprintf(stderr,
01434 "Missing required ancillary keyword '%s'.\n",
01435 keyname);
01436 failure = 1;
01437 }
01438
01439 if (!failure && anckey)
01440 {
01441
01442 if (drms_keyword_isconstant(anckey))
01443 {
01444
01445 snprintf(keyname,
01446 sizeof(keyname), "%s%s",
01447 slotKeyname,
01448 kSlotAncKey_Unit);
01449 anckey =
01450 (DRMS_Keyword_t *)hcon_lookup_lower(&(template->keywords),
01451 keyname);
01452 }
01453 else
01454 {
01455 fprintf(stderr,
01456 "Ancillary keyword '%s' must be constant.\n",
01457 keyname);
01458 failure = 1;
01459 }
01460 }
01461
01462 if (!failure && anckey)
01463 {
01464
01465 if (drms_keyword_gettype(anckey) == DRMS_TYPE_STRING &&
01466 drms_keyword_isconstant(anckey))
01467 {
01468 DRMS_SlotKeyUnit_t utype =
01469 drms_keyword_getunit(anckey, NULL);
01470
01471 if (utype == kSlotKeyUnit_Invalid)
01472 {
01473 fprintf(stderr,
01474 "Slot keyword unit '%s' is not valid.\n",
01475 drms_keyword_getvalue(anckey)->string_val);
01476 failure = 1;
01477 }
01478 }
01479 else
01480 {
01481 fprintf(stderr,
01482 "Ancillary keyword '%s' must be constant"
01483 " and of data type 'string'.\n",
01484 keyname);
01485 failure = 1;
01486 }
01487 }
01488 }
01489 break;
01490 default:
01491 fprintf(stderr,
01492 "Invalid recscope type '%d'.\n",
01493 (int)drms_keyword_getrecscope(*pSlotKey));
01494 failure = 1;
01495 }
01496
01497 if (failure == 1)
01498 {
01499 hiter_destroy(&hit);
01500 hcon_destroy(&slotted);
01501 return 1;
01502 }
01503 }
01504
01505 hiter_destroy(&hit);
01506 }
01507 else
01508 {
01509 fprintf(stderr, "Couldn't create iterator.\n");
01510 hcon_destroy(&slotted);
01511 return 1;
01512 }
01513 }
01514
01515 hcon_destroy(&slotted);
01516 }
01517
01518 if (cparmkeys)
01519 {
01520
01521 HIterator_t *hiter = hiter_create(cparmkeys);
01522 DRMS_Keyword_t *cpkeyin = NULL;
01523 DRMS_Keyword_t **pcpkeyin = NULL;
01524 DRMS_Keyword_t *cpkey = NULL;
01525 if (hiter)
01526 {
01527 while ((pcpkeyin = (DRMS_Keyword_t **)hiter_getnext(hiter)) != NULL)
01528 {
01529 cpkeyin = *pcpkeyin;
01530 cpkey = hcon_allocslot_lower(&template->keywords, cpkeyin->info->name);
01531 XASSERT(cpkey);
01532 memset(cpkey, 0, sizeof(DRMS_Keyword_t));
01533 drms_copy_keyword_struct(cpkey, cpkeyin);
01534 }
01535
01536 hiter_destroy(&hiter);
01537 }
01538 }
01539
01540 return 0;
01541 }
01542
01543 enum PFormatLMod_enum
01544 {
01545 kPFormatLMod_None = 0,
01546 kPFormatLMod_Char,
01547 kPFormatLMod_Short,
01548 kPFormatLMod_LongLong,
01549 kPFormatLMod_LongDouble
01550 };
01551 typedef enum PFormatLMod_enum PFormatLMod_t;
01552
01553 static int FormatChk(const char *format, DRMS_Type_t dtype)
01554 {
01555 int ok = 1;
01556 int gotformat = 0;
01557
01558 if (dtype == DRMS_TYPE_TIME)
01559 {
01560 signed char val;
01561
01562 if (sscanf(format, "%hhd", &val) != 1 || val <= -10 || val >= 10)
01563 {
01564 ok = 0;
01565 }
01566 }
01567 else
01568 {
01569
01570
01571 char *fcopy = strdup(format);
01572 char *ppcnt = strchr(fcopy, '%');
01573
01574 while (ok && ppcnt)
01575 {
01576 while (ppcnt && ppcnt - fcopy < strlen(fcopy) - 1 && *(ppcnt + 1) == '%')
01577 {
01578 ppcnt = strchr(ppcnt + 2, '%');
01579 }
01580
01581 if (ppcnt && gotformat)
01582 {
01583 ok = 0;
01584 fprintf(stderr, "Too many format specifiers in '%s'. There should be one only.\n", format);
01585 break;
01586 }
01587
01588 if (ppcnt)
01589 {
01590 char *lasts;
01591 char *fcopy2 = strdup(ppcnt);
01592 char *md = NULL;
01593 PFormatLMod_t lmod;
01594 int fmtstrlen = 0;
01595
01596
01597
01598
01599
01600 md = strtok_r(fcopy2, "dioxXfFeEgGaAs", &lasts);
01601 if (md)
01602 {
01603 fmtstrlen = strlen(md);
01604 char sp = ppcnt[fmtstrlen];
01605 gotformat = 1;
01606 md++;
01607
01608
01609 if (strstr(md, "hh"))
01610 {
01611
01612
01613 lmod = kPFormatLMod_Char;
01614 }
01615 else if (strchr(md, 'h'))
01616 {
01617
01618
01619 lmod = kPFormatLMod_Short;
01620 }
01621 else if (strstr(md, "ll"))
01622 {
01623
01624
01625 lmod = kPFormatLMod_LongLong;
01626 }
01627 else if (strchr(md, 'l'))
01628 {
01629
01630
01631
01632
01633 if (dtype == DRMS_TYPE_STRING)
01634 {
01635 fprintf(stderr, "Format 'ls' implies the string argument is Unicode - DRMS does not support Unicode strings.\n");
01636 }
01637 else
01638 {
01639 fprintf(stderr, "Using format length modifier 'l' is dangerous; on 32-bit machines, a 32-bit value is expected, but on 64-bit machines, a 64-bit value is expected.\n");
01640 }
01641 ok = 0;
01642 }
01643 else if (strchr(md, 'j'))
01644 {
01645
01646 lmod = kPFormatLMod_LongLong;
01647 }
01648 else if (strchr(md, 'L'))
01649 {
01650 lmod = kPFormatLMod_LongDouble;
01651 }
01652 else if (strchr(md, 'z') || strchr(md, 't'))
01653 {
01654
01655
01656 ok = 0;
01657 }
01658 else
01659 {
01660 lmod = kPFormatLMod_None;
01661 }
01662
01663 if (ok)
01664 {
01665
01666
01667
01668 switch (dtype)
01669 {
01670 case DRMS_TYPE_CHAR:
01671 ok &= (lmod == kPFormatLMod_None || lmod == kPFormatLMod_Char ||
01672 lmod == kPFormatLMod_Short || lmod == kPFormatLMod_LongLong);
01673 ok &= (sp == 'd' || sp == 'i' || sp == 'o' || sp == 'x' || sp == 'X' ||
01674 sp == 'f' || sp == 'F' || sp == 'e' || sp == 'E' || sp == 'g' || sp == 'G' ||
01675 sp == 'a' || sp == 'A');
01676 break;
01677 case DRMS_TYPE_SHORT:
01678 ok &= (lmod == kPFormatLMod_None || lmod == kPFormatLMod_Short ||
01679 lmod == kPFormatLMod_LongLong);
01680 ok &= (sp == 'd' || sp == 'i' || sp == 'o' || sp == 'x' || sp == 'X' ||
01681 sp == 'f' || sp == 'F' || sp == 'e' || sp == 'E' || sp == 'g' || sp == 'G' ||
01682 sp == 'a' || sp == 'A');
01683 break;
01684 case DRMS_TYPE_INT:
01685 ok &= (lmod == kPFormatLMod_None || lmod == kPFormatLMod_LongLong);
01686 ok &= (sp == 'd' || sp == 'i' || sp == 'o' || sp == 'x' || sp == 'X' ||
01687 sp == 'f' || sp == 'F' || sp == 'e' || sp == 'E' || sp == 'g' || sp == 'G' ||
01688 sp == 'a' || sp == 'A');
01689 break;
01690 case DRMS_TYPE_LONGLONG:
01691 ok &= ((lmod == kPFormatLMod_None && (sp != 'd' && sp!= 'i'
01692 && sp != 'o' && sp != 'x' && sp != 'X')) ||
01693 lmod == kPFormatLMod_LongLong);
01694 ok &= (sp == 'd' || sp == 'i' || sp == 'o' || sp == 'x' || sp == 'X' ||
01695 sp == 'f' || sp == 'F' || sp == 'e' || sp == 'E' || sp == 'g' || sp == 'G' ||
01696 sp == 'a' || sp == 'A');
01697 break;
01698 case DRMS_TYPE_FLOAT:
01699
01700 case DRMS_TYPE_DOUBLE:
01701
01702
01703 ok &= (sp == 'f' || sp == 'F' || sp == 'e' || sp == 'E' || sp == 'g' || sp == 'G' ||
01704 sp == 'a' || sp == 'A');
01705 break;
01706 case DRMS_TYPE_STRING:
01707
01708 ok &= (sp == 's');
01709 break;
01710 default:
01711
01712 ok = 0;
01713 fprintf(stderr, "Unsupported data type '%s'.\n", drms_type2str(dtype));
01714 }
01715 }
01716 }
01717 else
01718 {
01719
01720 ok = 0;
01721 fprintf(stderr, "Invalid format specifier.\n");
01722 }
01723
01724 if (fcopy2)
01725 {
01726 free(fcopy2);
01727 }
01728
01729 if (ok)
01730 {
01731
01732
01733 ppcnt = strchr(ppcnt + fmtstrlen + 1, '%');
01734 }
01735 }
01736 }
01737
01738 if (!gotformat)
01739 {
01740 ok = 0;
01741 fprintf(stderr, "No format specifier found.\n");
01742 }
01743
01744 if (fcopy)
01745 {
01746 free(fcopy);
01747 }
01748 }
01749
01750 return ok;
01751 }
01752
01753 static int parse_keyword(char **in,
01754 DRMS_Record_t *template,
01755 HContainer_t *slotted,
01756 int *keynum)
01757 {
01758 char *p,*q;
01759 char name[DRMS_MAXKEYNAMELEN]={0}, type[DRMS_MAXNAMELEN]={0}, linkname[DRMS_MAXLINKNAMELEN]={0}, defval[DRMS_DEFVAL_MAXLEN]={0};
01760 char unit[DRMS_MAXUNITLEN]={0}, description[DRMS_MAXCOMMENTLEN]={0}, format[DRMS_MAXFORMATLEN]={0};
01761 char target_key[DRMS_MAXKEYNAMELEN]={0}, constant[DRMS_MAXNAMELEN]={0}, scope[DRMS_MAXNAMELEN]={0}, name1[DRMS_MAXKEYNAMELEN+10]={0};
01762 int num_segments, per_segment, seg;
01763 DRMS_Keyword_t *key;
01764 int chused = 0;
01765 int parserline = -1;
01766 char *extname = NULL;
01767 int keychkrv;
01768
01769 p = q = *in;
01770 SKIPWS(p);
01771 q = p;
01772
01773
01774
01775 if (GETTOKEN(&q,name,sizeof(name)) <= 0) GOTOFAILURE;
01776 if (GETTOKEN(&q,type,sizeof(type)) <= 0) GOTOFAILURE;
01777 if ( !strcasecmp(type,"link") )
01778 {
01779
01780 if(GETTOKEN(&q,linkname,sizeof(linkname)) <= 0) GOTOFAILURE;
01781 if(GETTOKEN(&q,target_key,sizeof(target_key)) <= 0) GOTOFAILURE;
01782 if(GETTOKEN(&q,description,sizeof(description)) < 0) GOTOFAILURE;
01783 }
01784 else
01785 {
01786
01787 if(GETTOKEN(&q,constant,sizeof(constant)) <= 0) GOTOFAILURE;
01788 if(GETTOKEN(&q,scope,sizeof(scope)) <= 0) GOTOFAILURE;
01789 if(GETVALTOKEN(&q,drms_str2type(type), defval,sizeof(defval)) < 0) GOTOFAILURE;
01790 if(GETTOKEN(&q,format,sizeof(format)) <= 0) GOTOFAILURE;
01791 if(GETTOKEN(&q,unit,sizeof(unit)) < 0) GOTOFAILURE;
01792 if(GETTOKEN(&q,description,sizeof(description)) < 0) GOTOFAILURE;
01793 }
01794
01795
01796 #ifdef DEBUG
01797 printf("name = '%s'\n",name);
01798 printf("linkname = '%s'\n",linkname);
01799 printf("target_key = '%s'\n",target_key);
01800 printf("name = '%s'\n",name);
01801 printf("type = '%s'\n",type);
01802 printf("constant = '%s'\n",constant);
01803 printf("scope = '%s'\n",scope);
01804 printf("defval = '%s'\n",defval);
01805 printf("format = '%s'\n",format);
01806 printf("unit = '%s'\n",unit);
01807 printf("description = '%s'\n",description);
01808 #endif
01809
01810 if (keywordname_isreserved(name))
01811 {
01812 fprintf(stderr, "Keyword name '%s' is reserved and cannot be specified.\n", name);
01813 GOTOFAILURE;
01814 }
01815
01816 if (fitsexport_getextname(description, &extname, NULL))
01817 {
01818 fprintf(stderr, "Unparseable description field '%s'.\n", description);
01819 GOTOFAILURE;
01820 }
01821
01822 if (*extname != '\0')
01823 {
01824 keychkrv = fitsexport_fitskeycheck(extname);
01825 if (keychkrv == 2)
01826 {
01827 fprintf(stderr, "WARNING: External keyword name '%s' is reserved and should not be used.\n", extname);
01828 }
01829 else if (keychkrv == 3)
01830 {
01831 fprintf(stderr, "WARNING: External keyword name '%s' will be implicitly generated upon export and should not be used.\n", extname);
01832 }
01833 }
01834
01835 free(extname);
01836
01837
01838 if ( !strcasecmp(type,"link") )
01839 {
01840 key = hcon_allocslot_lower(&template->keywords,name);
01841 XASSERT(key);
01842 memset(key,0,sizeof(DRMS_Keyword_t));
01843 key->info = malloc(sizeof(DRMS_KeywordInfo_t));
01844 XASSERT(key->info);
01845 memset(key->info,0,sizeof(DRMS_KeywordInfo_t));
01846 strcpy(key->info->name,name);
01847 key->record = template;
01848 key->info->islink = 1;
01849 strcpy(key->info->linkname,linkname);
01850 strcpy(key->info->target_key,target_key);
01851 key->info->type = DRMS_TYPE_INT;
01852 key->value.int_val = 0;
01853 key->info->format[0] = 0;
01854 key->info->unit[0] = 0;
01855 key->info->recscope = kRecScopeType_Variable;
01856 drms_keyword_unsetperseg(key);
01857 drms_keyword_unsetintprime(key);
01858 drms_keyword_unsetextprime(key);
01859 key->info->rank = (*keynum)++;
01860
01861
01862
01863 key->info->kwflags |= (key->info->rank + 1) << 16;
01864
01865 strcpy(key->info->description,description);
01866 }
01867 else if (!strcasecmp(constant,"index"))
01868 {
01869
01870
01871
01872 fprintf(stderr, "Specification of an index keyword in a jsd is not allowed.\n");
01873 GOTOFAILURE;
01874 }
01875 else
01876 {
01877 num_segments = hcon_size(&template->segments);
01878
01879 if (!strcasecmp(scope,"segment"))
01880 per_segment = 1;
01881 else if (!strcasecmp(scope,"record"))
01882 per_segment = 0;
01883 else
01884 GOTOFAILURE;
01885
01886 if (per_segment == 1 && num_segments < 1)
01887 {
01888 fprintf(stderr,
01889 "'%s' declared per_segment, but no segments declared.\n",
01890 name);
01891 GOTOFAILURE;
01892 }
01893
01894 for (seg=0; seg<(per_segment==1?num_segments:1); seg++)
01895 {
01896
01897
01898
01899 if (per_segment)
01900 sprintf(name1,"%s_%03d",name,seg);
01901 else
01902 strcpy(name1,name);
01903
01904 if ((key = hcon_lookup_lower(&template->keywords,name1))) {
01905
01906 free(key->info);
01907 }
01908 key = hcon_allocslot_lower(&template->keywords,name1);
01909 XASSERT(key);
01910 memset(key,0,sizeof(DRMS_Keyword_t));
01911 key->info = malloc(sizeof(DRMS_KeywordInfo_t));
01912 XASSERT(key->info);
01913 memset(key->info, 0, sizeof(DRMS_KeywordInfo_t));
01914 strncpy(key->info->name,name1,sizeof(key->info->name));
01915 if (strlen(name1) >= sizeof(key->info->name))
01916 fprintf(stderr,
01917 "WARNING keyword name %s truncated to %lld characters.\n",
01918 name1,
01919 (long long)sizeof(key->info->name)-1);
01920 key->record = template;
01921
01922 if (per_segment)
01923 {
01924 drms_keyword_setperseg(key);
01925 }
01926 else
01927 {
01928 drms_keyword_unsetperseg(key);
01929 }
01930
01931 key->info->islink = 0;
01932 key->info->linkname[0] = 0;
01933 key->info->target_key[0] = 0;
01934 key->info->type = drms_str2type(type);
01935
01936 DRMS_Value_t vholder;
01937 TIME interval = 0;
01938
01939
01940 if (key->info->type == DRMS_TYPE_TIME)
01941 {
01942 interval = atoinc(unit);
01943 if (interval > 0)
01944 {
01945
01946 chused = drms_sscanf2(defval, NULL, 0, DRMS_TYPE_DOUBLE, &vholder);
01947
01948 if (chused != strlen(defval))
01949 {
01950 fprintf(stderr, "Invalid interval value '%s'.\n", defval);
01951 GOTOFAILURE;
01952 }
01953
01954 key->value.time_val = vholder.value.double_val * interval;
01955 }
01956 }
01957
01958 if (interval <= 0)
01959 {
01960
01961
01962
01963 chused = drms_sscanf2(defval, NULL, 0, key->info->type, &vholder);
01964 key->value = vholder.value;
01965 memset(&(vholder.value), 0, sizeof(DRMS_Type_Value_t));
01966
01967 if (chused < 0 || (chused == 0 && key->info->type != DRMS_TYPE_STRING && key->info->type != DRMS_TYPE_TIME))
01968 {
01969 fprintf(stderr, "Invalid default value '%s'.\n", defval);
01970 GOTOFAILURE;
01971 }
01972 else if (chused != strlen(defval) && key->info->type == DRMS_TYPE_TIME)
01973 {
01974 fprintf(stderr, "Invalid time string '%s'.\n", defval);
01975 GOTOFAILURE;
01976 }
01977 }
01978
01979 #ifdef DEBUG
01980 printf("Default value = '%s' = ",defval);
01981 drms_printfval(key->info->type, &key->value);
01982 printf("\n");
01983 #endif
01984 if (!FormatChk(format, key->info->type))
01985 {
01986 fprintf(stderr,
01987 "WARNING: The format specified '%s' is incompatible with the data type '%s' of keyword '%s'.\n",
01988 format,
01989 drms_type2str(key->info->type),
01990 key->info->name);
01991 }
01992 strcpy(key->info->format, format);
01993 strcpy(key->info->unit, unit);
01994 key->info->recscope = kRecScopeType_Variable;
01995 key->info->rank = (*keynum)++;
01996
01997
01998
01999 key->info->kwflags |= (key->info->rank + 1) << 16;
02000
02001 int stat;
02002 DRMS_RecScopeType_t rscope = drms_keyword_str2recscope(constant, &stat);
02003 if (stat == DRMS_SUCCESS)
02004 key->info->recscope = rscope;
02005 else
02006 GOTOFAILURE;
02007 strcpy(key->info->description,description);
02008
02009 drms_keyword_unsetintprime(key);
02010 drms_keyword_unsetextprime(key);
02011
02012 if (drms_keyword_isslotted(key))
02013 {
02014 hcon_insert(slotted, key->info->name, &key);
02015 }
02016 }
02017 }
02018 p = ++q;
02019 *in = q;
02020
02021 return 0;
02022 failure:
02023 fprintf(stderr,"%s, line %d: Invalid keyword descriptor on line %d.\n",
02024 __FILE__, parserline, lineno);
02025 return 1;
02026 }
02027
02028
02029 static int parse_primaryindex(char *desc, DRMS_Record_t *template)
02030 {
02031 int len;
02032 char *start, *p, *q;
02033 DRMS_Keyword_t *key;
02034 char name[DRMS_MAXKEYNAMELEN];
02035
02036
02037
02038 start = desc;
02039 len = getnextline(&start);
02040 while(*start)
02041 {
02042 p = start;
02043 SKIPWS(p);
02044
02045 if (*p == '\n')
02046 {
02047 p++;
02048 start = p;
02049 len = getnextline (&start);
02050 continue;
02051 }
02052
02053 q = p;
02054 if (GETKEYWORD(&q))
02055 return 1;
02056
02057 if (prefixmatch(p,"Index:") || prefixmatch(p,"PrimeKeys:"))
02058 {
02059 p = q;
02060 SKIPWS(p);
02061
02062 while(p<=(start+len) && *p)
02063 {
02064 if (template->seriesinfo->pidx_num >= DRMS_MAXPRIMIDX)
02065 {
02066 printf("Too many keywords in primary index.\n");
02067 return 1;
02068 }
02069
02070
02071 while(p<=(start+len) && isspace(*p))
02072 ++p;
02073 q = name;
02074 while(p<=(start+len) && q<name+sizeof(name) && !isspace(*p) && *p!=',')
02075 *q++ = *p++;
02076 *q++ = 0;
02077 p++;
02078
02079 key = hcon_lookup_lower(&template->keywords,name);
02080 if (key==NULL)
02081 {
02082 printf("Invalid keyword '%s' in primary index.\n",name);
02083 return 1;
02084 }
02085
02086 if (drms_keyword_getsegscope(key) == 1)
02087 {
02088
02089
02090
02091 #ifdef DEBUG
02092 printf("NOT adding primary key '%s' because it is a per-segment keyword.\n",
02093 name);
02094 #endif
02095 }
02096 else if (drms_keyword_isslotted(key))
02097 {
02098 #ifdef DEBUG
02099 printf("NOT adding key '%s' because it is slotted."
02100 "The corresopnding index key is prime instead.\n",
02101 name);
02102
02103
02104 #endif
02105 drms_keyword_setextprime(key);
02106
02107
02108 DRMS_Keyword_t *idxkey = drms_keyword_indexfromslot(key);
02109 if (idxkey)
02110 {
02111 template->seriesinfo->pidx_keywords[(template->seriesinfo->pidx_num)++] =
02112 idxkey;
02113 }
02114 else
02115 {
02116 fprintf(stderr, "Slotted keyword '%s' has no corresponding index keyword.\n", name);
02117 return 1;
02118 }
02119 }
02120 else
02121 {
02122 #ifdef DEBUG
02123 printf("adding primary key '%s'\n",name);
02124 #endif
02125 template->seriesinfo->pidx_keywords[(template->seriesinfo->pidx_num)++] =
02126 key;
02127
02128
02129
02130 drms_keyword_setintprime(key);
02131 drms_keyword_setextprime(key);
02132 }
02133 }
02134
02135 #ifdef DEBUG
02136 { int i;
02137 printf("Primary indices: ");
02138 for (i=0; i<template->seriesinfo->pidx_num; i++)
02139 printf("'%s' ",(template->seriesinfo->pidx_keywords[i])->info->name); }
02140 printf("\n");
02141 #endif
02142
02143 break;
02144 }
02145
02146 start += len+1;
02147 len = getnextline(&start);
02148 }
02149
02150
02151 DRMS_Keyword_t *pKey = NULL;
02152 const char *keyname = NULL;
02153 HIterator_t *hit = hiter_create(&(template->keywords));
02154
02155 if (hit)
02156 {
02157 while ((pKey =
02158 (DRMS_Keyword_t *)hiter_extgetnext(hit, &keyname)) != NULL)
02159 {
02160 if (drms_keyword_isslotted(pKey))
02161 {
02162 if (!drms_keyword_getextprime(pKey))
02163 {
02164 fprintf(stderr,
02165 "Slotted key '%s' was not declared drms prime.\n",
02166 keyname);
02167 return 1;
02168 }
02169 }
02170 }
02171
02172 hiter_destroy(&hit);
02173 }
02174
02175 return 0;
02176 }
02177
02178 static int parse_dbindex(char *desc, DRMS_Record_t *template)
02179 {
02180 int len;
02181 char *start, *p, *q;
02182 DRMS_Keyword_t *key;
02183 char name[DRMS_MAXNAMELEN];
02184 int exist = 0;
02185
02186
02187
02188 start = desc;
02189 len = getnextline(&start);
02190 while(*start)
02191 {
02192 p = start;
02193 SKIPWS(p);
02194
02195 if (*p == '\n')
02196 {
02197 p++;
02198 start = p;
02199 len = getnextline (&start);
02200 continue;
02201 }
02202
02203 q = p;
02204 if (GETKEYWORD(&q))
02205 return 1;
02206
02207 if (prefixmatch(p,"DBIndex:"))
02208 {
02209 exist = 1;
02210 p = q;
02211 SKIPWS(p);
02212
02213 while(p<=(start+len) && *p)
02214 {
02215 if (template->seriesinfo->dbidx_num >= DRMS_MAXDBIDX)
02216 {
02217 printf("Too many keywords in primary index.\n");
02218 return 1;
02219 }
02220
02221
02222 while(p<=(start+len) && isspace(*p))
02223 ++p;
02224 q = name;
02225 while(p<=(start+len) && q<name+sizeof(name) && !isspace(*p) && *p!=',')
02226 *q++ = *p++;
02227 *q++ = 0;
02228 p++;
02229
02230 key = hcon_lookup_lower(&template->keywords,name);
02231 if (key==NULL)
02232 {
02233 printf("Invalid keyword '%s' in db index.\n",name);
02234 return 1;
02235 }
02236
02237 if (drms_keyword_getsegscope(key) == 1)
02238 {
02239
02240
02241
02242 #ifdef DEBUG
02243 printf("NOT adding index key '%s' because it is a per-segment keyword.\n",
02244 name);
02245 #endif
02246 }
02247 else if (drms_keyword_isslotted(key))
02248 {
02249 #ifdef DEBUG
02250 printf("NOT adding key '%s' because it is slotted."
02251 "The corresopnding index key will have a dbindex instead.\n",
02252 name);
02253 #endif
02254
02255 DRMS_Keyword_t *idxkey = drms_keyword_indexfromslot(key);
02256 if (idxkey)
02257 {
02258 template->seriesinfo->dbidx_keywords[(template->seriesinfo->dbidx_num)++] =
02259 idxkey;
02260 }
02261 else
02262 {
02263 fprintf(stderr, "Slotted keyword '%s' has no corresponding index keyword.\n", name);
02264 return 1;
02265 }
02266 }
02267 else
02268 {
02269 #ifdef DEBUG
02270 printf("adding db idx '%s'\n",name);
02271 #endif
02272 template->seriesinfo->dbidx_keywords[(template->seriesinfo->dbidx_num)++] =
02273 key;
02274 }
02275 }
02276
02277 #ifdef DEBUG
02278 { int i;
02279 printf("DB indices: ");
02280 for (i=0; i<template->seriesinfo->dbidx_num; i++)
02281 printf("'%s' ",(template->seriesinfo->dbidx_keywords[i])->info->name); }
02282 printf("\n");
02283 #endif
02284
02285 break;
02286 }
02287
02288 start += len+1;
02289 len = getnextline(&start);
02290 }
02291
02292 if (!exist) {
02293 template->seriesinfo->dbidx_num = -1;
02294 }
02295
02296 return 0;
02297 }
02298
02299 static int keywordname_isreserved(const char *name)
02300 {
02301 return (base_drmskeycheck(name) == 2);
02302 }
02303
02304
02305
02306 static int getnextline(char **start)
02307 {
02308 char *p;
02309 int length;
02310
02311 length = 0;
02312 p = *start;
02313 SKIPWS(p);
02314 while(*p && *p=='#')
02315 {
02316 while(*p && *p != '\n')
02317 {
02318 p++;
02319 }
02320
02321 if (*p == '\n')
02322 {
02323 p++;
02324 lineno++;
02325 }
02326 }
02327
02328 *start = p;
02329
02330
02331 while(*p && *p != '\n')
02332 {
02333 length++;
02334 ++p;
02335 }
02336
02337 lineno++;
02338 return length;
02339 }
02340
02341
02342
02343
02344
02345
02346
02347
02348
02349
02350
02351
02352 static int getstring(char **inn, char *out, int maxlen) {
02353 char escape;
02354 int len;
02355 char *in;
02356
02357 in = *inn;
02358
02359 SKIPWS(in);
02360
02361 len = -1;
02362 if ( *in=='"' || *in=='\'' )
02363 {
02364 len++;
02365
02366
02367 escape = *in;
02368
02369 in++;
02370 while(*in && *in != escape && len<maxlen-1)
02371 {
02372 *out++ = *in++;
02373 len++;
02374 }
02375 if ( *in==escape )
02376 ++in;
02377
02378 }
02379 else
02380 {
02381
02382 while(*in && !ISBLANK(*in) && *in!=',' && *in != '\n' && len<maxlen-1)
02383 {
02384 *out++ = *in++;
02385 len++;
02386 }
02387
02388 if (len >= 0)
02389 {
02390 len++;
02391 }
02392 }
02393
02394 *out = 0;
02395
02396
02397 SKIPWS(in);
02398 *inn = in;
02399 return len;
02400 }
02401
02402
02403
02404
02405
02406
02407 static int getvalstring(char **inn, char *out, int maxlen)
02408 {
02409 char escape;
02410 int len;
02411 char *in;
02412
02413 in = *inn;
02414
02415 SKIPWS(in);
02416
02417 len = -1;
02418 if ( *in=='"' || *in=='\'' )
02419 {
02420 len++;
02421
02422
02423 escape = *in;
02424 *out++ = *in++;
02425 len++;
02426
02427 while(*in && *in != escape && len<maxlen-1)
02428 {
02429 *out++ = *in++;
02430 len++;
02431 }
02432 if ( *in==escape )
02433 {
02434 *out++ = *in++;
02435 len++;
02436 }
02437 }
02438 else
02439 {
02440
02441 return getstring(inn, out, maxlen);
02442 }
02443
02444 *out = 0;
02445
02446
02447 SKIPWS(in);
02448 *inn = in;
02449 return len;
02450 }
02451
02452 int getshort(char **in, int16_t *val, int parserline)
02453 {
02454 char *endptr;
02455 long long ival;
02456
02457 ival = (int)strtoll(*in, &endptr, 0);
02458 if (ival == 0 && endptr == *in )
02459 {
02460 fprintf(stderr,
02461 "%s, line %d: The string '%s' on line %d of JSOC series descriptor is not an integer.\n",
02462 __FILE__,
02463 parserline,
02464 *in,
02465 lineno);
02466 return 1;
02467 }
02468 else if (ival < INT16_MIN || ival > INT16_MAX)
02469 {
02470 fprintf(stderr,
02471 "%s, line %d: The string '%s' on line %d of JSOC series descriptor represents an out-of-range integer.\n",
02472 __FILE__,
02473 parserline,
02474 *in,
02475 lineno);
02476 return 1;
02477 }
02478 else
02479 {
02480 *val = (int16_t)ival;
02481 *in = endptr;
02482 return 0;
02483 }
02484 }
02485
02486 int getint(char **in, int *val, int parserline)
02487 {
02488 char *endptr;
02489 long long ival;
02490
02491 ival = (int)strtoll(*in, &endptr, 0);
02492 if (ival == 0 && endptr == *in )
02493 {
02494 fprintf(stderr,
02495 "%s, line %d: The string '%s' on line %d of JSOC series descriptor is not an integer.\n",
02496 __FILE__,
02497 parserline,
02498 *in,
02499 lineno);
02500 return 1;
02501 }
02502 else if (ival < INT_MIN || ival > INT_MAX)
02503 {
02504 fprintf(stderr,
02505 "%s, line %d: The string '%s' on line %d of JSOC series descriptor represents an out-of-range integer.\n",
02506 __FILE__,
02507 parserline,
02508 *in,
02509 lineno);
02510 return 1;
02511 }
02512 else
02513 {
02514 *val = (int)ival;
02515 *in = endptr;
02516 return 0;
02517 }
02518 }
02519
02520
02521
02522
02523
02524
02525
02526
02527
02528
02529
02530
02531
02532
02533
02534
02535
02536
02537
02538
02539
02540
02541
02542
02543
02544
02545
02546
02547
02548
02549
02550
02551
02552
02553
02554
02555
02556
02557
02558
02559
02560
02561
02562
02563
02564
02565
02566
02567
02568
02569
02570
02571
02572
02573
02574
02575
02576 static int gettoken(char **in, char *copy, int maxlen, int parserline)
02577 {
02578 int len;
02579 int ln = lineno;
02580
02581 if((len = getstring(in,copy,maxlen))<0)
02582 return -1;
02583
02584 #if 0
02585 if ((**in == '\n' || **in == ',') && len == 0)
02586 {
02587 return -1;
02588 }
02589 #endif
02590
02591 if (**in != '\n' && **in != '\0' && ln == lineno)
02592 {
02593 if (**in != ',')
02594 {
02595 fprintf(stderr,
02596 "%s, line %d: Expected comma (',') on line %d of JSOC series descriptor.\n",
02597 __FILE__,
02598 parserline,
02599 lineno);
02600 return -1;
02601 }
02602
02603 ++(*in);
02604 }
02605
02606 return len;
02607 }
02608
02609
02610
02611
02612
02613
02614
02615
02616
02617
02618
02619
02620
02621
02622 static int getvaltoken(char **in, DRMS_Type_t type, char *copy, int maxlen, int parserline)
02623 {
02624 if (type == DRMS_TYPE_STRING)
02625 {
02626 int len;
02627 int ln = lineno;
02628
02629 if((len = getvalstring(in,copy,maxlen))<0)
02630 return -1;
02631
02632 #if 0
02633 if ((**in == '\n' || **in == ',') && len == 0)
02634 {
02635 return -1;
02636 }
02637 #endif
02638
02639 if (**in != '\n' && **in != '\0' && ln == lineno)
02640 {
02641 if (**in != ',')
02642 {
02643 fprintf(stderr,
02644 "%s, line %d: Expected comma (',') on line %d of JSOC series descriptor.\n",
02645 __FILE__,
02646 parserline,
02647 lineno);
02648 return -1;
02649 }
02650
02651 ++(*in);
02652 }
02653
02654 return len;
02655 }
02656 else
02657 {
02658 return GETTOKEN(in, copy, maxlen);
02659 }
02660 }
02661
02662 static inline int prefixmatch(char *token, const char *pattern)
02663 {
02664 return !strncasecmp(token,pattern,strlen(pattern));
02665 }
02666
02667
02668
02669
02670
02671
02672 int getkeyword(char **line, int parserline)
02673 {
02674 char *p;
02675
02676 p = *line;
02677 SKIPWS(p);
02678 while (isalpha(*p)) ++p;
02679 SKIPWS(p);
02680 if (*p != ':')
02681 {
02682 fprintf(stderr,"%s, line %d: Syntax error in JSOC series descriptor. "
02683 "Expected ':' at line %d, column %d.\n", __FILE__,
02684 parserline, (int)(p - *line), lineno);
02685 return 1;
02686 }
02687 *line = p+1;
02688 return 0;
02689 }
02690
02691 void drms_keyword_print_jsd(DRMS_Keyword_t *key) {
02692 printf("Keyword:%s",key->info->name);
02693 if (key->info->islink) {
02694 printf(", link, %s, %s", key->info->linkname, key->info->target_key);
02695 } else {
02696 printf(", %s", drms_type2str(key->info->type));
02697 int stat;
02698 const char *rscope = drms_keyword_getrecscopestr(key, &stat);
02699 fprintf(stdout, ", %s", stat == DRMS_SUCCESS ? rscope : NULL);
02700
02701
02702
02703
02704 if (drms_keyword_getperseg(key))
02705 printf(", segment");
02706 else
02707 printf(", record");
02708 printf(", ");
02709 if (key->info->type == DRMS_TYPE_STRING) {
02710 char qf[DRMS_MAXFORMATLEN+2];
02711 sprintf(qf, "\"%s\"", key->info->format);
02712 printf(qf, key->value.string_val);
02713 }
02714 else
02715 drms_keyword_printval(key);
02716 if (key->info->unit[0] && key->info->unit[0] != ' ') {
02717 printf(", \"%s\", \"%s\"", key->info->format, key->info->unit);
02718 } else {
02719 printf(", %s, none", key->info->format);
02720 }
02721 }
02722 printf(", \"%s\"\n", key->info->description);
02723 }
02724
02725 void drms_segment_print_jsd(DRMS_Segment_t *seg) {
02726 int i;
02727 printf("Data: %s, ", seg->info->name);
02728 if (seg->info->islink) {
02729 printf("link, %s, %s", seg->info->linkname, seg->info->target_seg);
02730 if (seg->info->naxis) {
02731 printf(", %d", seg->info->naxis);
02732 printf(", %d", seg->axis[0]);
02733 for (i=1; i<seg->info->naxis; i++) {
02734 printf(", %d", seg->axis[i]);
02735 }
02736 }
02737 else
02738 {
02739
02740 printf(", %d", 0);
02741 }
02742 } else {
02743 switch(seg->info->scope)
02744 {
02745 case DRMS_CONSTANT:
02746 printf("constant");
02747 break;
02748 case DRMS_VARIABLE:
02749 printf("variable");
02750 break;
02751 case DRMS_VARDIM:
02752 printf("vardim");
02753 break;
02754 default:
02755 printf("Illegal value: %d", (int)seg->info->scope);
02756 }
02757 printf(", %s, %d", drms_type2str(seg->info->type), seg->info->naxis);
02758 if (seg->info->naxis) {
02759 printf(", %d", seg->axis[0]);
02760 for (i=1; i<seg->info->naxis; i++) {
02761 printf(", %d", seg->axis[i]);
02762 }
02763 }
02764
02765 printf(", \"%s\", ", seg->info->unit);
02766
02767 const char *protstr = drms_prot2str(seg->info->protocol);
02768 if (protstr)
02769 {
02770 printf(protstr);
02771 }
02772 else
02773 {
02774 printf("Illegal protocol: %d", (int)seg->info->protocol);
02775 }
02776
02777 if (seg->info->protocol == DRMS_FITS ||
02778 seg->info->protocol == DRMS_TAS)
02779 {
02780
02781 printf(", \"%s\"", seg->cparms);
02782 }
02783
02784 if ((seg->info->protocol == DRMS_TAS ||
02785 seg->info->protocol == DRMS_FITS ||
02786 seg->info->protocol == DRMS_FITZ ||
02787 seg->info->protocol == DRMS_BINARY ||
02788 seg->info->protocol == DRMS_BINZIP) &&
02789 (seg->info->type != DRMS_TYPE_FLOAT &&
02790 seg->info->type != DRMS_TYPE_DOUBLE))
02791 {
02792 printf(", %f", seg->bzero);
02793 printf(", %f", seg->bscale);
02794 }
02795 }
02796 printf(", \"%s\"\n", seg->info->description);
02797 }
02798
02799 void drms_link_print_jsd(DRMS_Link_t *link) {
02800 printf("Link: %s, %s, ", link->info->name, link->info->target_series);
02801 if (link->info->type == STATIC_LINK)
02802 printf("static");
02803 else
02804 printf("dynamic");
02805 printf(", \"%s\"\n", link->info->description);
02806 }
02807
02808 void drms_jsd_printfromrec(DRMS_Record_t *rec) {
02809 const int fwidth=17;
02810 HIterator_t hit;
02811 DRMS_Link_t *link;
02812 DRMS_Keyword_t *key;
02813 DRMS_Segment_t *seg;
02814 int npkeys = 0;
02815 char **extpkeys;
02816 DRMS_Keyword_t *dbidxkw = NULL;
02817 const char *dbidxkwname = NULL;
02818 int16_t newSuRet = INT16_MIN;
02819 int16_t stagingRet = INT16_MIN;
02820
02821 printf("#=====General Series Information=====\n");
02822 printf("%-*s\t%s\n",fwidth,"Seriesname:",rec->seriesinfo->seriesname);
02823 printf("%-*s\t\"%s\"\n",fwidth,"Author:",rec->seriesinfo->author);
02824 printf("%-*s\t%s\n",fwidth,"Owner:",rec->seriesinfo->owner);
02825 printf("%-*s\t%d\n",fwidth,"Unitsize:",rec->seriesinfo->unitsize);
02826 printf("%-*s\t%d\n",fwidth,"Archive:",rec->seriesinfo->archive);
02827
02828 newSuRet = drms_series_getnewsuretention(rec->seriesinfo);
02829 stagingRet = drms_series_getstagingretention(rec->seriesinfo);
02830 printf("%-*s\t%hd\n", fwidth, "Retention:", newSuRet);
02831 if (stagingRet == 0)
02832 {
02833 stagingRet = (int16_t)abs(STDRETENTION);
02834 }
02835 printf("%-*s\t%hd\n", fwidth, "StagingRetention:", stagingRet);
02836
02837 printf("%-*s\t%d\n",fwidth,"Tapegroup:",rec->seriesinfo->tapegroup);
02838
02839
02840 extpkeys = drms_series_createpkeyarray(rec->env, rec->seriesinfo->seriesname, &npkeys, NULL);
02841 if (extpkeys)
02842 {
02843 if ( npkeys > 0)
02844 { int i;
02845 printf("%-*s\t%s",fwidth,"PrimeKeys:",extpkeys[0]);
02846 for (i=1; i<npkeys; i++)
02847 printf(", %s", extpkeys[i]);
02848 printf("\n");
02849 }
02850 drms_series_destroypkeyarray(&extpkeys, npkeys);
02851 }
02852
02853 if (rec->seriesinfo->dbidx_num) {
02854 for (int i = 0; i < rec->seriesinfo->dbidx_num; i++) {
02855 dbidxkw = rec->seriesinfo->dbidx_keywords[i];
02856
02857
02858
02859
02860 if (drms_keyword_isindex(dbidxkw))
02861 {
02862 dbidxkwname = dbidxkw->info->name;
02863 dbidxkw = drms_keyword_slotfromindex(dbidxkw);
02864 if (!dbidxkw)
02865 {
02866 fprintf(stderr, "Invalid index keyword '%s'\n.", dbidxkwname);
02867 }
02868 }
02869
02870 if (i == 0)
02871 {
02872 printf("%-*s\t%s",fwidth,"DBIndex:", dbidxkw->info->name);
02873 }
02874 else
02875 {
02876 printf(", %s", dbidxkw->info->name);
02877 }
02878 }
02879 printf("\n");
02880 }
02881
02882 printf("%-*s\t\"%s\"\n",fwidth,"Description:",rec->seriesinfo->description);
02883 printf("\n#=====Links=====\n");
02884 hiter_new_sort(&hit, &rec->links, drms_link_ranksort);
02885 while( (link = (DRMS_Link_t *)hiter_getnext(&hit)) )
02886 drms_link_print_jsd(link);
02887
02888 printf("\n#=====Keywords=====\n");
02889 hiter_new_sort(&hit, &rec->keywords, drms_keyword_ranksort);
02890 while( (key = (DRMS_Keyword_t *)hiter_getnext(&hit)) )
02891 {
02892 if (!drms_keyword_getimplicit(key))
02893 {
02894 drms_keyword_print_jsd(key);
02895 }
02896 }
02897
02898 printf("\n#=====Segments=====\n");
02899 hiter_new_sort(&hit, &rec->segments, drms_segment_ranksort);
02900 while( (seg = (DRMS_Segment_t *)hiter_getnext(&hit)) )
02901 drms_segment_print_jsd(seg);
02902 }
02903
02904 void drms_jsd_print(DRMS_Env_t *drms_env, const char *seriesname) {
02905 int status = DRMS_SUCCESS;
02906
02907
02908
02909
02910
02911 DRMS_Record_t *rec = drms_create_jsdtemplate_record(drms_env, seriesname, &status);
02912
02913 if (rec==NULL)
02914 {
02915 printf("Series '%s' does not exist. drms_template_record returned "
02916 "status=%d\n",seriesname,status);
02917 }
02918 else
02919 {
02920 drms_jsd_printfromrec(rec);
02921 drms_destroy_jsdtemplate_record(&rec);
02922 }
02923 }
02924
02925
02926
02927
02928 void drms_sprint_rec_query(char *querystring, DRMS_Record_t *rec)
02929 {
02930 int iprime, nprime=0;
02931 char **external_pkeys, *pkey;
02932 DRMS_Keyword_t *rec_key;
02933
02934 if (!querystring)
02935 return;
02936 if (!rec)
02937 {
02938 sprintf(querystring, "** No Record **");
02939 return;
02940 }
02941 sprintf(querystring, "%s",rec->seriesinfo->seriesname);
02942 external_pkeys =
02943 drms_series_createpkeyarray(rec->env, rec->seriesinfo->seriesname, &nprime, NULL);
02944 if (external_pkeys && nprime > 0)
02945 {
02946 for (iprime = 0; iprime < nprime; iprime++)
02947 {
02948 pkey = external_pkeys[iprime];
02949 rec_key = drms_keyword_lookup (rec, pkey, 1);
02950 strcat(querystring, "[");
02951 drms_keyword_snprintfval (rec_key, querystring+strlen(querystring), DRMS_MAXQUERYLEN);
02952 strcat(querystring, "]");
02953 }
02954 }
02955 else
02956 sprintf(querystring, "[:#%lld]",rec->recnum);
02957
02958
02959 for (iprime = 0; iprime < nprime; iprime++)
02960 {
02961 if (external_pkeys[iprime])
02962 {
02963 free(external_pkeys[iprime]);
02964 }
02965 }
02966
02967 free(external_pkeys);
02968 }
02969
02970
02971 void drms_fprint_rec_query(FILE *fp, DRMS_Record_t *rec)
02972 {
02973 char querystring[DRMS_MAXQUERYLEN];
02974 drms_sprint_rec_query(querystring, rec);
02975 fprintf(fp, "%s", querystring);
02976 }
02977
02978
02979 void drms_print_rec_query(DRMS_Record_t *rec)
02980 {
02981 drms_fprint_rec_query(stdout, rec);
02982 }