10 #include <netinet/in.h>
11 #include <arpa/inet.h>
14 // #include <qthread.h>
17 static void load(char *);
18 static void initiate(int,char **);
19 int main(int,char **);
22 static void initiate();
28 * @brief Compiler and interpreter code
31 int internal_sock, graph_sock, net_sock, connected = 0;
32 struct sockaddr_un svr;
34 char ProgName[255], mygname[80], gname[80], mykname[80], nname[80], mynname[80];
39 ctx_struct parent_ctx;
42 * IDs of remote instances
47 * Direct connection channels
54 int fcol, bcol, curx=0, cury=0;
58 * Macro to decode addressing modes:
60 #define getargument(a, argnr) \
61 switch (eop->args[ argnr ]) \
63 case GLOBAL : a = M[ ic++ ]; break; \
64 case LOCAL : a = c1+M[ ic++ ]; break; \
65 case TEMPLOCAL : a = c2+M[ ic++ ]; break; \
66 case REMOTE : a = M[ M[ ic+1 ] ]+M[ ic ]; ic+=2; break;\
67 case INDIRECT : a = M[ M[ ic++ ] ]; break;\
68 case IMMEDIATE : a = ic++; break;\
69 case CONSTANT : a = M[ ic++ ]; break;\
70 case DOTACCESS : a = M[ display+M[ ic+1 ] ]+M[ ic ]; ic += 2; break;\
71 case NOARGUMENT : return; \
75 * Loads code and prototypes from files
76 * Files have following extensions:
77 * .ccd - compiler code
80 * @param _filename Filename of file to read.
82 static void load(char *_filename)
87 /* should suffice on all systems */
90 strcpy(filename, _filename);
91 /* allocate main memory array */
92 M = mallocate(memorysize + 1);
94 abend("Memory size too large (use /m option)\n");
96 addext(filename, ".ccd");
97 if ((fp = fopen(filename, BINARYREAD)) == NULL) {
98 fprintf(stderr, "Cannot open .ccd file\n");
102 /* read static data and code from .ccd file */
104 left = memorysize + 1;
107 abend("Memory size too small (use /m option)\n");
108 n = min(IOBLOCK / sizeof(word), left);
109 n = fread((char *) &M[ ic ], sizeof(word), (int) n, fp);
113 /* now ic = number of words read */
117 /* Get various addresses passed by GENERATOR */
119 /* primitive type desctriptions */
121 /* global temporary variables */
122 temporary = M[ic - 4];
123 /* string constants */
125 /* last prototype number */
126 lastprot = M[ic - 2];
127 /* first free word in memory */
130 /* Read prototypes from .pcd file */
131 addext(filename, ".pcd");
132 if ((fp = fopen(filename, BINARYREAD)) == NULL) {
133 fprintf(stderr,"Cannot open .pcd file\n");
136 for (n = MAINBLOCK; n <= lastprot; n++) {
137 cp = ballocate(sizeof(protdescr));
139 abend("Memory size too large (use /m option)\n");
140 prototype[n] = (protdescr *) cp;
142 if (fread(cp, sizeof(protdescr), 1, fp) != 1)
143 abend("Cannot read .pcd file\n");
147 /* Open trace file */
149 addext(filename, ".trd");
150 if ((tracefile = fopen(filename, "w")) == NULL)
151 abend("Cannot open .trd file\n");
156 * Establishes configuration parameters
157 * Creates two sockets for program run
159 * @param argc number of passed values in argv array
162 * @param argv[3] if value is equal to: "r", sets global #remote variable to
163 * TRUE, FALSE otherwise
165 static void initiate(int argc, char **argv)
175 if ((argc == 4) && (strcmp(argv[3], "r") == 0))
180 for(i = 0; i < 255; i++) {
188 strcpy(filename, argv[2]);
189 strcpy(ProgName, argv[2]);
191 strcpy(mynname, argv[1]);
192 strcat(mynname, ".net");
194 sock = socket(AF_UNIX, SOCK_STREAM, 0);
195 bzero(&svr, sizeof(svr));
196 svr.sun_family = AF_UNIX;
197 strcpy(svr.sun_path, mynname);
198 len = strlen(svr.sun_path) + sizeof(svr.sun_family);
199 bind(sock, (struct sockaddr*)&svr, len);
203 /* socket for graphic requests */
204 strcpy(mygname, argv[1]);
205 strcat(mygname, ".gr");
208 /* socket for KERNEL communication */
209 internal_sock = socket(AF_UNIX, SOCK_STREAM, 0);
210 bzero(&svr, sizeof(svr));
211 svr.sun_family = AF_UNIX;
212 strcpy(svr.sun_path, argv[1]);
213 strcpy(mykname, argv[1]);
214 len = strlen(svr.sun_path) + sizeof(svr.sun_family);
215 i = connect(internal_sock, (struct sockaddr*)&svr, len);
218 fcntl(internal_sock,F_SETFL, O_NONBLOCK |
219 fcntl(internal_sock,F_GETFL,0));
223 close(internal_sock);
224 internal_sock = socket(AF_UNIX, SOCK_STREAM, 0);
225 fcntl(internal_sock, F_SETFL, O_NONBLOCK |
226 fcntl(internal_sock, F_GETFL, 0));
227 i = connect(internal_sock, (struct sockaddr*)&svr, len);
230 setsockopt(internal_sock, IPPROTO_TCP, TCP_NODELAY, (char*)&on,
233 /* socket for network requests */
237 if (select(sock + 1, &rset, &wset, 0, 0))
238 net_sock = accept(sock, (struct sockaddr*)0, (int *)0);
241 fcntl(net_sock, F_SETFL, O_NONBLOCK |
242 fcntl(net_sock, F_GETFL, 0));
243 setsockopt(net_sock, IPPROTO_TCP, TCP_NODELAY, (char*)&on,
249 /* load code and prototypes */
250 if (filename != NULL)
262 /* pointer to extended opcode in M */
263 eop = (extopcode *)(M + ic);
264 /* save ic for possible redecoding */
267 opcode = ((int) eop->opcode ) & 0xFF ;
274 * Sends message to graph module.
275 * @param msg Message to send.
277 void send_to_graph(G_MESSAGE *msg)
279 write(graph_sock, msg, sizeof(G_MESSAGE));
283 * Reads message from graph module.
284 * @param msg Message to read.
286 int read_from_graph(G_MESSAGE *msg)
289 struct timeval tout = {0, 0};
293 FD_SET(graph_sock, &rset);
296 if (select(graph_sock + 1, &rset, &wset, 0, (struct timeval *)&tout) > 0) {
297 if (FD_ISSET(graph_sock, &rset))
298 return(read(graph_sock,msg,sizeof(G_MESSAGE)));
304 * Reads message from net module.
306 * @param msg Message to read.
308 int read_from_net(MESSAGE *msg)
311 struct timeval tout = {0, 0};
315 FD_SET(net_sock, &rset);
318 if (select(net_sock + 1, &rset, &wset, 0, (struct timeval *)&tout) > 0) {
319 if (FD_ISSET(net_sock, &rset))
320 return(read(net_sock, msg, sizeof(MESSAGE)));
327 * Gets graphic resource number
333 struct sockaddr_un svr;
338 sock = socket(AF_UNIX, SOCK_STREAM, 0);
339 bzero(&svr, sizeof(svr));
340 svr.sun_family = AF_UNIX;
341 strcpy(svr.sun_path, mygname);
342 len = strlen(svr.sun_path) + sizeof(svr.sun_family);
343 bind(sock, (struct sockaddr*)&svr, len);
347 msg.msg_type = MSG_GRAPH;
348 msg.param.pword[0] = GRAPH_ALLOCATE;
349 strcpy(msg.param.pstr, mygname);
350 write(internal_sock, &msg, sizeof(MESSAGE));
351 bzero(&msg, sizeof(MESSAGE));
355 if (select(sock+1, &rset, &wset, 0, 0))
356 graph_sock = accept(sock, (struct sockaddr*)0, (int*)0);
358 if (graph_sock == -1) {
364 fcntl(graph_sock, F_SETFL, O_NONBLOCK|fcntl(graph_sock, F_GETFL, 0));
365 setsockopt(graph_sock, IPPROTO_TCP, TCP_NODELAY, (char*)&on, sizeof(on));
372 * Writes string line (ended with new line character)
374 void writeln_str(char *s)
377 msg.msg_type = MSG_GRAPH;
378 msg.param.pword[1] = GraphRes;
379 msg.param.pword[2] = GRAPH_WRITE;
380 strcpy(msg.param.pstr, s);
383 strcpy(msg.param.pstr, "\n");
390 * Passed string is send to graph module by G_MESSAGE packet using send_to_graph
392 * @param s String to write
394 void write_str(char *s)
397 msg.msg_type = MSG_GRAPH;
398 msg.param.pword[1] = GraphRes;
399 msg.param.pword[0] = GRAPH_WRITE;
400 strcpy(msg.param.pstr, s);
407 * Passed char is send to graph module by G_MESSAGE packet using send_to_graph
409 * @param a Character to write
411 void write_char(char a)
415 msg.msg_type = MSG_GRAPH;
416 msg.param.pword[1] = GraphRes;
417 msg.param.pword[0] = GRAPH_PUTCHAR;
425 * @return Read character
433 msg.msg_type = MSG_GRAPH;
434 msg.param.pword[1] = GraphRes;
435 msg.param.pword[0] = GRAPH_READCHAR;
438 st = read_from_graph(&msg);
440 if ((msg.msg_type == MSG_GRAPH) &&
441 (msg.param.pword[0] == GRAPH_READCHAR_RESPONSE))
443 ch = msg.param.pchar;
460 msg.msg_type = MSG_GRAPH;
461 msg.param.pword[1] = GraphRes;
462 msg.param.pword[0] = GRAPH_READLN;
465 st = read_from_graph(&msg);
467 if ((msg.msg_type == MSG_GRAPH) &&
468 (msg.param.pword[0] == GRAPH_READLN_RESPONSE))
475 * @param s Buffer to store string.
477 void read_str(char *s)
483 msg.msg_type = MSG_GRAPH;
484 msg.param.pword[1] = GraphRes;
485 msg.param.pword[0] = GRAPH_READSTR;
488 st = read_from_graph(&msg);
490 if ((msg.msg_type == MSG_GRAPH) &&
491 (msg.param.pword[0] == GRAPH_READSTR_RESPONSE)) {
492 strcpy(ss, msg.param.pstr);
501 * Sends message to kernel
502 * @param msg Message to send to kernel
504 void send_to_kernel(MESSAGE *msg)
506 write(internal_sock, msg, sizeof(MESSAGE));
510 * Sends message to net
511 * @return Returns 1 if ok and 0 if node desn't exists (since 2010)
513 int send_to_net(MESSAGE *msg)
517 struct sockaddr_in svr;
521 k = msg->int_msg.control.receiver.node;
523 /* 2010 check if node exists */
524 m.msg_type = MSG_NET;
525 m.param.pword[0] = NET_NODE_EXIST;
526 m.param.pword[1] = k;
527 m.param.pword[2] = my_ctx.program_id;
528 write(net_sock, &m, sizeof(MESSAGE));
529 bzero(&m, sizeof(MESSAGE));
530 while((m.msg_type != MSG_NET) && (m.param.pword[0] != NET_NODE_EXIST))
531 read(net_sock, &m, sizeof(MESSAGE));
533 if (m.param.pword[1] != 1)
536 strcpy(addr, m.param.pstr);
538 if (RInstance[k] == -1) {
539 bzero(&m,sizeof(MESSAGE));
540 m.msg_type = MSG_VLP;
541 m.param.pword[0] = VLP_REMOTE_INSTANCE_PLEASE;
542 m.param.pword[1] = my_ctx.program_id;
543 m.param.pword[2] = k;
545 bzero(&m, sizeof(MESSAGE));
548 read(internal_sock, &m, sizeof(MESSAGE));
549 if ((m.msg_type == MSG_VLP) &&
550 (m.param.pword[0] == VLP_REMOTE_INSTANCE_HERE))
554 /*printf("DEBUG: remote instance made with id: "
555 "%d addr %s port %d\n", m.param.pword[1], addr,
556 htons(m.param.pword[8]));*/
557 RInstance[k] = m.param.pword[1];
558 /* Make direct connection */
559 DirConn[k] = socket(AF_INET, SOCK_STREAM, 0);
560 svr.sin_family = AF_INET;
561 svr.sin_addr.s_addr = inet_addr(addr);
562 svr.sin_port = htons(m.param.pword[8]);
563 len = connect(DirConn[k], (struct sockaddr*)&svr, sizeof(svr));
567 writeln_str("Cannot connect remote instance!");
569 fcntl(DirConn[k], F_SETFL, O_NONBLOCK |
570 fcntl(DirConn[k], F_GETFL, 0));
573 if (RInstance[k] != -1) {
574 write(DirConn[k], &(msg->int_msg), sizeof(message));
579 /* -------------------- Check for message on internal socket -------------*/
589 struct timeval tout = {0, 0};
592 /* ----------- Direct connection messages -----
595 for(i = 0; i < 255; i++)
596 if (DirConn[i]!=-1) {
597 FD_SET(DirConn[i], &DirSet);
598 if (maxDirSet<DirConn[i])
599 maxDirSet=DirConn[i];
602 if (select(maxDirSet + 1, &DirSet, 0, 0, (struct timeval *)&tout) > 0) {
603 for(i = 0; i < 255; i++) {
604 if ((DirConn[i] != -1) &&
605 (FD_ISSET(DirConn[i], &DirSet))) {
606 r = read(DirConn[i], &mx, sizeof(mx));
608 memcpy(globmsgqueue + msgtail,&mx,
610 msgtail = (msgtail + 1) % MAXMSGQUEUE;
616 -----------------------------------------*/
619 FD_SET(net_sock, &rset);
620 FD_SET(internal_sock, &rset);
621 if (net_sock > internal_sock)
626 for(i = 0; i < 255; i++) {
627 if (DirConn[i] != -1) {
628 FD_SET(DirConn[i], &rset);
629 if (max < DirConn[i])
634 if (select(max + 1, &rset, 0, 0, (struct timeval *)&tout) > 0) {
636 for(i = 0; i < 255; i++) {
637 if ((DirConn[i] != -1) && (FD_ISSET(DirConn[i], &rset))) {
639 printf("DEBUG: Interp has message on "
640 "direct connection: type %d par %d\n",
641 mx.control.type,mx.control.par);
643 r = read(DirConn[i], &mx, sizeof(mx));
644 if (r > 0 && r == sizeof(mx)) {
645 memcpy(globmsgqueue + msgtail, &mx,
647 msgtail = (msgtail+1) % MAXMSGQUEUE;
653 if (FD_ISSET(net_sock,&rset)) {
654 r = read(net_sock, &m, sizeof(MESSAGE));
659 switch(m.param.pword[0]) {
662 printf("DEBUG: cint net_sock MSG_NET "
663 "NET_PROPAGATE cmd %d\n",
665 memcpy(globmsgqueue + msgtail,
668 msgtail = (msgtail + 1) %
678 if (FD_ISSET(internal_sock, &rset)) {
679 r = read(internal_sock, &m, sizeof(MESSAGE));
684 switch(m.param.pword[0]) {
685 case INT_CLOSE_INSTANCE:
693 if (m.param.pword[0] == NET_PROPAGATE) {
695 printf("DEBUG: cint internal_sock MSG_NET NET_PROPAGATE cmd %d\n",m.param.pword[6]);*/
696 memcpy(globmsgqueue + msgtail,
699 msgtail = (msgtail+1) %
716 m.msg_type = MSG_INT;
717 m.param.pword[0] = INT_CTX_REQ;
719 while ((m.msg_type != MSG_INT) || (m.param.pword[0] != INT_CTX))
720 read(internal_sock, &m, sizeof(MESSAGE));
722 my_ctx.node = m.param.pword[1];
723 my_ctx.program_id = m.param.pword[2];
725 parent_ctx.node = m.param.pword[3];
726 parent_ctx.program_id = m.param.pword[4];
727 RInstance[parent_ctx.node] = parent_ctx.program_id;
729 parent_ctx.node = my_ctx.node;
730 parent_ctx.program_id = my_ctx.program_id;
732 ournode = my_ctx.node;
733 /* strcpy(nname,m.param.pstr);*/
734 /* net_sock = open(nname,O_WRONLY);*/
735 m1.msg_type = MSG_GRAPH;
736 m1.param.pword[0] = GRAPH_SET_TITLE;
737 m1.param.pword[1] = GraphRes;
738 sprintf(m1.param.pstr, "%s ID: %d", ProgName, my_ctx.program_id);
741 strcat(m1.param.pstr, " REMOTE instance");
751 struct sockaddr_in svr;
753 struct hostent *info;
756 msg.msg_type = MSG_NET;
757 msg.param.pword[0] = NET_PROPAGATE;
758 msg.param.pword[1] = MSG_VLP;
759 msg.param.pword[2] = my_ctx.node;
760 msg.param.pword[4] = parent_ctx.node;
761 msg.param.pword[6] = VLP_REMOTE_INSTANCE_OK;
762 msg.param.pword[7] = my_ctx.program_id;
764 sock = socket(AF_INET, SOCK_STREAM, 0);
765 bzero(&svr, sizeof(svr));
766 svr.sin_family = AF_INET;
767 svr.sin_addr.s_addr = INADDR_ANY;
769 bind(sock, (struct sockaddr*)&svr, sizeof(svr));
772 getsockname(sock,(struct sockaddr*)&svr, &len);
773 msg.param.pword[8] = ntohs(svr.sin_port);
774 gethostname(name, &len);
775 info = (struct hostent*)gethostbyname(name);
776 bcopy((char*)info->h_addr, (char*)&svr.sin_addr, info->h_length);
777 sprintf(msg.param.pstr, "%s", inet_ntoa(svr.sin_addr));
778 send_to_kernel(&msg);
780 bzero(&svr, sizeof(svr));
781 DirConn[parent_ctx.node] = accept(sock, (struct sockaddr*)&svr, &len);
782 fcntl(DirConn[parent_ctx.node], F_SETFL, O_NONBLOCK |
783 fcntl(DirConn[parent_ctx.node], F_GETFL, 0));
787 * strcpy(filename, argv[2]);
788 * strcpy(ProgName, argv[2]);
790 * @param argv[1] = base name of this interpreter instance.
791 * For network there is created argv[1].net socket
792 * For graphics there is created argv[1].gr socket
793 * @param argv[2] = up to 80 characters string (with terminating \0). It is used to
794 * load selected program
795 * @param argv[3] = if exists and is equal to 'r', this is a remote call
797 int main(int argc, char **argv)
799 /* initialize executor */
800 initiate(argc, argv);
801 /* initialize running system */
804 GraphRes = get_graph_res();
812 /* set label for continue long jump */
814 /* repeat until exit() is called */
817 /* reschedule current process */
820 /* fetch instruction */