00001
00018 #include <stdlib.h>
00019 #include <stdio.h>
00020 #include <string.h>
00021 #include <math.h>
00022 #include <signal.h>
00023 #include <conio.h>
00024 #include <stdarg.h>
00025 #include <ctype.h>
00026 #include "mex.h"
00027
00028 #define _MAIN_C
00029
00030 #include "globals.h"
00031 #include "module.h"
00032 #include "load.h"
00033 #include "exec.h"
00034 #include "legal.h"
00035 #include "output.h"
00036 #include "object.h"
00037 #include "convert.h"
00038 #include "find.h"
00039
00040 #define MAXNAME 256
00041 #define MATLABDATETIME(X) ((double)(X)/TS_SECOND/86400 + 719529)
00042
00043 typedef enum {MH_GLOBAL=0x19c3, MH_OBJECT=0x82a3, MH_CLASS=0x5d37, MH_MODULE=0xb40f} MEXHANDLETYPE;
00044
00045 static mxArray *make_handle(MEXHANDLETYPE type, void *ptr)
00046 {
00047 mxArray *handle = mxCreateNumericMatrix(1,2,mxINT64_CLASS,mxREAL);
00048 unsigned int64 *data = (unsigned int64*)mxGetPr(handle);
00049 data[0] = type;
00050 data[1] = (unsigned int64)ptr;
00051 return handle;
00052 }
00053
00054 static char *make_fieldname(char *str)
00055 {
00056 char *p;
00057 for (p=str; *p!='\0'; p++)
00058 if (!isalnum(*p))
00059 *p = '_';
00060 return str;
00061 }
00062
00063 static OBJECT *find_object(mxArray *handle)
00064 {
00065 unsigned int64 *data = (unsigned int64*)mxGetPr(handle);
00066 return data[0]==MH_OBJECT ? (OBJECT*)data[1] : NULL;
00067 }
00068
00069 static GLOBALVAR *find_global(mxArray *handle)
00070 {
00071 unsigned int64 *data = (unsigned int64*)mxGetPr(handle);
00072 return data[0]==MH_GLOBAL ? (GLOBALVAR*)data[1] : NULL;
00073 }
00074
00075 static CLASS *find_class(mxArray *handle)
00076 {
00077 unsigned int64 *data = (unsigned int64*)mxGetPr(handle);
00078 return data[0]==MH_CLASS ? (CLASS*)data[1] : NULL;
00079 }
00080
00081 static MODULE *find_module(mxArray *handle)
00082 {
00083 unsigned int64 *data = (unsigned int64*)mxGetPr(handle);
00084 return data[0]==MH_MODULE ? (MODULE*)data[1] : NULL;
00085 }
00086
00087 static mxArray *get_object_data(OBJECT *obj)
00088 {
00089 mxArray *plhs[1];
00090
00091
00092 #define ERROR "(error)"
00093 #define NONE "(none)"
00094 char *fnames[1024] = {"id","class","parent","rank","clock","latitude","longitude","in_svc","out_svc","flags",NULL};
00095 int nFields = 0;
00096 int nData = 0;
00097 char value[1024];
00098 PROPERTY *prop;
00099 mxArray *pId = mxCreateString(convert_from_object(value,sizeof(value),&obj,NULL)?value:ERROR);
00100 mxArray *pClass = mxCreateString(obj->oclass->name);
00101 mxArray *pParent = mxCreateString(obj->parent!=NULL&&convert_from_object(value,sizeof(value),&(obj->parent),NULL)?value:NONE);
00102 mxArray *pRank = mxCreateNumericMatrix(1,1,mxUINT32_CLASS,mxREAL);
00103 mxArray *pClock = mxCreateString(convert_from_timestamp(obj->clock,value,sizeof(value))?value:ERROR);
00104 mxArray *pLatitude = mxCreateString(convert_from_latitude(obj->latitude,value,sizeof(value))?value:NONE);
00105 mxArray *pLongitude = mxCreateString(convert_from_longitude(obj->longitude,value,sizeof(value))?value:NONE);
00106 mxArray *pInSvc = mxCreateString(convert_from_timestamp(obj->in_svc,value,sizeof(value))?value:ERROR);
00107 mxArray *pOutSvc = mxCreateString(convert_from_timestamp(obj->out_svc,value,sizeof(value))?value:ERROR);
00108 mxArray *pFlags = mxCreateString(convert_from_set(value,sizeof(value),(void*)&obj->flags,object_flag_property())?value:ERROR);
00109
00110 *(OBJECTRANK*)mxGetPr(pRank) = obj->rank;
00111
00112
00113 while (fnames[nFields]!=NULL) nFields++;
00114
00115
00116 for (prop=class_get_first_property(obj->oclass); prop!=NULL; prop=class_get_next_property(prop))
00118 fnames[nFields+nData++] = make_fieldname(prop->name);
00119
00120
00121 plhs[0] = mxCreateStructMatrix(1,1,nFields+nData,fnames);
00122
00123
00124 mxSetFieldByNumber(plhs[0],0,0,pId);
00125 mxSetFieldByNumber(plhs[0],0,1,pClass);
00126 mxSetFieldByNumber(plhs[0],0,2,pParent);
00127 mxSetFieldByNumber(plhs[0],0,3,pRank);
00128 mxSetFieldByNumber(plhs[0],0,4,pClock);
00129 mxSetFieldByNumber(plhs[0],0,5,pLatitude);
00130 mxSetFieldByNumber(plhs[0],0,6,pLongitude);
00131 mxSetFieldByNumber(plhs[0],0,7,pInSvc);
00132 mxSetFieldByNumber(plhs[0],0,8,pOutSvc);
00133 mxSetFieldByNumber(plhs[0],0,9,pFlags);
00134
00135
00136 for (prop=class_get_first_property(obj->oclass); prop!=NULL; nFields++,prop=class_get_next_property(prop))
00137 {
00138 mxArray *pValue;
00139 if (prop->ptype==PT_double)
00140 {
00141 pValue = mxCreateDoubleMatrix(1,1,mxREAL);
00142 *(double*)mxGetPr(pValue) = *object_get_double(obj,prop);
00143 }
00144 else if (prop->ptype==PT_int32)
00145 {
00146 pValue = mxCreateDoubleMatrix(1,1,mxREAL);
00147 *(double*)mxGetPr(pValue) = (double)*object_get_int32(obj,prop);
00148 }
00149 else if (prop->ptype==PT_complex)
00150 {
00151 complex *pData = object_get_complex(obj,prop);
00152 pValue = mxCreateDoubleMatrix(1,1,mxCOMPLEX);
00153 *(double*)mxGetPr(pValue) = pData->r;
00154 *(double*)mxGetPi(pValue) = pData->i;
00155 }
00156 else
00157 {
00158 pValue = mxCreateString(object_get_value_by_name(obj,prop->name,value,sizeof(value))?value:ERROR);
00159 }
00160 mxSetFieldByNumber(plhs[0],0,nFields,pValue);
00161 }
00162 return plhs[0];
00163 }
00164
00165 static void set_object_data(const mxArray *data)
00166 {
00167 OBJECT *obj;
00168 mxArray *pId = mxGetField(data,0,"id");
00169 char id[256];
00170 if (pId==NULL)
00171 output_error("set_object_data(const mxArray *data={...}) did not find a required object id field");
00172 else if (mxGetString(pId,id,sizeof(id)))
00173 output_error("set_object_data(const mxArray *data={...}) couldn't read the object id field");
00174 else if ((obj=object_find_name(id))==NULL)
00175 output_error("set_object_data(const mxArray *data={id='%s',...}) couldn't find object id", id);
00176 else
00177 {
00178 int i;
00179 for (i=0; i<mxGetNumberOfFields(data); i++)
00180 {
00181 const char *name;
00182 const mxArray *pField = mxGetFieldByNumber(data,0,i);
00183 char value[4096];
00184 if ((name=mxGetFieldNameByNumber(data,i))==NULL)
00185 output_error("set_object_data(const mxArray *data={id='%s',...}) couldn't read the name of field %d", id, i);
00186 else if (strcmp(name,"id")==0 || strcmp(name,"class")==0)
00187 { }
00188 else if (pField==NULL)
00189 output_error("set_object_data(const mxArray *data={id='%s',...}) couldn't read the object field '%s' for object '%s'", id, name);
00190 else if (mxIsChar(pField) && mxGetString(pField,value,sizeof(value)))
00191 output_error("set_object_data(const mxArray *data={id='%s',...}) couldn't read the string value '%s' from field '%s'", id, value, name);
00192 else if (mxIsDouble(pField) && sprintf(value,"%lg",*(double*)mxGetPr(pField))<1)
00193 output_error("set_object_data(const mxArray *data={id='%s',...}) couldn't read the double value '%lg' from field '%s'", id, *(double*)mxGetPr(pField), name);
00194 else if (mxIsComplex(pField) && sprintf(value,"%lg%+lgi",*(double*)mxGetPr(pField),*(double*)mxGetPi(pField))<1)
00195 output_error("set_object_data(const mxArray *data={id='%s',...}) couldn't read the complex value '%lg%+lgi' from field '%s'", id, *(double*)mxGetPr(pField), *(double*)mxGetPi(pField), name);
00196 else if (mxIsUint32(pField) && sprintf(value,"%lu",*(unsigned int*)mxGetPr(pField))<1)
00197 output_error("set_object_data(const mxArray *data={id='%s',...}) couldn't read the uint32 value '%lu' from field '%s'", id, *(unsigned int*)mxGetPr(pField), name);
00198 else if (strcmp(value,ERROR)==0)
00199 output_error("set_object_data(const mxArray *data={id='%s',...}) couldn't use error value '%s'", id, value);
00200 else if (strcmp(value,NONE)==0 && strcpy(value,"")==NULL)
00201 output_error("set_object_data(const mxArray *data={id='%s',...}) couldn't clear empty value '%s'", id, value);
00202 else if (!object_set_value_by_name(obj,name,value))
00203 output_error("set_object_data(const mxArray *data={id='%s',...}) couldn't read the value '%s' into property '%s'", id, value, name);
00204 }
00205 }
00206 }
00207
00208 static int cmex_printerr(char *format, ...)
00209 {
00210 int count=0;
00211 static char buffer[1024];
00212 va_list ptr;
00213 va_start(ptr,format);
00214 count += vsprintf(buffer,format,ptr);
00215 va_end(ptr);
00216 if (strncmp(buffer,"ERROR",5)==0 || strncmp(buffer,"FATAL",5)==0)
00217 mexErrMsgTxt(buffer);
00218 else if (strncmp(buffer,"WARN",4)==0)
00219 mexWarnMsgTxt(buffer);
00220 else
00221 mexPrintf("%s",buffer);
00222 return count;
00223 }
00224
00225 void cmex_object_list(int nlhs, mxArray *plhs[],
00226 int nrhs, const mxArray *prhs[] )
00227 {
00228 OBJECT *obj;
00229 char criteria[1024]="(undefined)";
00230 FINDPGM *search = NULL;
00231 char *fields[] = {"name","class","parent","flags","location","service","rank","clock","handle"};
00232 FINDLIST *list = NULL;
00233 if (nrhs>0 && mxGetString(prhs[0],criteria,sizeof(criteria))!=0)
00234 output_error("gl('list',type='object'): unable to read search criteria (arg 2)");
00235 else if (nrhs>0 && (search=find_mkpgm(criteria))==NULL)
00236 output_error("gl('list',type='object'): unable to run search '%s'",criteria);
00237 else if (search==NULL && (list=find_objects(NULL,NULL))==NULL)
00238 output_error("gl('list',type='object'): unable to obtain default list");
00239 else if (list==NULL && (list=find_runpgm(NULL,search))==NULL)
00240 output_error("gl('list',type='object'): unable search failed");
00241 else if ((plhs[0] = mxCreateStructMatrix(list->hit_count,1,sizeof(fields)/sizeof(fields[0]),fields))==NULL)
00242 output_error("gl('list',type='object'): unable to allocate memory for result list");
00243 else
00244 {
00245 unsigned int n;
00246 for (n=0, obj=find_first(list); obj!=NULL; n++, obj=find_next(list,obj))
00247 {
00248 char tmp[1024];
00249 mxArray *data;
00250 double *pDouble;
00251 unsigned int *pInt;
00252 mxSetFieldByNumber(plhs[0], n, 0, mxCreateString(object_name(obj)));
00253 mxSetFieldByNumber(plhs[0], n, 1, mxCreateString(obj->oclass->name));
00254 mxSetFieldByNumber(plhs[0], n, 2, mxCreateString(obj->parent?object_name(obj->parent):NONE));
00255 mxSetFieldByNumber(plhs[0], n, 3, mxCreateString(convert_from_set(tmp,sizeof(tmp),&(obj->flags),object_flag_property())?tmp:ERROR));
00256 pDouble = mxGetPr(data=mxCreateDoubleMatrix(1,2,mxREAL)); pDouble[0] = obj->longitude; pDouble[1] = obj->latitude;
00257 mxSetFieldByNumber(plhs[0], n, 4, data);
00258 pDouble = mxGetPr(data=mxCreateDoubleMatrix(1,2,mxREAL)); pDouble[0] = (double)obj->in_svc/TS_SECOND; pDouble[1] = (double)obj->out_svc/TS_SECOND;
00259 mxSetFieldByNumber(plhs[0], n, 5, data);
00260 pInt = (unsigned int*)mxGetPr(data=mxCreateNumericMatrix(1,1,mxINT32_CLASS,mxREAL)); pInt[0] = obj->rank;
00261 mxSetFieldByNumber(plhs[0], n, 6, data);
00262 pDouble = mxGetPr(data=mxCreateDoubleMatrix(1,1,mxREAL)); pDouble[0] = (double)obj->clock/TS_SECOND;
00263 mxSetFieldByNumber(plhs[0], n, 7, data);
00264 mxSetFieldByNumber(plhs[0], n, 8, make_handle(MH_OBJECT,obj));
00265 }
00266 }
00267 }
00268
00272 void cmex_list(int nlhs, mxArray *plhs[],
00273 int nrhs, const mxArray *prhs[] )
00274 {
00275 char type[32];
00276 if (nlhs>1)
00277 output_error("gl('list',type=...): returns only one value");
00278 else if (nlhs<1)
00279 return;
00280 else if (nrhs<1)
00281 output_error("gl('list',type=...): needs a type (arg 1)");
00282 else if (mxGetString(prhs[0],type,sizeof(type))==1)
00283 output_error("gl('list',type=...): type (arg 1) should be a string");
00284 else if (strcmp(type,"object")==0)
00285 cmex_object_list(nlhs,plhs,nrhs-1,prhs+1);
00286 else if (strcmp(type,"global")==0)
00287 output_error("gl('list',type='%s'): type (arg 1) not implemented",type);
00288 else if (strcmp(type,"class")==0)
00289 output_error("gl('list',type='%s'): type (arg 1) not implemented",type);
00290 else if (strcmp(type,"module")==0)
00291 output_error("gl('list',type='%s'): type (arg 1) not implemented",type);
00292 else
00293 output_error("gl('list',type='%s'): type (arg 1) not recognized",type);
00294
00295 return;
00296 }
00297
00301 void cmex_version(int nlhs, mxArray *plhs[],
00302 int nrhs, const mxArray *prhs[] )
00303 {
00304
00305 if (nlhs>0)
00306 {
00307 double *res = NULL;
00308 plhs[0] = mxCreateDoubleMatrix(1, 2, mxREAL);
00309 res = mxGetPr(plhs[0]);
00310 *res++ = global_version_major;
00311 *res++ = global_version_minor;
00312 }
00313 else
00314 legal_notice();
00315
00316 return;
00317 }
00318
00322 void cmex_global(int nlhs, mxArray *plhs[],
00323 int nrhs, const mxArray *prhs[] )
00324 {
00325 char name[256];
00326 size_t nDims;
00327 const mwSize *dim;
00328 if (nlhs!=0)
00329 output_error("global does not return a value");
00330 else if (nrhs!=2)
00331 output_error("global requires a name (arg 1) and an array (arg 2)");
00332 else if (!mxIsChar(prhs[0]) || mxGetString(prhs[0],name,sizeof(name))==1)
00333 output_error("global name (arg 1) must be a string");
00334 else if ((nDims=(size_t)mxGetNumberOfDimensions(prhs[1]))<2)
00335 output_error("dimensions of array (arg 2) are not valid");
00336 else if ((dim=mxGetDimensions(prhs[1]))==NULL)
00337 output_error("dimensions of array (arg 2) are not available");
00338 else
00339 {
00340 size_t size=1;
00341 while (nDims-->0)
00342 size*=dim[nDims];
00343 if (mxIsChar(prhs[1]))
00344 {
00345 char *buffer = malloc(1024);
00346 if(mxGetString(prhs[1],buffer,1024) && global_create(name,PT_char1024,buffer,PT_SIZE,1,NULL)==NULL)
00347 output_error("unable to register string variable '%s' in globals", name);
00348 }
00349 else if (mxIsDouble(prhs[1]))
00350 {
00351 double *x = malloc(sizeof(double)*size);
00352 unsigned int i;
00353 memset(x,0,sizeof(double)*size);
00354 for (i=0; i<size; i++)
00355 x[i] = ((double*)mxGetPr(prhs[1]))[i];
00356 if (global_create(name,PT_double,x,PT_SIZE,size,NULL)==NULL)
00357 output_error("unable to register double array variable '%s' in globals", name);
00358 }
00359 else if (mxIsComplex(prhs[1]))
00360 {
00361 complex *x = (complex*)malloc(sizeof(complex)*size);
00362 unsigned int i;
00363 memset(x,0,sizeof(complex)*size);
00364 for (i=0; i<size; i++)
00365 {
00366 x[i].r = ((double*)mxGetPr(prhs[1]))[i];
00367 x[i].i = ((double*)mxGetPi(prhs[1]))[i];
00368 x[i].f = I;
00369 }
00370 if (global_create(name,PT_complex,x,PT_SIZE,size,NULL)==NULL)
00371 output_error("unable to register complex array variable '%s' in globals", name);
00372 free(x);
00373 }
00374 else if (mxIsStruct(prhs[1]))
00375 {
00376 output_error("unable to register struct variable '%s' in globals", name);
00377 }
00378 else
00379 output_error("array (arg 2) type is not supported");
00380 }
00381 }
00382
00386 void cmex_setenv(int nlhs, mxArray *plhs[],
00387 int nrhs, const mxArray *prhs[] )
00388 {
00389 if (nrhs>1)
00390 {
00391 char name[1024];
00392 char value[1024];
00393 if (!mxIsChar(prhs[0]))
00394 output_error("variable name is not a string");
00395 else if (!mxIsChar(prhs[1]))
00396 output_error("value is not a string");
00397 else if (nlhs>0)
00398 output_error("setenv does not return a value");
00399 else if (mxGetString(prhs[0],name,sizeof(name))!=0)
00400 output_error("variable name too long");
00401 else if (mxGetString(prhs[1],value,sizeof(value))!=0)
00402 output_error("value too long");
00403 else
00404 {
00405 char env[2050];
00406 if (sprintf(env,"%s=%s", name, value)<0)
00407 output_error("unable to make environment value");
00408 else if (putenv(env)<0)
00409 output_error("unable to save environment value");
00410 }
00411 }
00412 else
00413 output_error("environment name and value not specified");
00414 return;
00415 }
00416
00420 void cmex_getenv(int nlhs, mxArray *plhs[],
00421 int nrhs, const mxArray *prhs[] )
00422 {
00423 char name[1024];
00424 if (!mxIsChar(prhs[0]))
00425 output_error("variable name is not a string");
00426 else if (mxGetString(prhs[0],name,sizeof(name))!=0)
00427 output_error("variable name too long");
00428 else
00429 {
00430 char *value = getenv(name);
00431 if (value==NULL)
00432 output_error("%s is not defined",name);
00433 else if (nlhs==0)
00434 output_message("%s='%s'",name,value);
00435 else if (nlhs==1)
00436 plhs[0] = mxCreateString(value);
00437 else
00438 output_error("getenv does not return more than one value");
00439 }
00440 return;
00441 }
00442
00446 void cmex_create(int nlhs, mxArray *plhs[],
00447 int nrhs, const mxArray *prhs[])
00448 {
00449 CLASS *oclass;
00450 OBJECT *obj;
00451 CLASSNAME classname;
00452 unsigned int num_properties = (nrhs-1)/2;
00453
00454
00455 if (nlhs>1)
00456 output_error("create only returns one struct");
00457
00458 else if (!mxIsChar(prhs[0]))
00459 output_error("class name (arg 1) must be a string");
00460
00461
00462 else if (mxGetString(prhs[0],classname,sizeof(classname)))
00463 output_error("unable to read class name (arg 1)");
00464
00465
00466 else if (num_properties!=(nrhs/2))
00467 output_error("an object property value is missing");
00468
00469
00470 else if ((oclass=class_get_class_from_classname(classname))==NULL)
00471 output_error("class '%s' is not registered", classname);
00472
00473
00474 else if (oclass->create(&obj,NULL)==FAILED)
00475 output_error("unable to create object of class %s", classname);
00476
00477
00478 else
00479 {
00480 unsigned int i;
00481 for (i=0; i<num_properties; i++)
00482 {
00483 char name[256];
00484 char value[1024];
00485 unsigned int n=i*2+1;
00486 const mxArray *p[] = {prhs[n],prhs[n+1]};
00487 if (!mxIsChar(p[0]))
00488 output_error("property name (arg %d) must be a string", n);
00489 else if (mxGetString(p[0],name,sizeof(name)))
00490 output_error("property name (arg %d) couldn't be read", n);
00491 else if (mxIsChar(p[1]) && mxGetString(p[1],value,sizeof(value)))
00492 output_error("property %s (arg %d) value couldn't be read", name, n);
00493 else if (mxIsDouble(p[1]) && sprintf(value,"%lg",*(double*)mxGetPr(p[1]))<1)
00494 output_error("property %s (arg %d) value couldn't be converted from double", name, n);
00495 else if (mxIsComplex(p[1]) && sprintf(value,"%lg%+lgi",*(double*)mxGetPr(p[1]),*(double*)mxGetPi(p[1]))<1)
00496 output_error("property %s (arg %d) value couldn't be converted from complex", name, n);
00497 else if (object_set_value_by_name(obj,name,value)==0)
00498 output_error("property %s (arg %d) couldn't be set to '%s'", name, n, value);
00499 else if (nlhs>0 && (plhs[0]=get_object_data(obj))==NULL)
00500 output_error("couldn't get object data for %s", name);
00501 }
00502 }
00503 }
00504
00508 void cmex_load(int nlhs, mxArray *plhs[],
00509 int nrhs, const mxArray *prhs[] )
00510 {
00511 if (nrhs>0)
00512 {
00513 char fname[1024];
00514 if (!mxIsChar(prhs[0]))
00515 output_error("Model name is not a string");
00516 else if (nlhs>0)
00517 output_error("load does not return a value");
00518 else if (mxGetString(prhs[0],fname,sizeof(fname))!=0)
00519 output_error("Model name too long");
00520 else if (loadall(fname)==FAILED)
00521 output_error("Model load failed");
00522 else
00523 output_message("Model %s loaded ok", fname);
00524 }
00525 else
00526 output_error("Module not specified");
00527 return;
00528 }
00529
00533 void cmex_start(int nlhs, mxArray *plhs[],
00534 int nrhs, const mxArray *prhs[] )
00535 {
00536 global_keep_progress = 1;
00537 if (exec_start()==FAILED)
00538 output_error("Simulation failed!");
00539 return;
00540 }
00545 void cmex_module(int nlhs, mxArray *plhs[],
00546 int nrhs, const mxArray *prhs[] )
00547 {
00548 if (nrhs>0)
00549 {
00550 char fname[1024];
00551 MODULE *mod;
00552 if (!mxIsChar(prhs[0]))
00553 output_error("Module name is not a string");
00554 else if (nlhs>1)
00555 output_error("Only one return value is possible");
00556 else if (mxGetString(prhs[0],fname,sizeof(fname))!=0)
00557 output_error("Module name too long");
00558 else if ((mod=module_find(fname))==NULL && (mod=module_load(fname,0,NULL))==NULL)
00559 output_error("Module load failed");
00560 else if (nlhs=0)
00561 output_message("Module '%s(%d.%d)' loaded ok", mod->name, mod->major, mod->minor);
00562 else
00563 {
00564
00565 char *fnames[256] = {"handle","name","major","minor"};
00566 mxArray *name = mxCreateString(mod->name);
00567 mxArray *handle = mxCreateNumericMatrix(1,1,sizeof(int32)==sizeof(int)?mxUINT32_CLASS:mxUINT64_CLASS,mxREAL);
00568 mxArray *major = mxCreateNumericMatrix(1,1,mxUINT8_CLASS,mxREAL);
00569 mxArray *minor = mxCreateNumericMatrix(1,1,mxUINT8_CLASS,mxREAL);
00570 mxArray *value[256];
00571 unsigned int64 *pHandle = mxGetData(handle);
00572 unsigned char *pMajor = mxGetData(major);
00573 unsigned char *pMinor = mxGetData(minor);
00574 char32 varname="";
00575 int nFields=4;
00576 char vnames[256][32];
00577 *pHandle = (unsigned int64)mod->hLib;
00578 *pMajor = (unsigned char)mod->major;
00579 *pMinor = (unsigned char)mod->minor;
00580
00581
00582 while (module_getvar(mod,varname,NULL,0))
00583 {
00584 char32 buffer;
00585 if (module_getvar(mod,varname,buffer,sizeof(buffer)) && nFields<sizeof(fname)/sizeof(fname[0]))
00586 {
00587 double *pVal;
00588 output_verbose("module variable %s = '%s'", varname, buffer);
00589 value[nFields] = mxCreateDoubleMatrix(1,1,mxREAL);
00590 pVal = mxGetPr(value[nFields]);
00591 *pVal = atof(buffer);
00592 strcpy(vnames[nFields],varname);
00593 fnames[nFields] = vnames[nFields];
00594 nFields++;
00595 }
00596 }
00597
00598
00599 plhs[0] = mxCreateStructMatrix(1,1,nFields,fnames);
00600 mxSetFieldByNumber(plhs[0],0,0,handle);
00601 mxSetFieldByNumber(plhs[0],0,1,name);
00602 mxSetFieldByNumber(plhs[0],0,2,major);
00603 mxSetFieldByNumber(plhs[0],0,3,minor);
00604 while (nFields-->4)
00605 mxSetFieldByNumber(plhs[0],0,nFields,value[nFields]);
00606
00607 }
00608 }
00609 else
00610 output_error("Module not specified");
00611 return;
00612 }
00613
00617 void cmex_set(int nlhs, mxArray *plhs[],
00618 int nrhs, const mxArray *prhs[])
00619 {
00620 if (nlhs>0)
00621 output_error("set does not return a value");
00622 else if (nrhs==1 && mxIsStruct(prhs[0]))
00623 set_object_data(prhs[0]);
00624 else if (nrhs!=3)
00625 output_error("set requires either a structure, or object id, property name and value");
00626 else if (!mxIsChar(prhs[0]))
00627 output_error("object id (arg 0) must be a string");
00628 else if (mxIsChar(prhs[1]))
00629 {
00630 char value[1024];
00631 PROPERTY* prop;
00632 OBJECT *obj=NULL;
00633 GLOBALVAR *var=NULL;
00634 if (mxGetString(prhs[0],value,sizeof(value))!=0)
00635 output_error("object name (arg 0) too long");
00636 else if (strcmp(value,"global")==0)
00637 {
00638 if (!mxIsChar(prhs[1]))
00639 output_error("global variable name is not a string");
00640 else if (!mxIsChar(prhs[2]))
00641 output_error("global value is not is not a string");
00642 else
00643 {
00644 char name[32], value[1024];
00645 mxGetString(prhs[1],name,sizeof(name));
00646 mxGetString(prhs[2],value,sizeof(value));
00647 if (global_setvar(name,value)!=SUCCESS)
00648 output_error("unable to set global '%s' to '%s'", name,value);
00649 }
00650 }
00651 else if (convert_to_object(value,&obj,NULL)==0)
00652 output_error("object (arg 0) %s not found",value);
00653 else if (mxGetString(prhs[1],value,sizeof(value))!=0)
00654 output_error("property name (arg 1) too long");
00655 else if ((prop=object_get_property(obj,value))==NULL)
00656 output_error("property name (arg 1) %s not found in object %s:%d", value,obj->oclass->name, obj->id);
00657 else if (mxIsChar(prhs[2]))
00658 {
00659 if (mxGetString(prhs[2],value,sizeof(value))!=0)
00660 output_error("value (arg 2) is too long");
00661 else if (object_set_value_by_name(obj,prop->name,value)==0)
00662 output_error("unable to set %s:%d/%s to %s", obj->oclass->name, obj->id, prop->name, value);
00663 else
00664 return;
00665 }
00666 else if (mxIsDouble(prhs[2]) && prop->ptype==PT_double)
00667 {
00668 double v = *mxGetPr(prhs[2]);
00669 if (prop->ptype==PT_double && object_set_double_by_name(obj,prop->name,v)==0)
00670 output_error("unable to set %s:%d/%s to %lg", obj->oclass->name, obj->id, prop->name, v);
00671 }
00672 else if (mxIsComplex(prhs[2]) || mxIsDouble(prhs[2]))
00673 {
00674 sprintf(value,"%lg%+lgi",*mxGetPr(prhs[2]),mxIsComplex(prhs[2])?*mxGetPi(prhs[2]):0);
00675 if (object_set_value_by_name(obj,prop->name,value)==0)
00676 output_error("unable to set %s:%d/%s to %s", obj->oclass->name, obj->id, prop->name, value);
00677 }
00678 else
00679 output_error("value (arg 2) has an unsupported data type");
00680 }
00681 else
00682 output_error("property or data (arg 1) type is not valid");
00683 }
00684
00688 void cmex_get(int nlhs, mxArray *plhs[],
00689 int nrhs, const mxArray *prhs[] )
00690 {
00691 if (nrhs>0)
00692 {
00693 char name[1024];
00694 OBJECT *obj=NULL;
00695 if (!mxIsChar(prhs[0]))
00696 output_error("entity name (arg 1) is not a string");
00697 else if (nlhs>1)
00698 output_error("only one return value is possible");
00699 else if (mxGetString(prhs[0],name,sizeof(name))!=0)
00700 output_error("object name too long");
00701 else if (strcmp(name,"clock")==0)
00702 {
00703 char *fnames[] = {"timestamp","timestring","timezone"};
00704 char buffer[256];
00705 mxArray *pTimestamp = mxCreateDoubleMatrix(1,1,mxREAL);
00706 mxArray *pTimestring = mxCreateString(convert_from_timestamp(global_clock,buffer,sizeof(buffer))?buffer:"(error)");
00707 mxArray *pTimezone = mxCreateString(timestamp_current_timezone());
00708
00709 *(double*)mxGetPr(pTimestamp) = ((double)global_clock)/TS_SECOND;
00710 plhs[0] = mxCreateStructMatrix(1,1,sizeof(fnames)/sizeof(fnames[0]),fnames);
00711 mxSetFieldByNumber(plhs[0],0,0,pTimestamp);
00712 mxSetFieldByNumber(plhs[0],0,1,pTimestring);
00713 mxSetFieldByNumber(plhs[0],0,2,pTimezone);
00714 }
00715 else if (strcmp(name,"property")==0 && nrhs>1)
00716 {
00717 if (mxGetString(prhs[1],name,sizeof(name))!=0)
00718 output_error("missing property name");
00719 else
00720 {
00721 char classname[256];
00722 char propname[256];
00723 if (sscanf(name,"%[^.].%s",classname,propname)==2)
00724 {
00725 CLASS *pClass = class_get_class_from_classname(classname);
00726 if (pClass)
00727 {
00728 PROPERTY *pProp = class_find_property(pClass,propname);
00729 if (pProp)
00730 {
00731 char *fields[] = {"class","name","type","size","access","unit","delegation","keywords"};
00732 int fn = 0;
00733 mxArray *oclass = mxCreateString(classname);
00734 mxArray *prop = mxCreateString(pProp->name);
00735 mxArray *type = mxCreateString(class_get_property_typename(pProp->ptype));
00736 mxArray *size = mxCreateDoubleMatrix(1,1,mxREAL);
00737 mxArray *access = mxCreateString("(na)");
00738 mxArray *unit = mxCreateString(pProp->unit->name);
00739 mxArray *delegation = mxCreateString(pProp->delegation?pProp->delegation->oclass->name:"(none)");
00740 mxArray *keywords = mxCreateString("(na)");
00741 *(mxGetPr(size)) = pProp->size==0?1:pProp->size;
00742 plhs[0] = mxCreateStructMatrix(1,1,sizeof(fields)/sizeof(fields[0]),fields);
00743 mxSetFieldByNumber(plhs[0],0,fn++,oclass);
00744 mxSetFieldByNumber(plhs[0],0,fn++,prop);
00745 mxSetFieldByNumber(plhs[0],0,fn++,type);
00746 mxSetFieldByNumber(plhs[0],0,fn++,size);
00747 mxSetFieldByNumber(plhs[0],0,fn++,access);
00748 mxSetFieldByNumber(plhs[0],0,fn++,unit);
00749 mxSetFieldByNumber(plhs[0],0,fn++,delegation);
00750 mxSetFieldByNumber(plhs[0],0,fn++,keywords);
00751 }
00752 else
00753 output_error("property %s is not found in class %s", propname,classname);
00754 }
00755 else
00756 output_error("class %s is not found");
00757 }
00758 else
00759 output_error("property name not in class.name format");
00760 }
00761 }
00762 else if ((convert_to_object(name,&obj,NULL))==0)
00763 {
00764 GLOBALVAR *var = global_find(name);
00765 if (var==NULL)
00766 output_error("entity '%s' not found", name);
00767 else if (var->prop->ptype==PT_double)
00768 {
00769 size_t size = var->prop->size?var->prop->size:1;
00770 plhs[0] = mxCreateDoubleMatrix(size,1,mxREAL);
00771 memcpy(mxGetPr(plhs[0]),(void*)var->prop->addr,sizeof(double)*size);
00772 }
00773 else if (var->prop->ptype==PT_int32)
00774 {
00775 size_t size = var->prop->size?var->prop->size:1;
00776 plhs[0] = mxCreateDoubleMatrix(size,1,mxREAL);
00777
00778 memcpy(mxGetPr(plhs[0]),(void*)var->prop->addr,sizeof(double)*size);
00779 }
00780 else if (var->prop->ptype!=PT_double)
00781 output_error("cannot retrieve globals that are of type %s",class_get_property_typename(var->prop->ptype));
00782 }
00783 else if ((plhs[0]=get_object_data(obj))==NULL)
00784 output_error("unable to extract %s data", name);
00785 }
00786 else
00787 output_error("object not specified");
00788 return;
00789 }
00790
00791
00792
00793
00794
00795
00796
00797 typedef struct
00798 {
00799 char *name;
00800 void (*call)(int, mxArray*[],int,const mxArray*[]);
00801 char *brief;
00802 char *detail;
00803 } CMDMAP;
00804 static CMDMAP cmdMap[] =
00805 {
00806 {"setenv",cmex_setenv,"Set environment",
00807 "\tgl('setenv','name','value')\n"
00808 " Set an environment variable\n"
00809 },
00810
00811 {"getenv",cmex_getenv,"Get environment",
00812 "\tgl('getenv','name')\n"
00813 " Get an environment variable\n"
00814 },
00815
00816 {"start",cmex_start,"Start simulation",
00817 "\tgl('start')\n"
00818 " Start the GridLAB simulation.\n"
00819 },
00820
00821 {"load",cmex_load,"Import GridLAB model",
00822 "\tgl('load',filename)\n"
00823 " Import the GridLAB model in <filename>.\n"
00824 },
00825
00826 {"module",cmex_module,"Load GridLAB module",
00827 "\tgl('module',modulename)\n"
00828 " Load the GridLAB module named <modulename>.\n"
00829 },
00830
00831 {"version",cmex_version,"Get GridLAB version information",
00832 "\tgl('version')\n"
00833 " Returns the major, minor, and build numbers of the installed version of GridLAB.\n"
00834 },
00835
00836 {"get",cmex_get,"Get an object's data",
00837 "\tgl('get',name)\n"
00838 " Returns the object structure\n"
00839 },
00840
00841 {"set",cmex_set,"Set an object's data",
00842 "\tgl('set',id,property,value)\n"
00843 " Returns the object structure\n"
00844 },
00845 {"create",cmex_create,"Create an object",
00846 "\tgl('create',class, property1,value1, property2,value2, ..., propertyN,valueN)\n"
00847 " Returns the object structure\n"
00848 },
00849 {"global",cmex_global,"Create a global variable",
00850 "\tgl('global',name,array)\n"
00851 " Returns nothing\n"
00852 },
00853
00854 {"list",cmex_list,"Obtain a list of entities",
00855 "\tgl('list',type)\n"
00856 " Returns a list of entities\n"
00857 },
00858 };
00859
00860 void mexFunction( int nlhs, mxArray *plhs[],
00861 int nrhs, const mxArray *prhs[] )
00862 {
00863 static first = 1;
00864 char key[MAXNAME];
00865 int i;
00866
00867 if (first==1)
00868 {
00869 first = 0;
00870
00871
00872 mexLock();
00873
00874
00875 output_set_stdout(mexPrintf);
00876 output_set_stderr(cmex_printerr);
00877
00878
00879 legal_license();
00880
00881
00882 exec_init();
00883 }
00884
00885
00886 if (nrhs<1)
00887 {
00888 output_error("Use gl('help') for a list of commands.");
00889 return;
00890 }
00891
00892
00893 if (!mxIsChar(prhs[0]))
00894 {
00895 output_error("token must be a string");
00896 return;
00897 }
00898
00899
00900 if (mxGetString(prhs[0],key,sizeof(key))!=0)
00901 output_warning("GridLAB key string too long");
00902
00903
00904 for (i=0; i<sizeof(cmdMap)/sizeof(cmdMap[0]); i++)
00905 {
00906 if (strcmp(key,cmdMap[i].name)==0)
00907 {
00908 if (cmdMap[i].call == NULL)
00909 {
00910 int j;
00911 if (nrhs==1)
00912 {
00913 output_raw("Available top-level commands\n");
00914 for (j=0; j<sizeof(cmdMap)/sizeof(cmdMap[0]); j++)
00915 output_raw("\t%s\t%s\n", cmdMap[j].name, cmdMap[j].brief);
00916 output_raw("Use gl('help',command) for details\n");
00917 return;
00918 }
00919 else if (mxIsChar(prhs[1]))
00920 {
00921 char cmd[MAXNAME];
00922 if (mxGetString(prhs[1],cmd,sizeof(cmd))!=0)
00923 output_warning("command string too long to read fully");
00924
00925 for (j=0; j<sizeof(cmdMap)/sizeof(cmdMap[0]); j++)
00926 {
00927 if (strcmp(cmd,cmdMap[j].name)==0)
00928 {
00929 output_raw("Help for command '%s'\n\n%s\n", cmd, cmdMap[j].detail ? cmdMap[j].detail : "\tNo details available\n");
00930 return;
00931 }
00932 }
00933 output_error("Command '%s' does not exist", cmd);
00934 return;
00935 }
00936 else
00937 {
00938 output_error("command must be a string");
00939 return;
00940 }
00941 }
00942 else
00943 {
00944 (cmdMap[i].call)(nlhs,plhs,nrhs-1,prhs+1);
00945 return;
00946 }
00947 }
00948 }
00949
00950
00951 { int nret = nlhs;
00952 output_error("unrecognized GridLAB operation--gl('help') for list");
00953 while (nret-->0)
00954 plhs[nret] = mxCreateDoubleMatrix(0,0,mxREAL);
00955 }
00956 return;
00957 }
00958