1 /*
2 Copyright (c) 1991-2002, The Numerical ALgorithms Group Ltd.
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
8
9 - Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11
12 - Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in
14 the documentation and/or other materials provided with the
15 distribution.
16
17 - Neither the name of The Numerical ALgorithms Group Ltd. nor the
18 names of its contributors may be used to endorse or promote products
19 derived from this software without specific prior written permission.
20
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
22 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
25 OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 /* Still a problem with close_client */
35
36 /* Communication interface for external FriCAS buffers */
37
38 #include "fricas_c_macros.h"
39 #include "debug.h"
40
41 #include <signal.h>
42
43 #include "hyper.h"
44 #include "parse.h"
45 #include "bsdsignal.h"
46
47 #include "all_hyper_proto.H1"
48 #include "sockio-c.H1"
49 #include "bsdsignal.H1"
50
51 static void start_user_buffer(HyperDocPage * page);
52 static void clear_execution_marks(HashTable * depend_hash);
53 static void issue_dependent_commands(HyperDocPage * page, TextNode * command,
54 int type);
55 static void send_pile(Sock * sock, char * str);
56 static void mark_as_executed(HyperDocPage * page, TextNode * command,
57 int type);
58 static void accept_menu_server_connection(HyperDocPage * page);
59 static void switch_frames(void);
60 static void close_client(int pid);
61
62 typedef struct sock_list { /* linked list of Sock */
63 Sock Socket;
64 struct sock_list *next;
65 } Sock_List;
66
67 Sock_List *plSock = (Sock_List *) 0;
68 Sock *spad_socket = (Sock *) 0; /* to_server socket for SpadServer */
69
70 char *p2sBuf = NULL;
71 int p2sBufSize = 0;
72
73 /* issue a FriCAS command to the buffer associated with a page */
74 void
issue_spadcommand(HyperDocPage * page,TextNode * command,int immediate,int type)75 issue_spadcommand(HyperDocPage *page, TextNode *command, int immediate,
76 int type)
77 {
78 char *buf;
79 int ret_val;
80
81 ret_val = connect_spad();
82 if (ret_val == NotConnected || ret_val == SpadBusy)
83 return;
84
85 if (page->sock == NULL)
86 start_user_buffer(page);
87 ret_val = send_int(page->sock, TestLine);
88 if (ret_val == -1) {
89 page->sock = NULL;
90 clear_execution_marks(page->depend_hash);
91 issue_spadcommand(page, command, immediate, type);
92 return;
93 }
94 issue_dependent_commands(page, command, type);
95 ret_val = send_int(page->sock, ReceiveInputLine);
96 buf = print_to_string(command);
97 if (immediate) {
98 int len = strlen(buf);
99 buf = p2sBuf = resizeBuffer(len + 2, p2sBuf, &p2sBufSize);
100 buf[len + 1] = '\0';
101 buf[len] = '\n';
102 }
103 if (type == Spadsrc)
104 send_pile(page->sock, buf);
105 else
106 send_string(page->sock, buf);
107 mark_as_executed(page, command, type);
108 gIsEndOfOutput = 0;
109 }
110 static void
send_pile(Sock * sock,char * str)111 send_pile(Sock *sock,char * str)
112 {
113 FILE *f;
114 char name[512], command[512];
115
116 sprintf(name, "/tmp/hyper%s.input", getenv("SPADNUM"));
117 f = fopen(name, "w");
118 if (f == NULL) {
119 fprintf(stderr, "Can't open temporary input file %s\n", name);
120 return;
121 }
122 fprintf(f, "%s", str);
123 fclose(f);
124 sprintf(command, ")read %s\n", name);
125 send_string(sock, command);
126 }
127 static void
issue_dependent_commands(HyperDocPage * page,TextNode * command,int type)128 issue_dependent_commands(HyperDocPage *page, TextNode *command,int type)
129 {
130 TextNode *node, *depend_label;
131 SpadcomDepend *depend;
132 int end_type = (type == Spadcommand || type == Spadgraph) ?
133 (Endspadcommand) : (Endspadsrc);
134
135 for (node = command->next; node->type != end_type;
136 node = node->next)
137 if (node->type == Free)
138 for (depend_label = node->data.node; depend_label != NULL;
139 depend_label = depend_label->next)
140 if (depend_label->type == Word) {
141 depend = (SpadcomDepend *)
142 hash_find(page->depend_hash, depend_label->data.text);
143 if (depend == NULL) {
144 fprintf(stderr, "Error: dependency on undefined label: %s\n",
145 depend_label->data.text);
146 continue;
147 }
148 if (!depend->executed) {
149 issue_spadcommand(page, depend->spadcom->next, 1,
150 depend->spadcom->type);
151 while (!gIsEndOfOutput)
152 pause();
153 fricas_sleep(100);
154 }
155 }
156 }
157 static void
mark_as_executed(HyperDocPage * page,TextNode * command,int type)158 mark_as_executed(HyperDocPage *page, TextNode *command,int type)
159 {
160 TextNode *node, *depend_label;
161 SpadcomDepend *depend;
162 int end_type = (type == Spadcommand || type == Spadgraph)
163 ? (Endspadcommand) : (Endspadsrc);
164
165 for (node = command; node->type != end_type; node = node->next)
166 if (node->type == Bound)
167 for (depend_label = node->data.node; depend_label != NULL;
168 depend_label = depend_label->next)
169 if (depend_label->type == Word) {
170 depend = (SpadcomDepend *)
171 hash_find(page->depend_hash, depend_label->data.text);
172 if (depend == NULL) {
173 fprintf(stderr, "No dependency entry for label: %s\n",
174 depend_label->data.text);
175 continue;
176 }
177 depend->executed = 1;
178 }
179 }
180
181 /* start a spad buffer for the page associated with the give */
182 static void
start_user_buffer(HyperDocPage * page)183 start_user_buffer(HyperDocPage *page)
184 {
185 char buf[1024], *title;
186 char *SPAD;
187 char spadbuf[250];
188 char complfile[250];
189 int ret_val;
190
191 SPAD = (char *) getenv("FRICAS");
192 if (SPAD == NULL) {
193 fprintf(stderr, "start_user_buffer: $FRICAS is empty\n");
194 exit(-1);
195 }
196 sprintf(spadbuf, "%s/lib/spadbuf", SPAD);
197 sprintf(complfile, "%s/lib/command.list", SPAD);
198 title = print_to_string(page->title);
199 if (access(complfile, R_OK) == 0)
200
201 /*
202 * TTT says : why not invoke with "-name fricasclient" and set any
203 * defaults in the usual way
204 */
205 sprintf(buf,
206 "xterm -sb -sl 500 -name fricasclient -n '%s' -T '%s' -e %s %s %s&",
207 title, title, spadbuf, page->name, complfile);
208 else
209 sprintf(buf,
210 "xterm -sb -sl 500 -name fricasclient -n '%s' -T '%s' -e %s '%s'&",
211 title, title, spadbuf, page->name);
212 ret_val = system(buf);
213 if (ret_val == -1 || ret_val == 127) {
214
215 /*
216 * perror("running the xterm spadbuf program"); exit(-1);
217 */
218 }
219 accept_menu_server_connection(page);
220 fricas_sleep(100);
221 }
222
223 /* Clears the execution marks in a hash table when a buffer has been killed */
224 static void
clear_execution_marks(HashTable * depend_hash)225 clear_execution_marks(HashTable *depend_hash)
226 {
227 int i;
228 HashEntry *h;
229 SpadcomDepend *depend;
230
231 if (depend_hash == 0)
232 return;
233 for (i = 0; i < depend_hash->size; i++)
234 for (h = depend_hash->table[i]; h != NULL; h = h->next) {
235 depend = (SpadcomDepend *) h->data;
236 depend->executed = 0;
237 }
238 }
239
240 Sock *
accept_menu_connection(Sock * server_sock)241 accept_menu_connection(Sock *server_sock)
242 {
243 int sock_fd /*, session, ret_code*/;
244 Sock_List *pls;
245 /*Sock local_sock;*/
246
247 /* Could only be InterpWindow */
248
249 pls = (Sock_List *) halloc(sizeof(Sock_List),"SockList");
250 sock_fd = accept(server_sock->socket, 0, 0);
251 if (sock_fd == -1) {
252 perror("session : accepting connection");
253 return 0;
254 }
255 (pls->Socket).socket = sock_fd;
256 get_socket_type((Sock *) pls);
257
258 #ifdef DEBUG
259 fprintf(stderr,
260 "session: accepted InterpWindow , fd = %d\n", sock_fd);
261 #endif
262
263
264 /* put new item at head of list */
265
266 if (plSock == (Sock_List *) 0) {
267 plSock = pls;
268 plSock->next = (Sock_List *) 0;
269 }
270 else {
271 pls->next = plSock;
272 plSock = pls;
273 }
274
275 /* need to maintain socket_mask since we roll our own accept */
276
277 FD_SET(plSock->Socket.socket, &socket_mask);
278 return (Sock *) plSock;
279 }
280
281 static void
accept_menu_server_connection(HyperDocPage * page)282 accept_menu_server_connection(HyperDocPage *page)
283 {
284
285 /*
286 * TTT thinks this code should just provide a Sock to the page. The only
287 * client assumed is a spadbuf. Since spadbuf was invoked with the page
288 * name, it just passes it back here as a check (get_string line).
289 */
290 int ret_code/*, i*/;
291 fd_set rd;
292 Sock *sock;
293 char *buf_name;
294 HyperDocPage *npage;
295
296 if (page->sock != NULL)
297 return;
298 while (1) {
299 rd = server_mask;
300 ret_code = sselect(FD_SETSIZE, &rd, 0, 0, NULL);
301 if (ret_code == -1) {
302 perror("Session manager select");
303 continue;
304 }
305
306 if (server[1].socket > 0 && FD_ISSET(server[1].socket, &rd)) {
307 sock = accept_menu_connection(server + 1);
308 if (sock == 0)
309 return;
310 if (sock->purpose == InterpWindow) {
311 buf_name = get_string(sock);
312 npage = (HyperDocPage *)
313 hash_find(gWindow->fPageHashTable, buf_name);
314 if (npage == NULL) {
315
316 /*
317 * Lets just try using the current page TTT doesn't know
318 * why this could be detrimental
319 *
320 * fprintf(stderr, "connecting spadbuf to unknown page:
321 * %s\n", buf_name);
322 */
323 page->sock = sock;
324 return;
325 }
326 else {
327
328 /*
329 * For some reason npage and page may be different TTT
330 * thinks this happens when a dynamic page has the same
331 * name as an existing static page.
332 */
333 npage->sock = sock;
334 page->sock = sock;
335 }
336 if (!strcmp(buf_name, page->name)) {
337 return;
338 }
339 }
340 }
341 }
342 }
343
344
345 /*
346 * This procedure takes a HyperDoc node, and expands it into string
347 */
348
349 /*
350 * This routine takes a text node and creates a string out of it. This is for
351 * use with things such as spad commands. There are a very limited set of
352 * node types it can handle, so be careful
353 */
354
355 char *
print_to_string(TextNode * command)356 print_to_string(TextNode *command)
357 {
358 int len = 0;
359
360 print_to_string1(command, &len);
361 p2sBuf = resizeBuffer(len, p2sBuf, &p2sBufSize);
362 return print_to_string1(command, NULL);
363 }
364
365 /*
366 see the code in ht-util.boot
367 $funnyQuote := char 127
368 $funnyBacks := char 128
369 */
370 #define funnyEscape(c) ((c) == '"' ? '\177' : ((c) == '\\' ? '\200' : c))
371 #define funnyUnescape(c) ((c) == '\177' ? '"' : ((c) == '\200' ? '\\' : c))
372 #define storeChar(ch) \
373 do { if (sizeBuf) { (*sizeBuf)++;} else {*c++ = (ch);} } while(0)
374 #define storeString(str) for (s=str;*s;s++) {storeChar(*s);}
375
376 extern int include_bf;
377
378 char *
print_to_string1(TextNode * command,int * sizeBuf)379 print_to_string1(TextNode *command,int * sizeBuf)
380 {
381 char *c = p2sBuf;
382 char *s;
383 InputItem *item;
384 LineStruct *curr_line;
385 int lcount;
386 InputBox *box;
387 int num_spaces;
388 int count;
389 TextNode *node;
390
391 /*
392 * Init the stack of text nodes, things are pushed on here when I trace
393 * through a nodes data.node. This way we always know where the next is.
394 */
395
396 for (node = command; node != NULL;) {
397 switch (node->type) {
398 case Newline:
399 storeChar('\n');
400 node = node->next;
401 break;
402 case Ifcond:
403 if (check_condition(node->data.ifnode->cond))
404 node = node->data.ifnode->thennode;
405 else
406 node = node->data.ifnode->elsenode;
407 break;
408 case Endarg:
409 case Endspadcommand:
410 case Endspadsrc:
411 case Endpix:
412 storeChar('\0');
413 return p2sBuf;
414 case Endverbatim:
415 case Endif:
416 case Fi:
417 case Endmacro:
418 case Endparameter:
419 case Rbrace:
420 case Endgroup:
421 node = node->next;
422 break;
423 case Punctuation:
424
425 /*
426 * Simply copy the piece of text
427 */
428 if (node->space & FRONTSPACE) { storeChar(' '); }
429 for (s = node->data.text; *s; s++) { storeChar(*s); }
430 node = node->next;
431 break;
432 case WindowId:
433
434 /*
435 * Simply copy the piece of text
436 */
437 if (node->space) { storeChar(' '); }
438 for (s = node->data.text; *s; s++) { storeChar(*s); }
439 storeChar(' ');
440 node = node->next;
441 break;
442 case Verbatim:
443 case Spadsrctxt:
444
445 /*
446 * Simply copy the piece of text
447 */
448 if (node->space) { storeChar(' '); }
449 for (s = node->data.text; *s; s++) { storeChar(*s); }
450
451 /*
452 * now add the eol
453 */
454
455 /*
456 * if(node->next && node->next->type != Endspadsrc)
457 * storeChar('\n');
458 */
459 node = node->next;
460 break;
461 case Dash:
462 case Rsquarebrace:
463 case Lsquarebrace:
464 case Word:
465
466 /*
467 * Simply copy the piece of text
468 */
469 if (node->space) { storeChar(' '); }
470 for (s = node->data.text; *s; s++) { storeChar(*s); }
471 node = node->next;
472 break;
473 case BoxValue:
474 box =
475 (InputBox *) hash_find(gWindow->page->box_hash, node->data.text);
476 if (box == NULL) {
477 fprintf(stderr,
478 "Print_to_string:Box %s Has no symbol table entry\n",
479 node->data.text);
480 exit(-1);
481 }
482 storeChar(' ');
483 if (box->picked) {
484 storeChar('t');
485 }
486 else {
487 storeChar('n');
488 storeChar('i');
489 storeChar('l');
490 }
491 node = node->next;
492 break;
493 case StringValue:
494 item = return_item(node->data.text);
495 if (item != NULL) {
496 if (node->space)
497 storeChar(' ');
498 curr_line = item->lines;
499 while (curr_line != NULL) {
500 for (lcount = 0, s = curr_line->buffer; *s && lcount < item->size;
501 s++, lcount++) {
502 storeChar(funnyEscape(*s));
503 }
504 if (curr_line->len <= item->size && curr_line->next)
505 storeChar('\n');
506 curr_line = curr_line->next;
507 }
508 }
509 else if ((box = (InputBox *) hash_find(gWindow->page->box_hash,
510 node->data.text)) != NULL) {
511 if (node->space) { storeChar(' '); }
512 if (box->picked) {
513 storeChar('t');
514 }
515 else {
516 storeChar('n');
517 storeChar('i');
518 storeChar('l');
519 }
520 }
521 else {
522 fprintf(stderr, "Error, Symbol %s has no symbol table entry\n",
523 node->data.text);
524 exit(-1);
525 }
526 node = node->next;
527 break;
528 case Space:
529 num_spaces = (node->data.node != NULL ?
530 atoi(node->data.node->data.text) : 1);
531 for (count = 0; count < num_spaces; count++)
532 storeChar(' ');
533 node = node->next;
534 break;
535 case Titlenode:
536 case Endtitle:
537 case Center:
538 case Endcenter:
539 case BoldFace:
540 case Emphasize:
541 case Indentrel:
542 node = node->next;
543 break;
544 case Bound:
545 if (include_bf) {
546 int len, i;
547 TextNode *n2 = node->data.node;
548
549 storeChar('\\');
550 storeChar('b');
551 storeChar('o');
552 storeChar('u');
553 storeChar('n');
554 storeChar('d');
555 storeChar('{');
556 for (; n2->type != Endarg; n2 = n2->next) {
557 if (n2->type == Word) {
558 len = strlen(n2->data.text);
559 for (i = 0; i < len; i++)
560 storeChar(n2->data.text[i]);
561 storeChar(' ');
562 }
563 }
564 storeChar('}');
565 }
566 node = node->next;
567 break;
568 case Free:
569 if (include_bf) {
570 int len, i;
571 TextNode *n2 = node->data.node;
572
573 storeChar('\\');
574 storeChar('f');
575 storeChar('r');
576 storeChar('e');
577 storeChar('e');
578 storeChar('{');
579 for (; n2->type != Endarg; n2 = n2->next) {
580 if (n2->type == Word) {
581 len = strlen(n2->data.text);
582 for (i = 0; i < len; i++)
583 storeChar(n2->data.text[i]);
584 storeChar(' ');
585 }
586 }
587 storeChar('}');
588 }
589 node = node->next;
590 break;
591 case Macro:
592 node = node->next;
593 break;
594 case Pound:
595 if (node->space) { storeChar(' '); }
596 node = node->next;
597 break;
598 case Group:
599 node = node->next;
600 break;
601 case Indent:
602 num_spaces = (node->data.node != NULL ?
603 atoi(node->data.node->data.text) : 1);
604 for (count = 0; count < num_spaces; count++)
605 storeChar(' ');
606 node = node->next;
607 break;
608 default:
609 fprintf(stderr,
610 "Print_to_string: Unrecognized Keyword Type %d\n",
611 node->type);
612 node=node->next;
613 break;
614 }
615 }
616 storeChar('\0');
617 return p2sBuf;
618 }
619
620 /*
621 * Send a lisp or spad command to the FriCAS server for execution , if
622 * type is link, then we wait for a HyperDoc card to be returned
623 */
624
625 HyperDocPage *
issue_server_command(HyperLink * link)626 issue_server_command(HyperLink *link)
627 {
628 TextNode *command = (TextNode *) link->reference.node;
629 int ret_val;
630 char *buf;
631 HyperDocPage *page;
632
633 ret_val = connect_spad();
634 if (ret_val == NotConnected) {
635 page = (HyperDocPage *) hash_find(gWindow->fPageHashTable, "SpadNotConnectedPage");
636 if (page == NULL)
637 fprintf(stderr, "No SpadNotConnectedPage found\n");
638 return page;
639 }
640 if (ret_val == SpadBusy) {
641 page = (HyperDocPage *) hash_find(gWindow->fPageHashTable, "SpadBusyPage");
642 if (page == NULL)
643 fprintf(stderr, "No SpadBusyPage found\n");
644 return page;
645 }
646 switch_frames();
647 switch (link->type) {
648 case Qspadcall:
649 case Qspadcallquit:
650 case Spadlink:
651 case Spaddownlink:
652 case Spadmemolink:
653 send_int(spad_socket, QuietSpadCommand);
654 break;
655 case Spadcall:
656 case Spadcallquit:
657 send_int(spad_socket, SpadCommand);
658 break;
659 default:
660 send_int(spad_socket, LispCommand);
661 break;
662 }
663 buf = print_to_string(command);
664 send_string(spad_socket, buf);
665 if (link->type == Lispcommand || link->type == Spadcall
666 || link->type == Spadcallquit || link->type == Qspadcallquit
667 || link->type == Qspadcall || link->type == Lispcommandquit)
668 return NULL;
669 page = parse_page_from_socket();
670 return page;
671 }
672
673 int
issue_serverpaste(TextNode * command)674 issue_serverpaste(TextNode *command)
675 {
676 char *buf;
677 int ret_val;
678
679 ret_val = connect_spad();
680 if (ret_val == NotConnected || ret_val == SpadBusy)
681 return 1;
682 switch_frames();
683 send_int(spad_socket, LispCommand);
684 buf = print_to_string(command);
685 send_string(spad_socket, buf);
686 return 1;
687 }
688
689 /*
690 * issue a unix command
691 */
692 void
issue_unixcommand(TextNode * node)693 issue_unixcommand(TextNode *node)
694 {
695 char *buf;
696 char *copy;
697
698
699 buf = print_to_string(node);
700 copy =(char *) halloc((strlen(buf)+2)*sizeof(char),"Unixcommand");
701 strcpy(copy,buf);
702 copy[strlen(buf) + 1] = '\0';
703 copy[strlen(buf)] = '&';
704 system(copy);
705 free(copy);
706 return;
707 }
708
709 HyperDocPage *
issue_unixlink(TextNode * node)710 issue_unixlink(TextNode *node)
711 {
712 HyperDocPage *page;
713 char *buf;
714
715 buf = print_to_string(node);
716 if ((unixfd = popen(buf, "r")) == NULL) {
717 fprintf(stderr, "Error popening %s\n", buf);
718 exit(-1);
719 }
720 bsdSignal(SIGUSR2,SIG_IGN,0);
721 page = parse_page_from_unixfd();
722 bsdSignal(SIGUSR2,sigusr2_handler,0);
723 return page;
724 }
725
726 int
issue_unixpaste(TextNode * node)727 issue_unixpaste(TextNode *node)
728 {
729 char *buf;
730
731 buf = print_to_string(node);
732 if ((unixfd = popen(buf, "r")) == NULL) {
733 fprintf(stderr, "Error popening %s\n", buf);
734 exit(-1);
735 }
736 return 1;
737 }
738
739
740 /*
741 * called when session_server selects
742 */
743 void
service_session_socket(void)744 service_session_socket(void)
745 {
746 int cmd, pid;
747
748 cmd = get_int(session_server);
749 switch (cmd) {
750 case CloseClient:
751 pid = get_int(session_server);
752 if (pid != -1)
753 close_client(pid);
754 break;
755 default:
756 fprintf(stderr,
757 "(HyperDoc) Unknown command from SessionServer %d\n", cmd);
758 break;
759 }
760 }
761
762
763 /*
764 * let spad know which frame to issue command via
765 */
766 static void
switch_frames(void)767 switch_frames(void)
768 {
769 if (session_server == NULL) {
770 fprintf(stderr, "(HyperDoc) No session manager connected!\n");
771 return;
772 }
773 if (gWindow->fricas_frame == -1) {
774 fprintf(stderr, "(HyperDoc) No FriCAS frame associated with top level window!\n");
775 return;
776 }
777 send_int(session_server, SwitchFrames);
778 send_int(session_server, gWindow->fricas_frame);
779 }
780 void
send_lisp_command(char * command)781 send_lisp_command(char *command)
782 {
783 int ret_val;
784
785 ret_val = connect_spad();
786 if (ret_val == NotConnected || ret_val == SpadBusy) {
787 return;
788 }
789 send_int(spad_socket, LispCommand);
790 send_string(spad_socket, command);
791 }
792 void
escape_string(char * s)793 escape_string(char *s)
794 {
795 char *st;
796
797 for (st = s; *st; st++)
798 *st = funnyEscape(*st);
799 }
800 void
unescape_string(char * s)801 unescape_string(char *s)
802 {
803 char *st;
804
805 for (st = s; *st; st++)
806 *st = funnyUnescape(*st);
807 }
808 static void
close_client(int pid)809 close_client(int pid)
810 {
811 /*int i;*/
812 Sock_List *pSock, *locSock;
813
814 /*
815 * just need to drop the list item
816 */
817
818 if (plSock == (Sock_List *) 0)
819 return;
820
821 /*
822 * first check head
823 */
824
825 if ((plSock->Socket.pid == pid)) {
826 locSock = plSock;
827 if ((*plSock).next == (Sock_List *) 0) {
828 plSock = (Sock_List *) 0;
829 }
830 else {
831 plSock = plSock->next;
832 }
833 free(locSock);
834 }
835
836 /*
837 * now check the rest
838 */
839
840 else {
841 for (pSock = plSock; pSock->next != (Sock_List *) 0; pSock = pSock->next)
842 if (pSock->next->Socket.pid == pid) {
843 locSock = pSock->next;
844 if (pSock->next->next == (Sock_List *) 0) {
845 pSock->next = (Sock_List *) 0;
846 }
847 else {
848 pSock->next = pSock->next->next;
849 }
850 free(locSock);
851 break;
852 }
853 }
854 }
855
856
857
858 char *
print_source_to_string(TextNode * command)859 print_source_to_string(TextNode *command)
860 {
861 int len = 0;
862
863 print_source_to_string1(command, &len);
864 p2sBuf = resizeBuffer(len, p2sBuf, &p2sBufSize);
865 return print_source_to_string1(command, NULL);
866 }
867 char *
print_source_to_string1(TextNode * command,int * sizeBuf)868 print_source_to_string1(TextNode *command,int * sizeBuf)
869 {
870 char *c = p2sBuf;
871 char *s;
872 InputItem *item;
873 LineStruct *curr_line;
874 int lcount;
875 InputBox *box;
876 int num_spaces;
877 int count;
878 TextNode *node;
879
880 /*
881 print out HyperDoc source for what you see
882 */
883
884 for (node = command; node != NULL;) {
885 switch (node->type) {
886 case Newline:
887 storeString("\\newline\n");
888 node = node->next;
889 break;
890 case Par:
891 storeString("\n\n");
892 node = node->next;
893 break;
894 case Indentrel:
895 storeString("\\indentrel{");
896 storeString(node->data.node->data.text);
897 storeChar('}');
898 node = node->next;
899 break;
900 case Tab:
901 storeString("\\tab{");
902 storeString(node->data.node->data.text);
903 storeChar('}');
904 node = node->next;
905 break;
906 case Ifcond:
907 if (check_condition(node->data.ifnode->cond))
908 node = node->data.ifnode->thennode;
909 else
910 node = node->data.ifnode->elsenode;
911 break;
912 case Endarg:
913 case Endspadsrc:
914 case Endpix:
915 case Endbutton:
916 storeChar('}');
917 node = node->next;
918 break;
919 case Endverbatim:
920 case Endif:
921 case Fi:
922 case Endmacro:
923 case Endparameter:
924 case Rbrace:
925 node = node->next;
926 break;
927 case Punctuation:
928
929 /*
930 * Simply copy the piece of text
931 */
932 if (node->space & FRONTSPACE) { storeChar(' '); }
933 for (s = node->data.text; *s; s++) { storeChar(*s); }
934 node = node->next;
935 break;
936 case WindowId:
937 storeString("\\windowid ");
938 node = node->next;
939 break;
940 case Verbatim:
941 case Spadsrctxt:
942 if (node->space) { storeChar(' '); }
943 for (s = node->data.text; *s; s++) { storeChar(*s); }
944 node = node->next;
945 break;
946 case Dash:
947 case Rsquarebrace:
948 case Lsquarebrace:
949 case Word:
950 if (node->space) { storeChar(' '); }
951 for (s = node->data.text; *s; s++) { storeChar(*s); }
952 node = node->next;
953 break;
954 case BoxValue:
955 box = (InputBox *) hash_find(gWindow->page->box_hash, node->data.text);
956 if (box == NULL) {
957 fprintf(stderr, "Print_to_string:Box %s Has no symbol table entry\n",
958 node->data.text);
959 exit(-1);
960 }
961 storeChar(' ');
962 if (box->picked) {
963 storeChar('t');
964 }
965 else {
966 storeChar('n');
967 storeChar('i');
968 storeChar('l');
969 }
970 node = node->next;
971 break;
972 case StringValue:
973 item = return_item(node->data.text);
974 if (item != NULL) {
975 if (node->space) { storeChar(' '); }
976 curr_line = item->lines;
977 while (curr_line != NULL) {
978 for (lcount = 0, s = curr_line->buffer;
979 *s && lcount < item->size;
980 s++, lcount++) {
981 storeChar(funnyUnescape(*s));
982 }
983 if (curr_line->len <= item->size && curr_line->next)
984 storeChar('\n');
985 curr_line = curr_line->next;
986 }
987 }
988 else if ((box = (InputBox *) hash_find(gWindow->page->box_hash,
989 node->data.text)) != NULL) {
990 if (node->space) { storeChar(' '); }
991 if (box->picked) {
992 storeChar('t');
993 }
994 else {
995 storeChar('n');
996 storeChar('i');
997 storeChar('l');
998 }
999 }
1000 else {
1001 fprintf(stderr, "Error, Symbol %s has no symbol table entry\n",
1002 node->data.text);
1003 exit(-1);
1004 }
1005 node = node->next;
1006 break;
1007 case Space:
1008 num_spaces = (node->data.node != NULL ?
1009 atoi(node->data.node->data.text) : 1);
1010 for (count = 0; count < num_spaces; count++)
1011 storeChar(' ');
1012 node = node->next;
1013 break;
1014 case Emphasize:
1015 storeString("\\em ");
1016 node = node->next;
1017 break;
1018 case BoldFace:
1019 storeString("\\bf ");
1020 node = node->next;
1021 break;
1022 case Sl:
1023 storeString("\\it ");
1024 node = node->next;
1025 break;
1026 case Rm:
1027 storeString("\\rm ");
1028 node = node->next;
1029 break;
1030 case It:
1031 storeString("\\it ");
1032 node = node->next;
1033 break;
1034 case Tt:
1035 storeString("\\tt ");
1036 node = node->next;
1037 break;
1038 case Group:
1039 /* skip {} */
1040 if (node->next->type==Endgroup){
1041 node=node->next->next;
1042 break;
1043 }
1044 storeChar('{');
1045 node = node->next;
1046 break;
1047 case Endgroup:
1048 storeChar('}');
1049 node = node->next;
1050 break;
1051 case Box:
1052 storeString("\\box{");
1053 node = node->next;
1054 break;
1055 case Endbox:
1056 storeChar('}');
1057 node = node->next;
1058 break;
1059 case Center:
1060 storeString("\\center{");
1061 node = node->next;
1062 break;
1063 case Endcenter:
1064 storeString("}");
1065 storeChar('\n');
1066 node = node->next;
1067 break;
1068 case Titlenode:
1069 case Endtitle:
1070 node = node->next;
1071 break;
1072 case Bound:
1073 {
1074 TextNode *n2 = node->data.node;
1075
1076 storeString("\\bound{");
1077 for (; n2->type != Endarg; n2 = n2->next) {
1078 if (n2->type == Word) {
1079 storeString(n2->data.text);
1080 storeChar(' ');
1081 }
1082 }
1083 storeChar('}');
1084 }
1085 node = node->next;
1086 break;
1087 case Free:
1088 {
1089 TextNode *n2 = node->data.node;
1090
1091 storeString("\\free{");
1092 for (; n2->type != Endarg; n2 = n2->next) {
1093 if (n2->type == Word) {
1094 storeString(n2->data.text);
1095 storeChar(' ');
1096 }
1097 }
1098 storeChar('}');
1099 }
1100 node = node->next;
1101 break;
1102 case Macro:
1103 storeChar(' ');
1104 node = node->next;
1105 break;
1106 case Pound:
1107 if (node->space) { storeChar(' '); }
1108 node = node->next;
1109 break;
1110 case Indent:
1111 num_spaces = (node->data.node != NULL ?
1112 atoi(node->data.node->data.text) : 1);
1113 for (count = 0; count < num_spaces; count++)
1114 storeChar(' ');
1115 node = node->next;
1116 break;
1117 case Inputbitmap:
1118 storeString("\\inputbitmap{");
1119 storeString(node->data.text);
1120 storeString("}\n");
1121 node = node->next;
1122 break;
1123 case Endscrolling:
1124 storeString("\\end{scroll}\n");
1125 node = node->next;
1126 break;
1127 case Scrollingnode:
1128 storeString("\\begin{scroll}\n");
1129 storeString("% This is the scrolling area\n");
1130 node = node->next;
1131 break;
1132 case Horizontalline:
1133 storeString("\\horizontalline\n");
1134 node = node->next;
1135 break;
1136 case Endtable:
1137 storeChar('}');
1138 node = node->next;
1139 break;
1140 case Table:
1141 storeString("\\table{");
1142 node = node->next;
1143 break;
1144 case Tableitem:
1145 storeChar('{');
1146 node = node->next;
1147 break;
1148 case Endtableitem:
1149 storeChar('}');
1150 node = node->next;
1151 break;
1152 case Beginitems:
1153 storeString("\\begin{items}");
1154 node = node->next;
1155 break;
1156 case Item:
1157 storeString("\n\\item");
1158 node = node->next;
1159 break;
1160 case Enditems:
1161 storeString("\n\\end{items}");
1162 node = node->next;
1163 break;
1164 /*** LINKS ***/
1165 /* all these guys are ended by Endbutton
1166 we close the brace then */
1167 case Spadlink:
1168 storeString("\\fauxspadlink{");
1169 node = node->next;
1170 break;
1171 case Unixlink:
1172 storeString("\\fauxunixlink{");
1173 node = node->next;
1174 break;
1175 case Lisplink:
1176 storeString("\\fauxlisplink{");
1177 node = node->next;
1178 break;
1179 case Link:
1180 storeString("\\fauxlink{");
1181 node = node->next;
1182 break;
1183 case LispDownLink:
1184 storeString("\\fauxlispdownlink{");
1185 node = node->next;
1186 break;
1187 case LispMemoLink:
1188 storeString("\\fauxlispmemolink{");
1189 node = node->next;
1190 break;
1191 case Memolink:
1192 storeString("\\fauxmemolink{");
1193 node = node->next;
1194 break;
1195 case Windowlink:
1196 storeString("\\fauxwindowlink{");
1197 node = node->next;
1198 break;
1199 case Downlink:
1200 storeString("\\fauxdownlink{");
1201 node = node->next;
1202 break;
1203 /** END OF LINKS **/
1204 case Unixcommand:
1205 storeString("\\unixcommand{");
1206 node = node->next;
1207 break;
1208 case Lispcommand:
1209 storeString("\\lispcommand{");
1210 node = node->next;
1211 break;
1212 case Spadgraph:
1213 storeString("\\spadgraph{");
1214 node = node->next;
1215 break;
1216 case Spadcommand:
1217 storeString("\\spadcommand{");
1218 node = node->next;
1219 break;
1220 case Endspadcommand:
1221 storeChar('}');
1222 node = node->next;
1223 break;
1224 case Footernode:
1225 storeString("% This is the footer\n");
1226 node = node->next;
1227 break;
1228 case Endfooter:
1229 storeString("% This is the end of the footer\n");
1230 node = node->next;
1231 break;
1232 case Endheader:
1233 storeString("% This is the end of the header\n");
1234 node = node->next;
1235 break;
1236 case Headernode:
1237 storeString("% This is the header\n");
1238 node = node->next;
1239 break;
1240 default:
1241 fprintf(stderr,
1242 "Print_source_to_string: Unrecognized Keyword Type %d\n",
1243 node->type);
1244 node=node->next;
1245 break;
1246 }
1247 }
1248 storeChar('\0');
1249 return p2sBuf;
1250 }
1251