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