diff options
Diffstat (limited to 'pkg/vocl/voclient.c')
-rw-r--r-- | pkg/vocl/voclient.c | 1754 |
1 files changed, 1754 insertions, 0 deletions
diff --git a/pkg/vocl/voclient.c b/pkg/vocl/voclient.c new file mode 100644 index 00000000..e140b7dd --- /dev/null +++ b/pkg/vocl/voclient.c @@ -0,0 +1,1754 @@ +/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + */ + +#define import_spp +#define import_libc +#define import_stdio +#define import_prstat +#define import_xwhen +#include <iraf.h> + +#include "config.h" +#include "clmodes.h" +#include "operand.h" +#include "mem.h" +#include "grammar.h" +#include "opcodes.h" +#include "param.h" +#include "task.h" +#include "errs.h" +#include "construct.h" +#include "ytab.h" /* pick up yacc token #defines */ + +#include "voclient.h" + +#define SZ_RESBUF (32*SZ_LINE) +#define DEF_RESATTR "ServiceURL" +#define MAX_ATTRS 32 + + +extern int do_error; /* runtime error handling */ +extern ErrCom errcom; + +extern int optbl[]; +extern char *ifnames[]; + +static int debug = 0; +static int reg_nresolved = 0; + +int VOClient_initialized = 0; + +char *voGetStrArg(); +int voGetIntArg(); +double voGetDblArg(); + +#ifdef FOO +typedef int DAL; /* DAL type aliases */ +typedef int Query; /* DAL Query object */ +typedef int QResponse; /* Query Response object */ +typedef int QRecord; /* Query Record (row) object */ +typedef int QRAttribute; /* Query Attr (col) object */ +typedef int RegQuery; /* Registry Query object */ +typedef int RegResult; /* Query Result object */ +#endif + + + +/** + * VO Client Library: + * ---------------------- + * + * stat = initVOClient (opts) int [opt] + * stat = closeVOClient (quit_flag) int [opt] + * stat = restartVOClient (quit_flag) int [opt] + * + * stat = validateObj (obj) int + * stat = vocReady () bool + * + * DAL Service Interface: (task prefix 'dal') + * ---------------------- + * + * Hi-Level Interface: + * + * qres = dalConeSvc (url, ra, dec, sr) int + * qres = dalSiapSvc (url, ra, dec, rsize[, dsize[, fmt]]) int + * + * count = dalRecordCount (qres) int + * + * stat = dalGetData (qres, recnum, fname) int + * + * fname = getData (acref) string + * fname = getData (acref, fname) string + * fname = getData (rec, acref, fname) string + * + * rec = dalGetRecord (qres, recnum) int + * str = dalGetStr (qres, attrname, recnum) string + * ival = dalGetInt (qres, attrname, recnum) int + * dval = dalGetDbl (qres, attrname, recnum) double + * + * + * Low-Level Interface: + * + * count = dalAttrCount (rec) int + * attrname = dalAttrName (rec, index) string + * ival = dalIntAttr (rec, attrname) int + * dval = dalFloatAttr (rec, attrname) double + * str = dalStrAttr (rec, attrname) string + * + * nscan = dalAttrScan (rec, attr_list, <p1>...<pN>) *NYI + * + * + * Registry Search Interface: (task prefix 'reg') + * -------------------------- + * + * str = regResolver (shortName,[svctype[,attr[,index]]]) string + * N = nresolved () int + * + * resource = regSearch (term [, orValues]) int + * resource = regSearch (keywords, orValues) int + * resource = regSearch (sql, keywords, orValues) int + * + * resource = regSvcSearch (searchTerm, svcType, bpass, + * clevel, orValues) int + * + * count = regResultCount (resource) int + * str = regValue (resource, attr_list, resIndex) int + * + * nscan = regScan (resource, attribute, resIndex, <p>) *NYI + */ + + + + +/* VOCOP -- Process a VO Client request. + */ +vocop (opcode, op_index, nargs) +int opcode; +int op_index; +int nargs; +{ + struct operand o; + int op = optbl[op_index]; + + + if (debug) + printf ("vocop: opcode=%d index=%d nargs=%d\n", + opcode, op_index, nargs); + +#ifndef USE_VOCOP + if (opcode != OP_INITVOC && opcode != OP_RESTARTVOC) { + if (VOClient_initialized) { + int voc_status = voc_ready(); + if (voc_status != 0) { + VOClient_initialized = 0; + voc_closeVOClient (0); + if (voc_initVOClient (envget("vo_runid")) != OK) + cl_error (E_UERR, "Error re-initializing VOClient"); + } + } else { + if (voc_initVOClient (envget("vo_runid")) != OK) + cl_error (E_UERR, "Error initializing VOClient"); + else { + VOClient_initialized = 1; + sleep (3); + } + } + } +#else + VOClient_initialized = 1; +#endif + + switch (opcode) { + case OP_INITVOC: + /* Initialize the VOClient + */ + if (nargs > 1) + cl_error (E_UERR, "usage: initVOClient([opt_string])\n"); + else + cl_initVOClient (nargs); + break; + + case OP_CLOSEVOC: + /* Shut down the VO Client connection + */ + if (nargs != 1) + cl_error (E_UERR, "usage: closeVOClient(shutdown_flag)\n"); + else + cl_closeVOClient (); + break; + + case OP_RESTARTVOC: + /* Restart the VO Client connection + */ + if (nargs > 0) + cl_error (E_UERR, "usage: restartVOClient()\n"); + else + cl_restartVOClient (); + break; + + case OP_CONESVC: + /* Query a Cone Service + */ + if (nargs < 4) + cl_error (E_UERR, "usage: res = dalConeSvc(url, ra, dec, sr)"); + else + cl_dalConeSvc (); + break; + + case OP_SIAPSVC: + /* Query a SIAP Service + */ + if (nargs < 4) + cl_error (E_UERR, + "usage: res = dalSiapSvc(url, ra, dec, rasz[, decsz[, fmt]])"); + else + cl_dalSiapSvc (nargs); + break; + + case OP_RECCNT: + /* Count DAL query result records + */ + if (nargs != 1) + cl_error (E_UERR, "usage: dalRecordCount(qres)\n"); + else + cl_dalRecordCount (); + break; + + case OP_GETREC: + /* Get a QRecord handle from a QResponse + */ + if (nargs != 2) + cl_error (E_UERR, "usage: dalGetRecord(qres, recnum)\n"); + else + cl_dalGetRecord (); + break; + + case OP_GETDATA: + /* Get a dataset pointed to by an AccessReference field at the + * given record number in the query response. Download to the + * named file. + */ + if (nargs != 3) + cl_error (E_UERR, "usage: dalGetData(qres, recnum, fname)\n"); + else + cl_dalGetData (); + break; + + case OP_GETSTR: + /* Get a string-valued attribute from a DAL response table. + */ + if (nargs != 3) + cl_error (E_UERR, "usage: dalGetStr(qres, attrname, recnum)\n"); + else + cl_dalGetStr (); + break; + + case OP_GETINT: + /* Get an integer-valued attribute from a DAL response table. + */ + if (nargs != 3) + cl_error (E_UERR, "usage: dalGetInt(qres, attrname, recnum)\n"); + else + cl_dalGetInt (); + break; + + case OP_GETDBL: + /* Get a real-valued attribute from a DAL response table. + */ + if (nargs != 3) + cl_error (E_UERR, "usage: dalGetDbl(qres, attrname, recnum)\n"); + else + cl_dalGetDbl (); + break; + + case OP_ATTRCNT: + /* Count number of attributes in a QRecord + */ + if (nargs != 1) + cl_error (E_UERR, "usage: dalAttrCount(rec)\n"); + else + cl_dalAttrCount (); + break; + + case OP_ATTRNAME: + /* Get an attribute name for the given column index + */ + if (nargs != 2) + cl_error (E_UERR, "usage: dalAttrName(rec,index)\n"); + else + cl_dalAttrName (); + break; + + case OP_INTATTR: + /* Get a an attribute as an integer. + */ + if (nargs != 2) + cl_error (E_UERR, "usage: dalIntAttr(rec,attrname)\n"); + else + cl_dalIntAttr (); + break; + + case OP_FLOATATTR: + /* Get a an attribute as a real. + */ + if (nargs != 2) + cl_error (E_UERR, "usage: dalFloatAttr(rec,attrname)\n"); + else + cl_dalFloatAttr (); + break; + + case OP_STRATTR: + /* Get a an attribute as a string. + */ + if (nargs != 2) + cl_error (E_UERR, "usage: dalStrAttr(rec,attrname)\n"); + else + cl_dalStrAttr (); + break; + + case OP_DATASET: + /* Download the dataset at the given acref to a named file + */ + if (nargs > 3) + cl_error (E_UERR, "usage: dalDataset([rec,] acref [,fname])\n"); + else + cl_dalDataset (nargs); + break; + + case OP_ATTRSCAN: + /* Get the value of one or more attributes. + */ + if (nargs < 2) + cl_error (E_UERR, "usage: dalAttrScan(rec,attrList,p1,...,pN)\n"); + else + cl_dalAttrScan (nargs); + break; + + + case OP_REGSEARCH: + /* Get the value of the named resource attribute. + * resource = regSearch (term [, orValues]) + * resource = regSearch (keywords, orValues) + * resource = regSearch (sql, keywords, orValues) + */ + if (nargs < 1 || nargs > 3) + cl_error (E_UERR, "usage: regSearch(res,attr)\n"); + else + cl_regSearch (nargs); + break; + + case OP_REGSVCSEARCH: + /* Get the value of the named resource attribute. + * resource = regSvcSearch (term, svcType, bpass, clevel, orValues) + */ + if (nargs != 5) + cl_error (E_UERR, + "usage: regSvcSearch(term,svcType,bpass,clevel,orVals)\n"); + else + cl_regSvcSearch (); + break; + + case OP_REGCOUNT: + /* Get the value of the named resource attribute. + */ + if (nargs > 1) + cl_error (E_UERR, "usage: regResultCount(res)\n"); + else + cl_regResultCount (); + break; + + case OP_REGBPASS: + /* Set a Bandpass constraint on a query. + */ + if (nargs != 2) + cl_error (E_UERR, "usage: regSetBandpass(query, bpass)\n"); + else + cl_regSetBandpass (); + break; + + case OP_REGSVC: + /* Set a ServiceType constraint on a query. + */ + if (nargs != 2) + cl_error (E_UERR, "usage: regSetService(res, svcType)\n"); + else + cl_regSetService (); + break; + + case OP_REGCONTENT: + /* Set a ContentLevel constraint on a query. + */ + if (nargs != 2) + cl_error (E_UERR, "usage: regSetContent(res, clevel)\n"); + else + cl_regSetContent (); + break; + + case OP_REGVALUE: + /* Get the value of the named resource attribute. + * nscan = regValue (resource, attribute, resIndex, <p>) + */ + if (nargs < 2 || nargs > 3) + cl_error (E_UERR, "usage: regValue(res,attr)\n"); + else + cl_regValue (); + break; + + + case OP_REGRESOLVER: + /* Get the number of resources found with the last regResolver() call. + */ + if (nargs < 1 || nargs > 4) + cl_error (E_UERR, + "usage: regResolver(id_str [, svctyp [, attr [, index] ] ])\n"); + else + cl_regResolver (nargs); + break; + + case OP_NRESOLVED: + /* Get the number of resources found with the last regResolver() call. + */ + if (nargs > 0) + cl_error (E_UERR, "usage: nresolved()\n"); + else + cl_regNResolved (); + break; + + case OP_VALIDOBJ: + /* Validate an object in the VO Client. + */ + if (nargs != 1) + cl_error (E_UERR, "usage: validObj(obj)\n"); + else + cl_validObj (); + break; + + case OP_VOCREADY: + /* Verify that the VO Client is ready. + */ + if (nargs != 1) + cl_error (E_UERR, "usage: vocReady()\n"); + else + cl_vocReady (); + break; + + default: + cl_error (E_IERR, e_badsw, op, "voclient has invalid intrfunc()"); + break; + } + + return (OK); +} + + +/* Initialize the VO Client. + */ +int +cl_initVOClient (nargs) +int nargs; +{ + char *opts = NULL, *runid = NULL; + struct operand o; + + if (nargs) + opts = voGetStrArg (); + + runid = envget ("vo_runid"); /* Get the system RUNID */ + if (runid) { + if (opts) + strcat (opts, ","); + strcat (opts, runid); + } + + o.o_type = OT_INT; + if (! VOClient_initialized) + o.o_val.v_i = voc_initVOClient (opts); + else + o.o_val.v_i = OK; + pushop (&o); + + VOClient_initialized = 1; + + if (opts) + free ((char *) opts); + return (OK); +} + + +/* Close the VO Client connection. + */ +int +cl_closeVOClient () +{ + int shutdown = 0; + struct operand o; + + shutdown = voGetIntArg (); + + /* The close is a void function so we simply return a dummy OK + * value to the caller. + */ + if (VOClient_initialized) + (void) voc_closeVOClient (shutdown); + + o.o_type = OT_INT; + o.o_val.v_i = OK; + pushop (&o); + + VOClient_initialized = 0; + + return (OK); +} + + +/* Restart the VO Client. + */ +int +cl_restartVOClient () +{ + char *opts = NULL; + struct operand o; + + o.o_type = OT_INT; + voc_closeVOClient (1); + if (VOClient_initialized) + o.o_val.v_i = voc_initVOClient (envget("vo_runid")); + else + o.o_val.v_i = 0; + pushop (&o); + + VOClient_initialized = 1; + + return (OK); +} + + +/* Validate an object in the VO Client. + */ +int +cl_validObj () +{ + struct operand o; + + int obj = voGetIntArg (); + + o.o_type = OT_INT; + if (! VOClient_initialized) { + /* Client not initialized, obviously not valid. + */ + o.o_val.v_i = 0; + } else + o.o_val.v_i = voc_validateObject (obj); + pushop (&o); + + return (OK); +} + + +/* Verify the VOClient is ready. + */ +int +cl_vocReady () +{ + struct operand o; + + o.o_type = OT_BOOL; + if (! VOClient_initialized) { + /* Client not initialized, obviously not valid. + */ + o.o_val.v_i = 0; + } else + o.o_val.v_i = voc_ready (); + pushop (&o); + + return (OK); +} + + +/* Call a Cone service. + */ +int +cl_dalConeSvc () +{ + char *url; + double sr, ra, dec; + DAL cone; + Query query; + QResponse result = (QResponse) ERR; + struct operand o; + + + /* Initialize the VO Client if it isn't already running. */ + if (! VOClient_initialized) { + cl_initVOClient (NULL); + o = popop (); /* pop status posted by initVOClient */ + } + + /* Args are on the stack in reverse order, pop 'em now. */ + sr = voGetDblArg (); + dec = voGetDblArg (); + ra = voGetDblArg (); + url = voGetStrArg (); + + /* Open a connection to the url, form a query and execute it. + */ + cone = voc_openConeConnection (url); + query = voc_getConeQuery (cone, ra, dec, sr); + result = voc_executeQuery (query); + + o.o_type = OT_INT; /* push result on stack */ + o.o_val.v_i = result; + pushop (&o); + + if (debug) + printf ("dalConeSvc=%d: url='%s'\n\tra=%g dec=%g sr=%g\n", + result, url, ra, dec, sr); + + if (url) free ((char *) url); + + return (OK); +} + + +/* Call a Siap service. + */ +int +cl_dalSiapSvc (nargs) +int nargs; +{ + char *fmt, *url; + double rasz, decsz, ra, dec; + DAL siap; + Query query; + QResponse result; + struct operand o; + + + /* Initialize the VO Client if it isn't already running. */ + if (! VOClient_initialized) { + cl_initVOClient (NULL); + o = popop (); /* pop status posted by initVOClient */ + } + + /* Args are on the stack in reverse order, pop 'em now. */ + if (nargs > 5) + fmt = voGetStrArg (); + else + fmt = "image/fits"; + if (nargs > 4) { + decsz = voGetDblArg (); + rasz = voGetDblArg (); + } else if (nargs == 4) { + rasz = decsz = voGetDblArg (); + } + dec = voGetDblArg (); + ra = voGetDblArg (); + url = voGetStrArg (); + + /* Open a connection to the url, form a query and execute it. + */ + if (url && url[0]) { + siap = voc_openSiapConnection (url); + query = voc_getSiapQuery (siap, ra, dec, rasz, decsz, fmt); + + result = voc_executeQuery (query); + } else + cl_error (E_UERR, "Invalid or NULL service URL specified."); + + if (debug) + printf ("dalSiapSvc: siap=%d query=%d result=%d\n", + siap, query, result); + + o.o_type = OT_INT; + o.o_val.v_i = result; + pushop (&o); + + if (debug) + printf ("dalSiapSvc=%d: url='%s'\n\tra=%g dec=%g sz=%g/%g fmt=%s\n", + result, url, ra, dec, rasz, decsz, fmt); + + if (url) free ((char *) url); + if (fmt && nargs > 5) free ((char *) fmt); + + return ( (result ? OK : ERR) ); +} + + +/* Get a count of the number of return records. + */ +int +cl_dalRecordCount () +{ + QResponse qres; + int count = -1; + int stat = OK; + struct operand o; + + + qres = (QResponse) voGetIntArg (); + + if (qres > 0) + count = voc_getRecordCount (qres); + else + stat = ERR; + + o.o_type = OT_INT; + o.o_val.v_i = count; + pushop (&o); + + return (stat); +} + + +/* Get the record handle. + */ +int +cl_dalGetRecord () +{ + QRecord rec; + QResponse qres; + int stat, count, recnum = -1; + struct operand o; + + recnum = voGetIntArg (); + qres = (QResponse) voGetIntArg (); + + if (voc_validateObject (qres)) { + /* Do the bounds checking here so we can return a sensible error. + */ + count = voc_getRecordCount (qres); + if (recnum < 0 || recnum > (count-1)) + cl_error (E_UERR, "dalGetRecord: index out-of-bounds\n"); + else + rec = voc_getRecord (qres, recnum); + } else + cl_error (E_UERR, "dalGetRecord: invalid `qres' argument\n"); + + o.o_type = OT_INT; + o.o_val.v_i = (int) rec; + pushop (&o); + + return (stat); +} + + +/* Download a dataset referred to by a URL. + */ +int +cl_dalGetData () +{ + QRecord rec; + QResponse qres; + QRAttribute attr; + char *fname, *acref, fbuf[SZ_FNAME]; + int recnum, count = -1; + int stat = OK; + struct operand o; + + + bzero (fbuf, SZ_FNAME); + + fname = voGetStrArg (); + recnum = voGetIntArg (); + qres = (QResponse) voGetIntArg (); + + if (voc_validateObject (qres)) { + rec = voc_getRecord (qres, recnum); + if (voc_validateObject (rec)) { + attr = voc_getAttribute (rec, "AccessReference"); + if (voc_validateObject (attr)) { + acref = voc_stringValue (attr); + stat = voc_getDataset (rec, acref, fname); + } else + cl_error (E_UERR, "getData: invalid `attr' argument\n"); + } else + cl_error (E_UERR, "getData: invalid `rec' argument\n"); + } else + cl_error (E_UERR, "getData: invalid `qres' argument\n"); + + o.o_type = OT_STRING; + strcpy (fbuf, fname); + o.o_val.v_s = fbuf; + pushop (&o); + + if (fname) free ((char *) fname); + if (acref) voc_freePointer( ((char *) acref) ); + return (stat); +} + + +/* Get a string-valued attribute from a DAL response table. + */ +int +cl_dalGetStr () +{ + QRecord rec; + QResponse qres; + QRAttribute attr; + char *attrname, *aval, sbuf[SZ_LINE]; + int recnum, stat = ERR; + struct operand o; + + + recnum = voGetIntArg (); + attrname = voGetStrArg (); + qres = (QResponse) voGetIntArg (); + + bzero (sbuf, SZ_LINE); + if (voc_validateObject (qres)) { + rec = voc_getRecord (qres, recnum); + if (voc_validateObject (rec)) { + attr = voc_getAttribute (rec, attrname); + if (voc_validateObject (attr)) { + if ( (aval = voc_stringValue (attr)) ) { + strcpy (sbuf, aval); + voc_freePointer( ((char *) aval) ); + stat = OK; + } + } + } + } + + o.o_type = OT_STRING; + o.o_val.v_s = sbuf; + pushop (&o); + + if (attrname) free ((char *) attrname); + return (stat); +} + + +/* Get an integer-valued attribute from a DAL response table. + */ +int +cl_dalGetInt () +{ + QRecord rec; + QResponse qres; + QRAttribute attr; + char *attrname; + int ival = INDEFI, recnum, stat = OK; + struct operand o; + + + recnum = voGetIntArg (); + attrname = voGetStrArg (); + qres = (QResponse) voGetIntArg (); + + if (voc_validateObject (qres)) { + rec = voc_getRecord (qres, recnum); + if (voc_validateObject (rec)) { + attr = voc_getAttribute (rec, attrname); + if (voc_validateObject (attr)) + ival = voc_intValue (attr); + } + } + + o.o_type = OT_INT; + o.o_val.v_i = ival; + pushop (&o); + + if (attrname) free ((char *) attrname); + return (stat); +} + + +/* Get an integer-valued attribute from a DAL response table. +*/ +int +cl_dalGetDbl () +{ + QRecord rec; + QResponse qres; + QRAttribute attr; + char *attrname; + int recnum, stat = OK; + double dval = INDEFD; + struct operand o; + + + recnum = voGetIntArg (); + attrname = voGetStrArg (); + qres = (QResponse) voGetIntArg (); + + if (voc_validateObject (qres)) { + rec = voc_getRecord (qres, recnum); + if (voc_validateObject (rec)) { + attr = voc_getAttribute (rec, attrname); + if (voc_validateObject (attr)) + dval = voc_floatValue (attr); + } + } + + o.o_type = OT_REAL; + o.o_val.v_r = dval; + pushop (&o); + + if (attrname) free ((char *) attrname); + return (stat); +} + + + +/* Return a count of the number of attributes (i.e. columns) in a record (row). + */ +int +cl_dalAttrCount () +{ + QRecord rec; + int count = -1; + int stat = OK; + struct operand o; + + + rec = (QRecord) voGetIntArg (); + + if (voc_validateObject (rec)) + count = voc_getAttrCount (rec); + else { + cl_error (E_UERR, "dalAttrCount: invalid `rec' argument\n"); + stat = ERR; + } + + o.o_type = OT_INT; + o.o_val.v_i = count; + pushop (&o); + + return (stat); +} + + +/* Get the name of the attribute (i.e. column) given the index. + */ +int +cl_dalAttrName () +{ + QRecord rec; + int index, count = -1; + int stat = OK; + struct operand o; + + + index = voGetIntArg (); + rec = (QRecord) voGetIntArg (); + + if (voc_validateObject (rec)) { + char *attr_list = voc_getAttrList (rec); + char *ip = attr_list; + + } else { + cl_error (E_UERR, "dalAttrCount: invalid `rec' argument\n"); + stat = ERR; + } + + o.o_type = OT_STRING; + o.o_val.v_s = "foo"; + pushop (&o); + + return (stat); +} + + +/* Get the requested attribute as an integer. + */ +int +cl_dalStrAttr () +{ + QRAttribute attr; + QRecord rec; + char *name; + int stat = OK; + struct operand o; + + + name = voGetStrArg (); + rec = (QRecord) voGetIntArg (); + + if (voc_validateObject (rec)) + attr = voc_getAttribute (rec, name); + else { + cl_error (E_UERR, "dalAttrCount: invalid `rec' argument\n"); + stat = ERR; + } + + o.o_type = OT_STRING; + o.o_val.v_s = voc_stringValue (attr); + pushop (&o); + + if (name) free ((char *) name); + + return (stat); +} + + +/* Get the requested attribute as an integer. + */ +int +cl_dalFloatAttr () +{ + QRAttribute attr; + QRecord rec; + char *name; + int stat = OK; + struct operand o; + + + name = voGetStrArg (); + rec = (QRecord) voGetIntArg (); + + if (voc_validateObject (rec)) + attr = voc_getAttribute (rec, name); + else { + cl_error (E_UERR, "dalAttrCount: invalid `rec' argument\n"); + stat = ERR; + } + + o.o_type = OT_REAL; + o.o_val.v_r = voc_floatValue (attr); + pushop (&o); + + if (name) free ((char *) name); + + return (stat); +} + + +/* Get the requested attribute as an integer. + */ +int +cl_dalIntAttr () +{ + QRAttribute attr; + QRecord rec; + char *name; + int stat = OK; + struct operand o; + + + name = voGetStrArg (); + rec = (QRecord) voGetIntArg (); + + if (voc_validateObject (rec)) + attr = voc_getAttribute (rec, name); + else { + cl_error (E_UERR, "dalAttrCount: invalid `rec' argument\n"); + stat = ERR; + } + + o.o_type = OT_INT; + o.o_val.v_s = voc_intValue (attr); + pushop (&o); + + if (name) free ((char *) name); + + return (stat); +} + + +/* Download a dataset referred to by a URL. + */ +int +cl_dalDataset (nargs) +int nargs; +{ + QRecord rec = (QRecord) NULL; + char *fname, *acref, *res, *val, fbuf[SZ_FNAME]; + int count = -1, stat = OK, urlsize = (2 * 1024 * 1024); + struct operand o; + + + bzero (fbuf, SZ_FNAME); + + switch (nargs) { + case 3: + fname = voGetStrArg (); + acref = voGetStrArg (); + rec = (QRecord) voGetIntArg (); + break; + case 2: + fname = voGetStrArg (); + acref = voGetStrArg (); + break; + case 1: + fname = "uparm$url_file"; + acref = voGetStrArg (); + break; + default: + cl_error (E_UERR, "dalDataset: invalid argument list\n"); + break; + } + + if (acref && acref[0]) { + if (rec && voc_validateObject (rec)) { + stat = voc_getDataset (rec, acref, fname); + } else { + int fd, nb, nbytes; + + res = voc_getRawURL (acref, &nbytes); + if (res == NULL) + cl_error (E_UERR, "getDataset: cannot access URL\n"); + + if (c_access (fname, 0, 0)) + c_delete (fname); + if ((fd = c_open (fname, NEW_FILE, BINARY_FILE)) != ERR) { + nb = c_write (fd, res, nbytes); + if (nb != nbytes) + printf ("Warning: short file write\n"); + c_close (fd); + } else { + cl_error (E_UERR, "dalDataset: cannot open output file\n"); + } + voc_freePointer ((char *) res); + } + } else { + cl_error (E_UERR, "dalDataset: invalid `acref' argument\n"); + stat = ERR; + } + + o.o_type = OT_STRING; + strcpy (fbuf, fname); + o.o_val.v_s = fbuf; + pushop (&o); + + if (acref) free ((char *) acref); + if (nargs > 1 && fname) free ((char *) fname); + + return (stat); +} + + +/* Scan attribute values to local parameters. Returns number of values + * read (always the number requested, empty fields filled w/ INDEF) or EOF. + */ +int +cl_dalAttrScan (nargs) +int nargs; +{ + QRecord rec; + QRAttribute attr; + char *alist, *val = NULL; + char *ip, *op, *attr_list[MAX_ATTRS]; + int i, nattrs=0, stat = OK; + struct operand o; + + + bzero (attr_list, MAX_ATTRS); /* clear arrays */ + + alist = voGetStrArg (); /* get the attribute list */ + for (nattrs=0, ip=alist; *ip && nattrs < MAX_ATTRS; ) { + attr_list[nattrs++] = op = ip; + while (*ip && *ip != ',') + ip++; + if (*ip == ',') + *ip++ = '\0'; + else + break; + } +/* +for(i=0; i < nattrs; i++) + printf ("%d: attr_list='%s'\n", i, attr_list[i]); +*/ + + rec = (QRecord) voGetIntArg (); + + if (attr) { + for (i = (nattrs-1); i > 0; i--) { + attr = voc_getAttribute (rec, attr_list[i]); + val = voc_getStringAttr (rec, attr); +/* +printf ("%d: attr='%s' => '%s'\n", i, attr_list[i], val); +*/ + } + } else + stat = ERR; + + o.o_type = OT_STRING; + o.o_val.v_i = val; + pushop (&o); + + if (alist) free ((char *) alist); + + return (stat); +} + + + + +/* Do a Registry search using keyword terms and/or sql predicates. We + * return a resource pointer to the records that can be queried using the + * regValue() builtin for specific items. + * + * Usage: + * resource = regSearch (sql) + * resource = regSearch (keywords, orValues) + * resource = regSearch (sql, keywords, orValues) + */ +int +cl_regSearch (nargs) +int nargs; +{ + RegResult res; + char *sql = NULL, *keyw = NULL; + int stat = OK, orValues = 0; + struct operand o; + + + + /* Initialize the VO Client if it isn't already running. */ + if (! VOClient_initialized) { + cl_initVOClient (NULL); + o = popop (); /* pop status posted by initVOClient */ + } + + /* Get the calling arguments in reverse order from the stack. + */ + switch (nargs) { + case 3: + orValues = voGetIntArg (); + keyw = voGetStrArg (); + sql = voGetStrArg (); + break; + case 2: + orValues = voGetIntArg (); + keyw = voGetStrArg (); + break; + case 1: + sql = voGetStrArg (); + break; + default: + cl_error (E_UERR, "regSearch: invalid number of arguments\n"); + return (ERR); + } + + + /* Do the registry query. */ + res = voc_regSearch (sql, keyw, orValues); + + o.o_type = OT_INT; + o.o_val.v_i = res; + pushop (&o); + + /* Clean up and return. + */ + if (keyw) free ((char *) keyw); + if (sql) free ((char *) sql); + + return (stat); +} + + +/* Do a Registry search and limit results to a specific service type. + * Search term may be either a keyword list or sql predicate. + */ +int +cl_regSvcSearch () +{ + RegResult res; + int count = -1; + char *svc, *term, *bpass, *clevel; + int stat = OK, orValues = 0; + struct operand o; + + + /* Initialize the VO Client if it isn't already running. */ + if (! VOClient_initialized) { + cl_initVOClient (NULL); + o = popop (); /* pop status posted by initVOClient */ + } + + orValues = voGetIntArg (); + clevel = voGetStrArg (); + bpass = voGetStrArg (); + svc = voGetStrArg (); + term = voGetStrArg (); + + + /* Do the registry query. */ + res = voc_regSearchByService (svc, term, orValues); + + + o.o_type = OT_INT; + o.o_val.v_i = res; + pushop (&o); + + /* Clean up and return. + */ + if (term) free ((char *) term); + if (svc) free ((char *) svc); + + return (stat); +} + + +/* Return a count of the number of attributes (i.e. columns) in a record (row). + */ +int +cl_regResultCount () +{ + RegResult res; + int count = -1; + int stat = OK; + struct operand o; + + res = (RegResult) voGetIntArg (); + + if (res) + count = voc_resGetCount (res); + else + stat = ERR; + + o.o_type = OT_INT; + o.o_val.v_i = count; + pushop (&o); + + return (stat); +} + + +/* Set a bandpass constraint on a query. + */ +int +cl_regSetBandpass () +{ + char *bpass = NULL; + RegQuery query = 0; + int stat = OK; + struct operand o; + + bpass = voGetStrArg (); + query = (RegQuery) voGetIntArg (); + + if (query) + voc_regConstWaveband (query, bpass); + else + stat = ERR; + + o.o_type = OT_INT; + o.o_val.v_i = stat; + pushop (&o); + + return (stat); +} + + +/* Set a ServiceType constraint on a query. + */ +int +cl_regSetService () +{ + char *svctype = NULL; + RegQuery query = 0; + int stat = OK; + struct operand o; + + svctype = voGetStrArg (); + query = (RegQuery) voGetIntArg (); + + if (query) + voc_regConstSvcType (query, svctype); + else + stat = ERR; + + o.o_type = OT_INT; + o.o_val.v_i = stat; + pushop (&o); + + return (stat); +} + + +/* Set a ContentLevel constraint on a query. + */ +int +cl_regSetContent () /* FIXME - Not Yet Implemented */ +{ + struct operand o; + int stat = OK; + + o.o_type = OT_INT; + o.o_val.v_i = stat; + pushop (&o); + + return (stat); +} + + +/* Get the attribute value from the named resource query handle. + */ +int +cl_regValue (nargs) +int nargs; +{ + RegResult res; + int index = 0, stat = OK; + char *attr, *val, sbuf[SZ_RESBUF]; + struct operand o; + + + /* Get the arguments. Remember they're on the stack backwards. + */ + if (nargs > 2) + index = voGetIntArg (); + attr = voGetStrArg (); + res = (RegResult) voGetIntArg (); + + bzero (sbuf, SZ_RESBUF); + + if (res) + val = (char *) voc_resGetStr (res, attr, index); + else + stat = ERR; + + if (val && val[0]) + strcpy (sbuf, val); + + if (strlen (sbuf) > 255) + sbuf[255] = '\0'; + + o.o_type = OT_STRING; + o.o_val.v_s = sbuf; + pushop (&o); + + /* Clean up and return. + */ + if (attr) free ((char *) attr); + if (val) voc_freePointer ((char *) val); + + return (stat); +} + + +/* Resolve a (presumed) ShortName or Identifier string to one or more + * Registry resource attributes. By default we assume we are interested + * only in the ServiceURL, however optional arguments allow us to narrow + * the search to particular service types or individual records. Examples: + * + * 1) Find the ServiceURL for the GSC2.2 catalog + * + * cl> =regResolver ("GSC2.2") + * http://chart.stsci.edu/GSCVO/GSC22VO.jsp? + * cl> =nresolved() + * 2 # found more than one resource + * + * 2) Print the Title and ServiceType for each record found for USNO-B1: + * + * cl> print (regResolver ("USNO-B1","","ServiceType,Title",-1)) + * CONE USNO-B1 Catalogue + * SKYNODE USNO-B1 SkyNode from VizieR + * + * Note that in usage such as this we are still limited by the length + * of output permitted by the print() function (currently 32*SZ_LINE). + * + * 3) Get the ServiceURL for the USNO-B1 Skynode service: + * + * cl> =regResolver ("USNO-B1","skynode") + * http://cdsws.u-strasbg.fr/USNO-B1BasicSkyNode/services/BasicSkyNode + * + */ + +int +cl_regResolver (nargs) +int nargs; +{ + int i, j, nreturns=0, nattrs=0, comma = ',', stat = OK; + int exact=-1, recnum=0, istart, iend; + char *qterm=NULL, *attr=NULL, *type=NULL, *attr_val=NULL; + char *ip, *op, *attr_list[MAX_ATTRS]; + char qstring[SZ_LINE], svcstr[SZ_LINE]; + char attr_str[SZ_LINE], sbuf[SZ_RESBUF]; + struct operand o; + RegQuery query = 0; + RegResult resource = 0; + + + bzero (qstring, SZ_LINE); + bzero (svcstr, SZ_LINE); + bzero (sbuf, SZ_RESBUF); + + strcpy (attr_str, DEF_RESATTR); + + + /* Initialize the VO Client if it isn't already running. */ + if (! VOClient_initialized) { + cl_initVOClient (NULL); + o = popop (); /* pop status posted by initVOClient */ + } + + /* Parse any remaining (optional) arguments. Remember that the args are + * on the stack in the reverse order! The 1st arg is required and will + * be either an ivo: identifier or is presumed to be the ShortName. + */ + attr_list[0] = "ShortName"; + attr_list[1] = "Identifier"; + attr_list[2] = "ServiceUrl"; + nattrs = 3; + + switch (nargs) { + case 4: + recnum = voGetIntArg (); + /* fall thru */ + + case 3: + attr = voGetStrArg (); + if (attr && attr[0]) { + for (nattrs=2, ip=attr; *ip && nattrs < MAX_ATTRS; ) { + attr_list[nattrs++] = op = ip; + while (*ip && *ip != ',') + ip++; + if (*ip == ',') + *ip++ = '\0'; + else + break; + } + } + /* fall thru */ + + case 2: + type = voGetStrArg (); + if (type && type[0]) { + /* Aliases for service type include: + * + * Cone -> catalog, table + * SIAP -> image, archive + * SSAP -> spectrum + * + */ + if (strcmp(type,"catalog") == 0 || strcmp(type,"table") == 0) + sprintf (svcstr, "ServiceType like '%%cone%%'"); + else if (strcmp(type,"image") == 0 || strcmp(type,"archive") == 0) + sprintf (svcstr, "ServiceType like '%%siap%%'"); + else if (strcmp(type,"spectrum") == 0) + sprintf (svcstr, "ServiceType like '%%ssap%%'"); + else + sprintf (svcstr, "ServiceType like '%%%s%%'", type); + } + /* fall thru */ + + case 1: + qterm = voGetStrArg (); + + if (strncmp (qterm, "ivo://", 6) == 0) { /* remove svc num. */ + char *ip = qterm; + for (ip=qterm; *ip && *ip != '#'; ip++) + ; + *ip = '\0'; + } + sprintf (qstring, + "(Identifier like '%%%s%%') OR (ShortName like '%%%s%%')", + qterm, qterm); + break; + + default: + cl_error (E_UERR, "regResolver: invalid number of arguments\n"); + return (ERR); + } + + + + /* Do the registry query. + */ + query = voc_regQuery (qstring, 0); + if (type && type[0]) + voc_regAddSearchTerm (query, svcstr, 0); + + if (debug) { + printf ("regResolver: qterm='%s' type='%s' attr='%s' recnum=%d\n", + (qterm ? qterm : "null"), + (type ? type : "null"), + (attr ? attr : "null"), recnum); + printf ("query string:\n\n%s\n\n", voc_regGetQueryString (query)); + } + + /* Execute the query. + */ + resource = voc_regExecute (query); + + /* Save the number of resolved resources and get the requested attribute + * (or the default service URL). + */ + if ((reg_nresolved = voc_resGetCount (resource)) > 0) { + nreturns = (recnum >= 0 ? 1 : reg_nresolved); + + exact = 0; + if (recnum == 0 && reg_nresolved > 1) { + /* We didn't specify a record number but have more than one + * result. Look for an exact match in the ShortName which was + * a hidden part of the query. + */ + for (i=0; i < reg_nresolved; i++) { + attr_val = voc_resGetStr (resource, attr_list[0], i); + if (strncasecmp (qterm, attr_val, strlen(attr_val)) == 0) { + exact = i; + break; + } + attr_val = voc_resGetStr (resource, attr_list[1], i); + if (strncasecmp (qterm, attr_val, strlen(attr_val)) == 0) { + exact = i; + break; + } + } + } + + if (exact >= 0 && recnum < 1 && nreturns == 1) { + istart = exact; + iend = exact + 1; + } else { + istart = 0; + iend = nreturns; + } + + /* For a negative recnum we list the attr for all records. + */ + for (i=istart; i < iend; i++) { + for (j=2; j < nattrs; j++) { + attr_val = voc_resGetStr (resource, attr_list[j], i); + + if (attr_val) { + strcat (sbuf, attr_val); + if (j < (nattrs-1)) + strcat (sbuf, "\t"); + voc_freePointer ((char *) attr_val); + } else + strcat (sbuf, "INDEF\t"); + } + if (nreturns > 1 && i < (reg_nresolved-1)) + strcat (sbuf, "\n"); + } + + o.o_type = OT_STRING; + o.o_val.v_s = sbuf; + attr_val = (char *) NULL; + + } else { + for (j=0; j < nattrs; j++) { + strcpy (sbuf, "INDEF"); + if (j < (nattrs-1)) + strcat (sbuf, "\t"); + } + + o.o_type = OT_STRING; + o.o_val.v_s = sbuf; + } + + /* Push the result operand on the stack. + */ + pushop (&o); + + + /* Clean up and return. + */ + if (qterm) free ((char *) qterm); + if (type) free ((char *) type); + if (attr) free ((char *) attr); + + return (stat); +} + + +/* Get a count of the number of return records. + */ +int +cl_regNResolved () +{ + struct operand o; + + o.o_type = OT_INT; + o.o_val.v_i = reg_nresolved; + pushop (&o); + + return (OK); +} + + +/* ======================================================== + * + * End of VO Client functions. + * What follows is their support code. + * + * ========================================================*/ + + +int +voGetIntArg () +{ + struct operand o; + int ival; + + + o = popop(); + + switch (o.o_type & OT_BASIC) { + case OT_BOOL: + case OT_INT: ival = (int) o.o_val.v_i; break; + case OT_REAL: ival = (int) o.o_val.v_r; break; + case OT_STRING: ival = (int) atoi (o.o_val.v_s); break; + default: + cl_error (E_UERR, "printf: bad operand type\n"); + } + + if (debug) + printf ("ival arg = '%d'\n", ival); + + return (ival); +} + + +double +voGetDblArg () +{ + struct operand o; + double dval; + + + o = popop(); + + switch (o.o_type & OT_BASIC) { + case OT_BOOL: + case OT_INT: dval = (double) o.o_val.v_i; break; + case OT_REAL: dval = (double) o.o_val.v_r; break; + case OT_STRING: dval = (double) atof (o.o_val.v_s); break; + default: + cl_error (E_UERR, "printf: bad operand type\n"); + } + + if (debug) + printf ("dval arg = '%g'\n", dval); + + return (dval); +} + + +/* Note: caller must free the pointer! + */ +char * +voGetStrArg () +{ + struct operand o; + char *str = NULL; + + o = popop(); + + switch (o.o_type & OT_BASIC) { + case OT_BOOL: + case OT_INT: + str = calloc (1, SZ_FNAME); + sprintf (str, "%d", o.o_val.v_i); + break; + case OT_REAL: + str = calloc (1, SZ_FNAME); + sprintf (str, "%f", o.o_val.v_r); + break; + case OT_STRING: + str = calloc (1, strlen(o.o_val.v_s)+1); + sprintf (str, "%s", o.o_val.v_s); + break; + default: + cl_error (E_UERR, "printf: bad operand type\n"); + } + + if (debug) + printf ("str arg = '%s'\n", str); + + return (str); +} + |