00001
00074
00075
00076 #include <stdlib.h>
00077 #include <stdarg.h>
00078 #ifdef WIN32
00079 #include <direct.h>
00080 #define getcwd _getcwd
00081 #define putenv _putenv
00082 #else
00083 #include <unistd.h>
00084 #include <dlfcn.h>
00085 #endif
00086 #include "machine.h"
00087 #include "plc.h"
00088 #include "comm.h"
00089
00090 #ifdef WIN32
00091 char path[1024] = "c:/mingw/bin";
00092 char tmpdir[1024] = "c:/temp";
00093 #else
00094 char path[1024] = "/usr/bin";
00095 char tmpdir[1024] = "/tmp";
00096 #endif
00097
00098 int exec(char *format,...)
00099 {
00100 char cmd[1024];
00101 va_list ptr;
00102 va_start(ptr,format);
00103 vsprintf(cmd,format,ptr);
00104 va_end(ptr);
00105 gl_debug("Running '%s'", cmd);
00106 return system(cmd);
00107 }
00108
00109 void sendx(machine *src, char *to, void *str, unsigned int len)
00110 {
00111 if (len==0)
00112 len=(unsigned int)strlen((char*)str);
00113 OBJECT *obj = gl_get_object(to);
00114 if (obj)
00115 {
00116 machine *dst = OBJECTDATA(obj,plc)->get_machine();
00117 src->send(new Message(str,len,src,dst));
00118 }
00119 else
00120 gl_error("sendx(machine=%x, to='%s', str='%-.8s%s', len=%d): message recipient '%s' not found", src, to, (char*)str, len>8?"...":"", len, to);
00121 }
00122
00123 int recvx(machine *dst, char *from, void *str, unsigned int len)
00124 {
00125 Message *msg = dst->receive();
00126 if (msg!=NULL)
00127 {
00128 unsigned int sz = (unsigned int)msg->get_size()+1;
00129 if (sz>len) sz=len;
00130 memcpy(str,msg->get_data(),sz);
00131 strcpy(from,"(unknown)");
00132 return sz;
00133 }
00134 else
00135 return 0;
00136 }
00137
00138 machine::machine(void)
00139 : _link()
00140 {
00141 _code=NULL;
00142 _init=NULL;
00143 _data=NULL;
00144 wait=-1;
00145 }
00146
00147 machine::~machine(void)
00148 {
00149 }
00150
00151
00152
00153
00154
00155
00156
00157 int machine::compile(char *source)
00158 {
00159 extern char libpath[65536], incpath[65536];
00160 char cfile[1024];
00161 char ofile[1024];
00162 char lfile[1024];
00163 char name[64], *basename;
00164 char *pSlash, *pDot;
00165 char oldpath[65536]="", newpath[65536];
00166 char buffer[1024];
00167 FILE *fp;
00168
00169
00170 if (getenv("PATH")) strcpy(oldpath, getenv("PATH"));
00171 if (strcmp(oldpath,"")==0)
00172 sprintf(newpath,"PATH=%s",path);
00173 else
00174 sprintf(newpath,"PATH=%s;%s",path,oldpath);
00175 putenv(newpath);
00176
00177
00178 strcpy(name,source);
00179 pSlash = strrchr(name,'/');
00180 pDot = strrchr(name,'.');
00181 if (pDot!=NULL && pDot>pSlash)
00182 *pDot='\0';
00183 basename = (pSlash==NULL ? name : pSlash+1);
00184 sprintf(cfile,"%s/%s.c", tmpdir,basename);
00185 sprintf(ofile,"%s/%s.o", tmpdir,basename);
00186
00187 #ifdef WIN32
00188 sprintf(lfile,"%s/%s.dll", tmpdir,basename);
00189 #else
00190 sprintf(lfile,"%s/lib%s.so", tmpdir,basename);
00191 #endif
00192
00193
00194 gl_verbose("converting %s to %s...", source, cfile);
00195 fp=fopen(cfile,"w");
00196 if (fp==NULL)
00197 {
00198 gl_error("%s: %s", cfile, strerror(errno));
00199 return -1;
00200 }
00201 fprintf(fp,"/* this code automatically generated by gridlab-d " __FILE__ "*/\n");
00202 fprintf(fp,"/* wd=%s */\n", getcwd(buffer,sizeof(buffer)));
00203 fprintf(fp,"#include <plc.h>\n");
00204 fprintf(fp,"#include \"%s/%s\"\n", buffer,source);
00205 fprintf(fp,"/* END */\n");
00206 fclose(fp);
00207
00208
00209 gl_verbose("compiling %s from %s using incpath '%s'...", ofile, cfile,incpath);
00210 unlink(ofile);
00211 if (exec("gcc -I\"%s\" -c \"%s\" -o \"%s\"",incpath,cfile,ofile)!=0)
00212 return -1;
00213
00214
00215 gl_verbose("converting %s to dynamic link library...", ofile);
00216 unlink(lfile);
00217 if (exec("gcc -export-all-symbols -shared -o \"%s\" -Wl,\"%s\"", lfile,ofile)!=0)
00218 return -1;
00219
00220
00221 gl_verbose("loading dynamic link library %s...", ofile);
00222 wait = load_library(lfile,&_code,&_init,&_data);
00223 if (wait<0)
00224 {
00225 #ifdef WIN32
00226 gl_error("%s: %s", lfile, strerror(errno));
00227 #else
00228 gl_error("%s: %s", lfile, dlerror());
00229 #endif
00230 return -1;
00231 }
00232 if (_code==NULL)
00233 {
00234 gl_error("%s: CODE block not found", source);
00235 return -1;
00236 }
00237 if (_init==NULL)
00238 {
00239 gl_error("%s: INIT block not found", source);
00240 return -1;
00241 }
00242 if (_data==NULL)
00243 {
00244 gl_error("%s: DATA block not found", source);
00245 return -1;
00246 }
00247 return 0;
00248 }
00249
00250
00251
00252
00253
00254
00255
00256 int machine::init(OBJECT *parent)
00257 {
00258 gl_debug("Connecting PLC to %s:%d...", parent->oclass->name, parent->id);
00259 PLCDATA item;
00260 for (item=_data; item->name!=NULL; item++)
00261 {
00262 PROPERTY *p = gl_get_property(parent,item->name);
00263 if (p==NULL)
00264 {
00265 gl_error("PCL data item %s is not found in object %s:%d", item->name, parent->oclass->name, parent->id);
00266 return -1;
00267 }
00268 else if (item->type!=p->ptype)
00269 {
00270 gl_error("PLC data item %s does not match parent's type", item->name);
00271 return -1;
00272 }
00273 else
00274 item->addr = (void*)((char*)(parent+1)+(unsigned int64)p->addr);
00275 }
00276 gl_debug("Initializing %s:%d PLC...", parent->oclass->name, parent->id);
00277 return (*_init)();
00278 }
00279
00280
00281
00282
00283
00284
00285
00286 int machine::run(double dt)
00287 {
00288 extern TIMESTAMP *pGlobalClock;
00289 static PLCDEV dev = {(unsigned int)((*pGlobalClock)/TS_SECOND),{&sendx,&recvx}};
00290 return (*_code)(this,dt,&dev);
00291 }
00292
00293 void machine::connect(comm *ptr)
00294 {
00295 net = ptr;
00296 }
00297
00298 void machine::deliver(Message *msg)
00299 {
00300 _link.add(msg);
00301 }
00302
00303 Message *machine::receive(void)
00304 {
00305 return _link.take();
00306 }
00307
00308 void machine::send(Message *msg)
00309 {
00310 net->route(msg);
00311 }
00312
00313 void machine::send(char *to, void *str, size_t len)
00314 {
00315 if (len==0)
00316 len=strlen((char*)str);
00317 OBJECT *obj = gl_get_object(to);
00318 machine *dst = OBJECTDATA(obj,plc)->get_machine();
00319 send(new Message(str,len,this,dst));
00320 }
00321