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 fprintf(stderr, "logint: Reading static data from %s file\n", filename);
98 if ((fp = fopen(filename, BINARYREAD)) == NULL) {
99 fprintf(stderr, "Cannot open .ccd file\n");
103 /* read static data and code from .ccd file */
105 left = memorysize + 1;
108 abend("Memory size too small (use /m option)\n");
109 n = min(IOBLOCK / sizeof(word), left);
110 n = fread((char *) &M[ ic ], sizeof(word), (int) n, fp);
114 fprintf(stderr, "logint: Static data from %s file has been read\n", filename);
115 /* now ic = number of words read */
119 /* Get various addresses passed by GENERATOR */
121 /* primitive type desctriptions */
123 /* global temporary variables */
124 temporary = M[ic - 4];
125 /* string constants */
127 /* last prototype number */
128 lastprot = M[ic - 2];
129 /* first free word in memory */
132 /* Read prototypes from .pcd file */
133 addext(filename, ".pcd");
134 fprintf(stderr, "logint: Reading prototypes from %s file\n", filename);
135 if ((fp = fopen(filename, BINARYREAD)) == NULL) {
136 fprintf(stderr,"Cannot open .pcd file\n");
139 for (n = MAINBLOCK; n <= lastprot; n++) {
140 cp = ballocate(sizeof(protdescr));
142 abend("Memory size too large (use /m option)\n");
143 prototype[n] = (protdescr *) cp;
145 if (fread(cp, sizeof(protdescr), 1, fp) != 1)
146 abend("Cannot read .pcd file\n");
149 fprintf(stderr, "logint: Prototypes from: %s file has been read\n", filename);
151 /* Open trace file */
153 addext(filename, ".trd");
154 if ((tracefile = fopen(filename, "w")) == NULL)
155 abend("Cannot open .trd file\n");
160 * Establishes configuration parameters
161 * Creates two sockets for program run
163 * @param argc number of passed values in argv array
166 * @param argv[3] if value is equal to: "r", sets global #remote variable to
167 * TRUE, FALSE otherwise
169 static void initiate(int argc, char **argv)
179 if ((argc == 4) && (strcmp(argv[3], "r") == 0))
184 for(i = 0; i < 255; i++) {
192 strcpy(filename, argv[2]);
193 strcpy(ProgName, argv[2]);
195 strcpy(mynname, argv[1]);
196 strcat(mynname, ".net");
198 sock = socket(AF_UNIX, SOCK_STREAM, 0);
199 bzero(&svr, sizeof(svr));
200 svr.sun_family = AF_UNIX;
201 strcpy(svr.sun_path, mynname);
202 len = strlen(svr.sun_path) + sizeof(svr.sun_family);
203 fprintf(stderr, "logint: Binding to socket: %s\n", svr.sun_path);
204 bind(sock, (struct sockaddr*)&svr, len);
208 /* socket for graphic requests */
209 strcpy(mygname, argv[1]);
210 strcat(mygname, ".gr");
213 /* socket for KERNEL communication */
214 internal_sock = socket(AF_UNIX, SOCK_STREAM, 0);
215 bzero(&svr, sizeof(svr));
216 svr.sun_family = AF_UNIX;
217 strcpy(svr.sun_path, argv[1]);
218 strcpy(mykname, argv[1]);
219 len = strlen(svr.sun_path) + sizeof(svr.sun_family);
220 fprintf(stderr, "logint: Connecting to socket: %s\n", svr.sun_path);
221 i = connect(internal_sock, (struct sockaddr*)&svr, len);
224 fcntl(internal_sock,F_SETFL, O_NONBLOCK |
225 fcntl(internal_sock,F_GETFL,0));
229 close(internal_sock);
230 internal_sock = socket(AF_UNIX, SOCK_STREAM, 0);
231 fcntl(internal_sock, F_SETFL, O_NONBLOCK |
232 fcntl(internal_sock, F_GETFL, 0));
233 i = connect(internal_sock, (struct sockaddr*)&svr, len);
237 setsockopt(internal_sock, IPPROTO_TCP, TCP_NODELAY, (char*)&on,
240 /* socket for network requests */
244 if (select(sock + 1, &rset, &wset, 0, 0))
245 net_sock = accept(sock, (struct sockaddr*)0, (int *)0);
248 fcntl(net_sock, F_SETFL, O_NONBLOCK |
249 fcntl(net_sock, F_GETFL, 0));
250 setsockopt(net_sock, IPPROTO_TCP, TCP_NODELAY, (char*)&on,
256 /* load code and prototypes */
257 if (filename != NULL) {
258 fprintf(stderr, "logint: loading code: %s\n", filename);
272 /* pointer to extended opcode in M */
273 eop = (extopcode *)(M + ic);
274 /* save ic for possible redecoding */
277 opcode = ((int) eop->opcode ) & 0xFF ;
284 * Sends message to graph module.
285 * @param msg Message to send.
287 void send_to_graph(G_MESSAGE *msg)
289 write(graph_sock, msg, sizeof(G_MESSAGE));
293 * Reads message from graph module.
294 * @param msg Message to read.
296 int read_from_graph(G_MESSAGE *msg)
299 struct timeval tout = {0, 0};
303 FD_SET(graph_sock, &rset);
306 if (select(graph_sock + 1, &rset, &wset, 0, (struct timeval *)&tout) > 0) {
307 if (FD_ISSET(graph_sock, &rset))
308 return(read(graph_sock,msg,sizeof(G_MESSAGE)));
314 * Reads message from net module.
316 * @param msg Message to read.
318 int read_from_net(MESSAGE *msg)
321 struct timeval tout = {0, 0};
325 FD_SET(net_sock, &rset);
328 if (select(net_sock + 1, &rset, &wset, 0, (struct timeval *)&tout) > 0) {
329 if (FD_ISSET(net_sock, &rset))
330 return(read(net_sock, msg, sizeof(MESSAGE)));
337 * Gets graphic resource number
343 struct sockaddr_un svr;
348 sock = socket(AF_UNIX, SOCK_STREAM, 0);
349 bzero(&svr, sizeof(svr));
350 svr.sun_family = AF_UNIX;
351 strcpy(svr.sun_path, mygname);
352 len = strlen(svr.sun_path) + sizeof(svr.sun_family);
353 bind(sock, (struct sockaddr*)&svr, len);
357 msg.msg_type = MSG_GRAPH;
358 msg.param.pword[0] = GRAPH_ALLOCATE;
359 strcpy(msg.param.pstr, mygname);
360 write(internal_sock, &msg, sizeof(MESSAGE));
361 bzero(&msg, sizeof(MESSAGE));
365 if (select(sock+1, &rset, &wset, 0, 0))
366 graph_sock = accept(sock, (struct sockaddr*)0, (int*)0);
368 if (graph_sock == -1) {
374 fcntl(graph_sock, F_SETFL, O_NONBLOCK|fcntl(graph_sock, F_GETFL, 0));
375 setsockopt(graph_sock, IPPROTO_TCP, TCP_NODELAY, (char*)&on, sizeof(on));
382 * Writes string line (ended with new line character)
384 void writeln_str(char *s)
387 msg.msg_type = MSG_GRAPH;
388 msg.param.pword[1] = GraphRes;
389 msg.param.pword[2] = GRAPH_WRITE;
390 strcpy(msg.param.pstr, s);
393 strcpy(msg.param.pstr, "\n");
400 * Passed string is send to graph module by G_MESSAGE packet using send_to_graph
402 * @param s String to write
404 void write_str(char *s)
407 msg.msg_type = MSG_GRAPH;
408 msg.param.pword[1] = GraphRes;
409 msg.param.pword[0] = GRAPH_WRITE;
410 strcpy(msg.param.pstr, s);
417 * Passed char is send to graph module by G_MESSAGE packet using send_to_graph
419 * @param a Character to write
421 void write_char(char a)
425 msg.msg_type = MSG_GRAPH;
426 msg.param.pword[1] = GraphRes;
427 msg.param.pword[0] = GRAPH_PUTCHAR;
435 * @return Read character
443 msg.msg_type = MSG_GRAPH;
444 msg.param.pword[1] = GraphRes;
445 msg.param.pword[0] = GRAPH_READCHAR;
448 st = read_from_graph(&msg);
450 if ((msg.msg_type == MSG_GRAPH) &&
451 (msg.param.pword[0] == GRAPH_READCHAR_RESPONSE))
453 ch = msg.param.pchar;
470 msg.msg_type = MSG_GRAPH;
471 msg.param.pword[1] = GraphRes;
472 msg.param.pword[0] = GRAPH_READLN;
475 st = read_from_graph(&msg);
477 if ((msg.msg_type == MSG_GRAPH) &&
478 (msg.param.pword[0] == GRAPH_READLN_RESPONSE))
485 * @param s Buffer to store string.
487 void read_str(char *s)
493 msg.msg_type = MSG_GRAPH;
494 msg.param.pword[1] = GraphRes;
495 msg.param.pword[0] = GRAPH_READSTR;
498 st = read_from_graph(&msg);
500 if ((msg.msg_type == MSG_GRAPH) &&
501 (msg.param.pword[0] == GRAPH_READSTR_RESPONSE)) {
502 strcpy(ss, msg.param.pstr);
511 * Sends message to kernel
512 * @param msg Message to send to kernel
514 void send_to_kernel(MESSAGE *msg)
516 write(internal_sock, msg, sizeof(MESSAGE));
520 * Sends message to net
521 * @return Returns 1 if ok and 0 if node desn't exists (since 2010)
523 int send_to_net(MESSAGE *msg)
527 struct sockaddr_in svr;
531 k = msg->int_msg.control.receiver.node;
533 /* 2010 check if node exists */
534 m.msg_type = MSG_NET;
535 m.param.pword[0] = NET_NODE_EXIST;
536 m.param.pword[1] = k;
537 m.param.pword[2] = my_ctx.program_id;
538 write(net_sock, &m, sizeof(MESSAGE));
539 bzero(&m, sizeof(MESSAGE));
540 while((m.msg_type != MSG_NET) && (m.param.pword[0] != NET_NODE_EXIST))
541 read(net_sock, &m, sizeof(MESSAGE));
543 if (m.param.pword[1] != 1)
546 strcpy(addr, m.param.pstr);
548 if (RInstance[k] == -1) {
549 bzero(&m,sizeof(MESSAGE));
550 m.msg_type = MSG_VLP;
551 m.param.pword[0] = VLP_REMOTE_INSTANCE_PLEASE;
552 m.param.pword[1] = my_ctx.program_id;
553 m.param.pword[2] = k;
555 bzero(&m, sizeof(MESSAGE));
558 read(internal_sock, &m, sizeof(MESSAGE));
559 if ((m.msg_type == MSG_VLP) &&
560 (m.param.pword[0] == VLP_REMOTE_INSTANCE_HERE))
564 /*printf("DEBUG: remote instance made with id: "
565 "%d addr %s port %d\n", m.param.pword[1], addr,
566 htons(m.param.pword[8]));*/
567 RInstance[k] = m.param.pword[1];
568 /* Make direct connection */
569 DirConn[k] = socket(AF_INET, SOCK_STREAM, 0);
570 svr.sin_family = AF_INET;
571 svr.sin_addr.s_addr = inet_addr(addr);
572 svr.sin_port = htons(m.param.pword[8]);
573 len = connect(DirConn[k], (struct sockaddr*)&svr, sizeof(svr));
577 writeln_str("Cannot connect remote instance!");
579 fcntl(DirConn[k], F_SETFL, O_NONBLOCK |
580 fcntl(DirConn[k], F_GETFL, 0));
583 if (RInstance[k] != -1) {
584 write(DirConn[k], &(msg->int_msg), sizeof(message));
589 /* -------------------- Check for message on internal socket -------------*/
599 struct timeval tout = {0, 0};
602 /* ----------- Direct connection messages -----
605 for(i = 0; i < 255; i++)
606 if (DirConn[i]!=-1) {
607 FD_SET(DirConn[i], &DirSet);
608 if (maxDirSet<DirConn[i])
609 maxDirSet=DirConn[i];
612 if (select(maxDirSet + 1, &DirSet, 0, 0, (struct timeval *)&tout) > 0) {
613 for(i = 0; i < 255; i++) {
614 if ((DirConn[i] != -1) &&
615 (FD_ISSET(DirConn[i], &DirSet))) {
616 r = read(DirConn[i], &mx, sizeof(mx));
618 memcpy(globmsgqueue + msgtail,&mx,
620 msgtail = (msgtail + 1) % MAXMSGQUEUE;
626 -----------------------------------------*/
629 FD_SET(net_sock, &rset);
630 FD_SET(internal_sock, &rset);
631 if (net_sock > internal_sock)
636 for(i = 0; i < 255; i++) {
637 if (DirConn[i] != -1) {
638 FD_SET(DirConn[i], &rset);
639 if (max < DirConn[i])
644 if (select(max + 1, &rset, 0, 0, (struct timeval *)&tout) > 0) {
646 for(i = 0; i < 255; i++) {
647 if ((DirConn[i] != -1) && (FD_ISSET(DirConn[i], &rset))) {
649 printf("DEBUG: Interp has message on "
650 "direct connection: type %d par %d\n",
651 mx.control.type,mx.control.par);
653 r = read(DirConn[i], &mx, sizeof(mx));
654 if (r > 0 && r == sizeof(mx)) {
655 memcpy(globmsgqueue + msgtail, &mx,
657 msgtail = (msgtail+1) % MAXMSGQUEUE;
663 if (FD_ISSET(net_sock,&rset)) {
664 r = read(net_sock, &m, sizeof(MESSAGE));
669 switch(m.param.pword[0]) {
672 printf("DEBUG: cint net_sock MSG_NET "
673 "NET_PROPAGATE cmd %d\n",
675 memcpy(globmsgqueue + msgtail,
678 msgtail = (msgtail + 1) %
688 if (FD_ISSET(internal_sock, &rset)) {
689 r = read(internal_sock, &m, sizeof(MESSAGE));
694 switch(m.param.pword[0]) {
695 case INT_CLOSE_INSTANCE:
703 if (m.param.pword[0] == NET_PROPAGATE) {
705 printf("DEBUG: cint internal_sock MSG_NET NET_PROPAGATE cmd %d\n",m.param.pword[6]);*/
706 memcpy(globmsgqueue + msgtail,
709 msgtail = (msgtail+1) %
726 m.msg_type = MSG_INT;
727 m.param.pword[0] = INT_CTX_REQ;
729 while ((m.msg_type != MSG_INT) || (m.param.pword[0] != INT_CTX))
730 read(internal_sock, &m, sizeof(MESSAGE));
732 my_ctx.node = m.param.pword[1];
733 my_ctx.program_id = m.param.pword[2];
735 parent_ctx.node = m.param.pword[3];
736 parent_ctx.program_id = m.param.pword[4];
737 RInstance[parent_ctx.node] = parent_ctx.program_id;
739 parent_ctx.node = my_ctx.node;
740 parent_ctx.program_id = my_ctx.program_id;
742 ournode = my_ctx.node;
743 /* strcpy(nname,m.param.pstr);*/
744 /* net_sock = open(nname,O_WRONLY);*/
745 m1.msg_type = MSG_GRAPH;
746 m1.param.pword[0] = GRAPH_SET_TITLE;
747 m1.param.pword[1] = GraphRes;
748 sprintf(m1.param.pstr, "%s ID: %d", ProgName, my_ctx.program_id);
751 strcat(m1.param.pstr, " REMOTE instance");
761 struct sockaddr_in svr;
763 struct hostent *info;
766 msg.msg_type = MSG_NET;
767 msg.param.pword[0] = NET_PROPAGATE;
768 msg.param.pword[1] = MSG_VLP;
769 msg.param.pword[2] = my_ctx.node;
770 msg.param.pword[4] = parent_ctx.node;
771 msg.param.pword[6] = VLP_REMOTE_INSTANCE_OK;
772 msg.param.pword[7] = my_ctx.program_id;
774 sock = socket(AF_INET, SOCK_STREAM, 0);
775 bzero(&svr, sizeof(svr));
776 svr.sin_family = AF_INET;
777 svr.sin_addr.s_addr = INADDR_ANY;
779 bind(sock, (struct sockaddr*)&svr, sizeof(svr));
782 getsockname(sock,(struct sockaddr*)&svr, &len);
783 msg.param.pword[8] = ntohs(svr.sin_port);
784 gethostname(name, &len);
785 info = (struct hostent*)gethostbyname(name);
786 bcopy((char*)info->h_addr, (char*)&svr.sin_addr, info->h_length);
787 sprintf(msg.param.pstr, "%s", inet_ntoa(svr.sin_addr));
788 send_to_kernel(&msg);
790 bzero(&svr, sizeof(svr));
791 DirConn[parent_ctx.node] = accept(sock, (struct sockaddr*)&svr, &len);
792 fcntl(DirConn[parent_ctx.node], F_SETFL, O_NONBLOCK |
793 fcntl(DirConn[parent_ctx.node], F_GETFL, 0));
797 * strcpy(filename, argv[2]);
798 * strcpy(ProgName, argv[2]);
800 * @param argv[1] = base name of this interpreter instance.
801 * For network there is created argv[1].net socket
802 * For graphics there is created argv[1].gr socket
803 * @param argv[2] = up to 80 characters string (with terminating \0). It is used to
804 * load selected program
805 * @param argv[3] = if exists and is equal to 'r', this is a remote call
807 int main(int argc, char **argv)
809 fprintf(stderr, "logint: initializing\n");
810 /* initialize executor */
811 initiate(argc, argv);
812 /* initialize running system */
813 fprintf(stderr, "logint: runsys\n");
815 fprintf(stderr, "logint: initializing scheduler\n");
817 fprintf(stderr, "logint: acquiring GRAPH resource\n");
818 GraphRes = get_graph_res();
820 fprintf(stderr, "logint: > acquiring GRAPH resource failed\n");
828 /* set label for continue long jump */
830 /* repeat until exit() is called */
833 /* reschedule current process */
836 /* fetch instruction */