12 #include <netinet/in.h>
13 #include <arpa/inet.h>
19 static void load(char *);
20 static void initiate(int,char **);
21 int main(int,char **);
24 static void initiate();
30 int internal_sock, graph_sock, net_sock, connected = 0;
31 struct sockaddr_un svr;
33 char ProgName[255], mygname[80], gname[80], mykname[80], nname[80], mynname[80];
38 ctx_struct parent_ctx;
41 * IDs of remote instances
46 * Direct connection channels
53 int fcol, bcol, curx=0, cury=0;
57 * Macro to decode addressing modes:
59 #define getargument(a, argnr) \
60 switch (eop->args[ argnr ]) \
62 case GLOBAL : a = M[ ic++ ]; break; \
63 case LOCAL : a = c1+M[ ic++ ]; break; \
64 case TEMPLOCAL : a = c2+M[ ic++ ]; break; \
65 case REMOTE : a = M[ M[ ic+1 ] ]+M[ ic ]; ic+=2; break;\
66 case INDIRECT : a = M[ M[ ic++ ] ]; break;\
67 case IMMEDIATE : a = ic++; break;\
68 case CONSTANT : a = M[ ic++ ]; break;\
69 case DOTACCESS : a = M[ display+M[ ic+1 ] ]+M[ ic ]; ic += 2; break;\
70 case NOARGUMENT : return; \
74 * Loads code and prototypes from files
75 * Files have following extensions:
76 * .ccd - compiler code
79 * @param _filename Filename of file to read.
81 static void load(char *_filename)
86 /* should suffice on all systems */
89 strcpy(filename, _filename);
90 /* allocate main memory array */
91 M = mallocate(memorysize + 1);
93 abend("Memory size too large (use /m option)\n");
95 addext(filename, ".ccd");
96 if ((fp = fopen(filename, BINARYREAD)) == NULL) {
97 fprintf(stderr, "Cannot open .ccd file\n");
101 /* read static data and code from .ccd file */
103 left = memorysize + 1;
106 abend("Memory size too small (use /m option)\n");
107 n = min(IOBLOCK / sizeof(word), left);
108 n = fread((char *) &M[ ic ], sizeof(word), (int) n, fp);
112 /* now ic = number of words read */
116 /* Get various addresses passed by GENERATOR */
118 /* primitive type desctriptions */
120 /* global temporary variables */
121 temporary = M[ic - 4];
122 /* string constants */
124 /* last prototype number */
125 lastprot = M[ic - 2];
126 /* first free word in memory */
129 /* Read prototypes from .pcd file */
130 addext(filename, ".pcd");
131 if ((fp = fopen(filename, BINARYREAD)) == NULL) {
132 fprintf(stderr,"Cannot open .pcd file\n");
135 for (n = MAINBLOCK; n <= lastprot; n++) {
136 cp = ballocate(sizeof(protdescr));
138 abend("Memory size too large (use /m option)\n");
139 prototype[n] = (protdescr *) cp;
141 if (fread(cp, sizeof(protdescr), 1, fp) != 1)
142 abend("Cannot read .pcd file\n");
146 /* Open trace file */
148 addext(filename, ".trd");
149 if ((tracefile = fopen(filename, "w")) == NULL)
150 abend("Cannot open .trd file\n");
155 * Establishes configuration parameters
156 * Creates two sockets for program run
158 static void initiate(int argc, char **argv)
168 if ((argc == 4) && (strcmp(argv[3], "r") == 0))
173 for(i = 0; i < 255; i++) {
181 strcpy(filename, argv[2]);
182 strcpy(ProgName, argv[2]);
184 strcpy(mynname, argv[1]);
185 strcat(mynname, ".net");
187 sock = socket(AF_UNIX, SOCK_STREAM, 0);
188 bzero(&svr, sizeof(svr));
189 svr.sun_family = AF_UNIX;
190 strcpy(svr.sun_path, mynname);
191 len = strlen(svr.sun_path) + sizeof(svr.sun_family);
192 bind(sock, (struct sockaddr*)&svr, len);
196 /* socket for graphic requests */
197 strcpy(mygname, argv[1]);
198 strcat(mygname, ".gr");
201 /* socket for KERNEL communication */
202 internal_sock = socket(AF_UNIX, SOCK_STREAM, 0);
203 bzero(&svr, sizeof(svr));
204 svr.sun_family = AF_UNIX;
205 strcpy(svr.sun_path, argv[1]);
206 strcpy(mykname, argv[1]);
207 len = strlen(svr.sun_path) + sizeof(svr.sun_family);
208 i = connect(internal_sock, (struct sockaddr*)&svr, len);
211 fcntl(internal_sock,F_SETFL, O_NONBLOCK |
212 fcntl(internal_sock,F_GETFL,0));
216 close(internal_sock);
217 internal_sock = socket(AF_UNIX, SOCK_STREAM, 0);
218 fcntl(internal_sock, F_SETFL, O_NONBLOCK |
219 fcntl(internal_sock, F_GETFL, 0));
220 i = connect(internal_sock, (struct sockaddr*)&svr, len);
223 setsockopt(internal_sock, IPPROTO_TCP, TCP_NODELAY, (char*)&on,
226 /* socket for network requests */
230 if (select(sock + 1, &rset, &wset, 0, 0))
231 net_sock = accept(sock, (struct sockaddr*)0, (int *)0);
234 fcntl(net_sock, F_SETFL, O_NONBLOCK |
235 fcntl(net_sock, F_GETFL, 0));
236 setsockopt(net_sock, IPPROTO_TCP, TCP_NODELAY, (char*)&on,
242 /* load code and prototypes */
243 if (filename != NULL)
255 /* pointer to extended opcode in M */
256 eop = (extopcode *)(M + ic);
257 /* save ic for possible redecoding */
260 opcode = ((int) eop->opcode ) & 0xFF ;
267 * Sends message to graph module.
268 * @param msg Message to send.
270 void send_to_graph(G_MESSAGE *msg)
272 write(graph_sock, msg, sizeof(G_MESSAGE));
276 * Reads message from graph module.
277 * @param msg Message to read.
279 int read_from_graph(G_MESSAGE *msg)
282 struct timeval tout = {0, 0};
286 FD_SET(graph_sock, &rset);
289 if (select(graph_sock + 1, &rset, &wset, 0, (struct timeval *)&tout) > 0) {
290 if (FD_ISSET(graph_sock, &rset))
291 return(read(graph_sock,msg,sizeof(G_MESSAGE)));
297 * Reads message from net module.
298 * @param msg Message to read.
300 int read_from_net(MESSAGE *msg)
303 struct timeval tout = {0, 0};
307 FD_SET(net_sock, &rset);
310 if (select(net_sock + 1, &rset, &wset, 0, (struct timeval *)&tout) > 0) {
311 if (FD_ISSET(net_sock, &rset))
312 return(read(net_sock, msg, sizeof(MESSAGE)));
319 * Gets graphic resource number
325 struct sockaddr_un svr;
330 sock = socket(AF_UNIX, SOCK_STREAM, 0);
331 bzero(&svr, sizeof(svr));
332 svr.sun_family = AF_UNIX;
333 strcpy(svr.sun_path, mygname);
334 len = strlen(svr.sun_path) + sizeof(svr.sun_family);
335 bind(sock, (struct sockaddr*)&svr, len);
339 msg.msg_type = MSG_GRAPH;
340 msg.param.pword[0] = GRAPH_ALLOCATE;
341 strcpy(msg.param.pstr, mygname);
342 write(internal_sock, &msg, sizeof(MESSAGE));
343 bzero(&msg, sizeof(MESSAGE));
347 if (select(sock+1, &rset, &wset, 0, 0))
348 graph_sock = accept(sock, (struct sockaddr*)0, (int*)0);
350 if (graph_sock == -1) {
356 fcntl(graph_sock, F_SETFL, O_NONBLOCK|fcntl(graph_sock, F_GETFL, 0));
357 setsockopt(graph_sock, IPPROTO_TCP, TCP_NODELAY, (char*)&on, sizeof(on));
364 * Writes string line (ended with new line character)
366 void writeln_str(char *s)
369 msg.msg_type = MSG_GRAPH;
370 msg.param.pword[1] = GraphRes;
371 msg.param.pword[2] = GRAPH_WRITE;
372 strcpy(msg.param.pstr, s);
375 strcpy(msg.param.pstr, "\n");
381 * @param s String to write
383 void write_str(char *s)
386 msg.msg_type = MSG_GRAPH;
387 msg.param.pword[1] = GraphRes;
388 msg.param.pword[0] = GRAPH_WRITE;
389 strcpy(msg.param.pstr, s);
395 * @param a Character to write
397 void write_char(char a)
401 msg.msg_type = MSG_GRAPH;
402 msg.param.pword[1] = GraphRes;
403 msg.param.pword[0] = GRAPH_PUTCHAR;
411 * @return Read character
419 msg.msg_type = MSG_GRAPH;
420 msg.param.pword[1] = GraphRes;
421 msg.param.pword[0] = GRAPH_READCHAR;
424 st = read_from_graph(&msg);
426 if ((msg.msg_type == MSG_GRAPH) &&
427 (msg.param.pword[0] == GRAPH_READCHAR_RESPONSE))
429 ch = msg.param.pchar;
446 msg.msg_type = MSG_GRAPH;
447 msg.param.pword[1] = GraphRes;
448 msg.param.pword[0] = GRAPH_READLN;
451 st = read_from_graph(&msg);
453 if ((msg.msg_type == MSG_GRAPH) &&
454 (msg.param.pword[0] == GRAPH_READLN_RESPONSE))
461 * @param s Buffer to store string.
463 void read_str(char *s)
469 msg.msg_type = MSG_GRAPH;
470 msg.param.pword[1] = GraphRes;
471 msg.param.pword[0] = GRAPH_READSTR;
474 st = read_from_graph(&msg);
476 if ((msg.msg_type == MSG_GRAPH) &&
477 (msg.param.pword[0] == GRAPH_READSTR_RESPONSE)) {
478 strcpy(ss, msg.param.pstr);
487 * Sends message to kernel
488 * @param msg Message to send to kernel
490 void send_to_kernel(MESSAGE *msg)
492 write(internal_sock, msg, sizeof(MESSAGE));
496 * Sends message to net
497 * @return Returns 1 if ok and 0 if node desn't exists (since 2010)
499 int send_to_net(MESSAGE *msg)
503 struct sockaddr_in svr;
507 k = msg->int_msg.control.receiver.node;
509 /* 2010 check if node exists */
510 m.msg_type = MSG_NET;
511 m.param.pword[0] = NET_NODE_EXIST;
512 m.param.pword[1] = k;
513 m.param.pword[2] = my_ctx.program_id;
514 write(net_sock, &m, sizeof(MESSAGE));
515 bzero(&m, sizeof(MESSAGE));
516 while((m.msg_type != MSG_NET) && (m.param.pword[0] != NET_NODE_EXIST))
517 read(net_sock, &m, sizeof(MESSAGE));
519 if (m.param.pword[1] != 1)
522 strcpy(addr, m.param.pstr);
524 if (RInstance[k] == -1) {
525 bzero(&m,sizeof(MESSAGE));
526 m.msg_type = MSG_VLP;
527 m.param.pword[0] = VLP_REMOTE_INSTANCE_PLEASE;
528 m.param.pword[1] = my_ctx.program_id;
529 m.param.pword[2] = k;
531 bzero(&m, sizeof(MESSAGE));
534 read(internal_sock, &m, sizeof(MESSAGE));
535 if ((m.msg_type == MSG_VLP) &&
536 (m.param.pword[0] == VLP_REMOTE_INSTANCE_HERE))
540 /*printf("DEBUG: remote instance made with id: "
541 "%d addr %s port %d\n", m.param.pword[1], addr,
542 htons(m.param.pword[8]));*/
543 RInstance[k] = m.param.pword[1];
544 /* Make direct connection */
545 DirConn[k] = socket(AF_INET, SOCK_STREAM, 0);
546 svr.sin_family = AF_INET;
547 svr.sin_addr.s_addr = inet_addr(addr);
548 svr.sin_port = htons(m.param.pword[8]);
549 len = connect(DirConn[k], (struct sockaddr*)&svr, sizeof(svr));
553 writeln_str("Cannot connect remote instance!");
555 fcntl(DirConn[k], F_SETFL, O_NONBLOCK |
556 fcntl(DirConn[k], F_GETFL, 0));
559 if (RInstance[k] != -1) {
560 write(DirConn[k], &(msg->int_msg), sizeof(message));
565 /* -------------------- Check for message on internal socket -------------*/
575 struct timeval tout = {0, 0};
578 /* ----------- Direct connection messages -----
581 for(i = 0; i < 255; i++)
582 if (DirConn[i]!=-1) {
583 FD_SET(DirConn[i], &DirSet);
584 if (maxDirSet<DirConn[i])
585 maxDirSet=DirConn[i];
588 if (select(maxDirSet + 1, &DirSet, 0, 0, (struct timeval *)&tout) > 0) {
589 for(i = 0; i < 255; i++) {
590 if ((DirConn[i] != -1) &&
591 (FD_ISSET(DirConn[i], &DirSet))) {
592 r = read(DirConn[i], &mx, sizeof(mx));
594 memcpy(globmsgqueue + msgtail,&mx,
596 msgtail = (msgtail + 1) % MAXMSGQUEUE;
602 -----------------------------------------*/
605 FD_SET(net_sock, &rset);
606 FD_SET(internal_sock, &rset);
607 if (net_sock > internal_sock)
612 for(i = 0; i < 255; i++) {
613 if (DirConn[i] != -1) {
614 FD_SET(DirConn[i], &rset);
615 if (max < DirConn[i])
620 if (select(max + 1, &rset, 0, 0, (struct timeval *)&tout) > 0) {
622 for(i = 0; i < 255; i++) {
623 if ((DirConn[i] != -1) && (FD_ISSET(DirConn[i], &rset))) {
625 printf("DEBUG: Interp has message on "
626 "direct connection: type %d par %d\n",
627 mx.control.type,mx.control.par);
629 r = read(DirConn[i], &mx, sizeof(mx));
630 if (r > 0 && r == sizeof(mx)) {
631 memcpy(globmsgqueue + msgtail, &mx,
633 msgtail = (msgtail+1) % MAXMSGQUEUE;
639 if (FD_ISSET(net_sock,&rset)) {
640 r = read(net_sock, &m, sizeof(MESSAGE));
645 switch(m.param.pword[0]) {
648 printf("DEBUG: cint net_sock MSG_NET "
649 "NET_PROPAGATE cmd %d\n",
651 memcpy(globmsgqueue + msgtail,
654 msgtail = (msgtail + 1) %
664 if (FD_ISSET(internal_sock, &rset)) {
665 r = read(internal_sock, &m, sizeof(MESSAGE));
670 switch(m.param.pword[0]) {
671 case INT_CLOSE_INSTANCE:
679 if (m.param.pword[0] == NET_PROPAGATE) {
681 printf("DEBUG: cint internal_sock MSG_NET NET_PROPAGATE cmd %d\n",m.param.pword[6]);*/
682 memcpy(globmsgqueue + msgtail,
685 msgtail = (msgtail+1) %
702 m.msg_type = MSG_INT;
703 m.param.pword[0] = INT_CTX_REQ;
705 while ((m.msg_type != MSG_INT) || (m.param.pword[0] != INT_CTX))
706 read(internal_sock, &m, sizeof(MESSAGE));
708 my_ctx.node = m.param.pword[1];
709 my_ctx.program_id = m.param.pword[2];
711 parent_ctx.node = m.param.pword[3];
712 parent_ctx.program_id = m.param.pword[4];
713 RInstance[parent_ctx.node] = parent_ctx.program_id;
715 parent_ctx.node = my_ctx.node;
716 parent_ctx.program_id = my_ctx.program_id;
718 ournode = my_ctx.node;
719 /* strcpy(nname,m.param.pstr);*/
720 /* net_sock = open(nname,O_WRONLY);*/
721 m1.msg_type = MSG_GRAPH;
722 m1.param.pword[0] = GRAPH_SET_TITLE;
723 m1.param.pword[1] = GraphRes;
724 sprintf(m1.param.pstr, "%s ID: %d", ProgName, my_ctx.program_id);
727 strcat(m1.param.pstr, " REMOTE instance");
735 struct sockaddr_in svr;
737 struct hostent *info;
740 msg.msg_type = MSG_NET;
741 msg.param.pword[0] = NET_PROPAGATE;
742 msg.param.pword[1] = MSG_VLP;
743 msg.param.pword[2] = my_ctx.node;
744 msg.param.pword[4] = parent_ctx.node;
745 msg.param.pword[6] = VLP_REMOTE_INSTANCE_OK;
746 msg.param.pword[7] = my_ctx.program_id;
748 sock = socket(AF_INET, SOCK_STREAM, 0);
749 bzero(&svr, sizeof(svr));
750 svr.sin_family = AF_INET;
751 svr.sin_addr.s_addr = INADDR_ANY;
753 bind(sock, (struct sockaddr*)&svr, sizeof(svr));
756 getsockname(sock,(struct sockaddr*)&svr, &len);
757 msg.param.pword[8] = ntohs(svr.sin_port);
758 gethostname(name, &len);
759 info = (struct hostent*)gethostbyname(name);
760 bcopy((char*)info->h_addr, (char*)&svr.sin_addr, info->h_length);
761 sprintf(msg.param.pstr, "%s", inet_ntoa(svr.sin_addr));
762 send_to_kernel(&msg);
764 bzero(&svr, sizeof(svr));
765 DirConn[parent_ctx.node] = accept(sock, (struct sockaddr*)&svr, &len);
766 fcntl(DirConn[parent_ctx.node], F_SETFL, O_NONBLOCK |
767 fcntl(DirConn[parent_ctx.node], F_GETFL, 0));
771 * strcpy(filename, argv[2]);
772 * strcpy(ProgName, argv[2]);
774 * argv[1] = base name of this interpreter instance.
775 * For network there is created argv[1].net socket
776 * For graphics there is created argv[1].gr socket
777 * argv[2] = up to 80 characters string (with terminating \0). It is used to
778 * load selected program
779 * argv[3] = if exists and is equal to 'r', this is a remote call
781 int main(int argc, char **argv)
783 /* initialize executor */
784 initiate(argc, argv);
785 /* initialize running system */
788 GraphRes = get_graph_res();
796 /* set label for continue long jump */
798 /* repeat until exit() is called */
801 /* reschedule current process */
804 /* fetch instruction */