1: /*
2: * $Id: xecline.c,v 1.32 2026/03/19 19:03:58 snw Exp $
3: * freem interpreter proper
4: *
5: *
6: * Author: Serena Willis <snw@coherent-logic.com>
7: * Copyright (C) 1998 MUG Deutschland
8: * Copyright (C) 2020, 2025 Coherent Logic Development LLC
9: *
10: *
11: * This file is part of FreeM.
12: *
13: * FreeM is free software: you can redistribute it and/or modify
14: * it under the terms of the GNU Affero Public License as published by
15: * the Free Software Foundation, either version 3 of the License, or
16: * (at your option) any later version.
17: *
18: * FreeM is distributed in the hope that it will be useful,
19: * but WITHOUT ANY WARRANTY; without even the implied warranty of
20: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21: * GNU Affero Public License for more details.
22: *
23: * You should have received a copy of the GNU Affero Public License
24: * along with FreeM. If not, see <https://www.gnu.org/licenses/>.
25: *
26: * $Log: xecline.c,v $
27: * Revision 1.32 2026/03/19 19:03:58 snw
28: * Attempt to rectify terminal corruption problem when the user performs a gracious exit
29: *
30: * Revision 1.31 2025/05/20 18:07:41 snw
31: * Add completion to debugger
32: *
33: * Revision 1.30 2025/05/20 16:20:42 snw
34: * Update ROUTINE SSVN after ZEDIT and ZSAVE
35: *
36: * Revision 1.29 2025/05/20 14:56:56 snw
37: * Fix direct-mode interface to online help
38: *
39: * Revision 1.28 2025/05/20 14:36:06 snw
40: * Documentation updates; raise ZCMMND instead of NOSTAND for restricted_mode restrictions
41: *
42: * Revision 1.27 2025/05/19 21:29:29 snw
43: * Add basic tab completion to direct mode
44: *
45: * Revision 1.26 2025/05/19 02:03:31 snw
46: * Reverse-engineer and document argumented ZPRINT (thanks to D. Wicksell)
47: *
48: * Revision 1.25 2025/05/18 18:15:38 snw
49: * Add ZEDIT command for editing routines
50: *
51: * Revision 1.24 2025/05/14 12:22:04 snw
52: * Further work on shared memory
53: *
54: * Revision 1.23 2025/05/06 16:10:06 snw
55: * Add extra blank before readline call on NetBSD
56: *
57: * Revision 1.22 2025/05/05 14:53:17 snw
58: * Modify rpm spec to include documentation TODO
59: *
60: * Revision 1.21 2025/05/01 17:02:30 snw
61: * Further debugging improvements
62: *
63: * Revision 1.20 2025/04/30 17:19:16 snw
64: * Improve backtraces in debugger
65: *
66: * Revision 1.19 2025/04/30 14:41:03 snw
67: * Further debugger work
68: *
69: * Revision 1.18 2025/04/29 18:46:17 snw
70: * Begin work on interactive debugger
71: *
72: * Revision 1.17 2025/04/28 19:38:55 snw
73: * Add trace mode
74: *
75: * Revision 1.16 2025/04/28 14:52:54 snw
76: * Temporarily revert global handler refactor and fix reference regression in xecline
77: *
78: * Revision 1.15 2025/04/15 16:49:36 snw
79: * Make use of logprintf throughout codebase
80: *
81: * Revision 1.14 2025/04/13 04:22:43 snw
82: * Fix snprintf calls
83: *
84: * Revision 1.13 2025/04/10 01:24:39 snw
85: * Remove C++ style comments
86: *
87: * Revision 1.12 2025/04/09 19:52:02 snw
88: * Eliminate as many warnings as possible while building with -Wall
89: *
90: * Revision 1.11 2025/04/02 03:02:42 snw
91: * Stop requiring users to pass -e to fmadm when -u or -g are passed
92: *
93: * Revision 1.10 2025/03/27 03:27:35 snw
94: * Install init scripts to share/freem/examples/init and fix regression in method dispatch
95: *
96: * Revision 1.9 2025/03/24 04:13:12 snw
97: * Replace action macro dat with fra_dat to avoid symbol conflict on OS/2
98: *
99: * Revision 1.8 2025/03/24 04:05:36 snw
100: * Replace crlf with frm_crlf to avoid symbol conflict with readline on OS/2
101: *
102: * Revision 1.7 2025/03/22 22:52:24 snw
103: * Add STRLEN_GBL macro to manage global string length
104: *
105: * Revision 1.6 2025/03/22 21:44:32 snw
106: * Make the startup messages fewer and add environment name to direct-mode prompt
107: *
108: * Revision 1.5 2025/03/09 19:50:47 snw
109: * Second phase of REUSE compliance and header reformat
110: *
111: *
112: * SPDX-FileCopyrightText: (C) 2025 Coherent Logic Development LLC
113: * SPDX-License-Identifier: AGPL-3.0-or-later
114: **/
115:
116: #include <stdlib.h>
117:
118: #include "mpsdef.h"
119: #include "namespace.h"
120: #include "transact.h"
121: #include "merge.h"
122: #include "sighnd.h"
123: #include "init.h"
124: #include "events.h"
125: #include "mdebug.h"
126: #include "freem.h"
127: #include "mref.h"
128: #include "log.h"
129: #include "consttbl.h"
130: #include "shmmgr.h"
131: #include "locktab.h"
132: #include "jobtab.h"
133: #include "config.h"
134: #include "datatypes.h"
135: #include "objects.h"
136: #include "mcommand.h"
137:
138: #if defined(__linux__)
139: # include <sched.h>
140: #endif
141:
142: #if !defined(MSDOS)
143: # include "io_socket.h"
144: #endif
145:
146: #include "merr.h"
147:
148: #include <errno.h>
149: #include <unistd.h>
150: #include <string.h>
151:
152: #if !defined(MSDOS)
153: # include <syslog.h>
154: #endif
155:
156: #include <stdio.h>
157: #include <ctype.h>
158:
159: #include <time.h>
160: #include <sys/types.h>
161: #include <pwd.h>
162: #if !defined(__OpenBSD__) && !defined(__FreeBSD__)
163: # include <sys/timeb.h>
164: #endif
165: #include <sys/wait.h>
166: #include <sys/time.h>
167: #include <time.h>
168:
169: #ifdef HAVE_LIBREADLINE
170: # if defined(HAVE_READLINE_READLINE_H)
171: # include <readline/readline.h>
172: # elif defined(HAVE_READLINE_H)
173: # include <readline.h>
174: # else /* !defined(HAVE_READLINE_H) */
175: extern char *readline ();
176: # endif /* !defined(HAVE_READLINE_H) */
177: /*char *cmdline = NULL;*/
178: #else /* !defined(HAVE_READLINE_READLINE_H) */
179: /* no readline */
180: #endif /* HAVE_LIBREADLINE */
181:
182: #ifdef HAVE_READLINE_HISTORY
183: # if defined(HAVE_READLINE_HISTORY_H)
184: # include <readline/history.h>
185: # elif defined(HAVE_HISTORY_H)
186: # include <history.h>
187: # else /* !defined(HAVE_HISTORY_H) */
188: extern void add_history ();
189: extern int write_history ();
190: extern int read_history ();
191: # endif /* defined(HAVE_READLINE_HISTORY_H) */
192: /* no history */
193: #endif /* HAVE_READLINE_HISTORY */
194:
195: #include "mwapi_window.h"
196: #include "mwapi_event.h"
197:
198:
199: void on_frame_entry(void);
200: void rbuf_dump(void);
201: short rbuf_slot_from_name(char *);
202: short is_standard(void);
203:
204: #ifdef HAVE_LIBREADLINE
205: char *m_commands[] = {
206: "?",
207: "@",
208: "!<",
209: "!>",
210: "!!",
211: "ablock",
212: "astart",
213: "astop",
214: "aunblock",
215: "break",
216: "close",
217: "do",
218: "else",
219: "events",
220: "for",
221: "goto",
222: "halt",
223: "hang",
224: "history",
225: "if",
226: "job",
227: "jobtab",
228: "kill",
229: "ksubscripts",
230: "kvalue",
231: "lock",
232: "locktab",
233: "merge",
234: "new",
235: "open",
236: "quit",
237: "rbuf",
238: "rcl",
239: "read",
240: "set",
241: "shmpages",
242: "shmstat",
243: "tcommit",
244: "then",
245: "trantab",
246: "trollback",
247: "tstart",
248: "use",
249: "view",
250: "wh",
251: "write",
252: "xecute",
253: "zassert",
254: "zbreak",
255: "zconst",
256: "zedit",
257: "zgoto",
258: "zhalt",
259: "zinsert",
260: "zjob",
261: "zload",
262: "zmap",
263: "znew",
264: "zprint",
265: "zquit",
266: "zremove",
267: "zsave",
268: "zthrow",
269: "ztrap",
270: "zunmap",
271: "zwatch",
272: "zwith",
273: "zwrite",
274: "ABLOCK",
275: "ASTART",
276: "ASTOP",
277: "AUNBLOCK",
278: "BREAK",
279: "CLOSE",
280: "DO",
281: "ELSE",
282: "FOR",
283: "GOTO",
284: "HALT",
285: "HANG",
286: "IF",
287: "JOB",
288: "KILL",
289: "KSUBSCRIPTS",
290: "KVALUE",
291: "LOCK",
292: "MERGE",
293: "NEW",
294: "OPEN",
295: "QUIT",
296: "READ",
297: "SET",
298: "TCOMMIT",
299: "THEN",
300: "TROLLBACK",
301: "TSTART",
302: "USE",
303: "VIEW",
304: "WRITE",
305: "XECUTE",
306: "ZASSERT",
307: "ZBREAK",
308: "ZCONST",
309: "ZEDIT",
310: "ZGOTO",
311: "ZHALT",
312: "ZINSERT",
313: "ZJOB",
314: "ZLOAD",
315: "ZMAP",
316: "ZNEW",
317: "ZPRINT",
318: "ZQUIT",
319: "ZREMOVE",
320: "ZSAVE",
321: "ZTHROW",
322: "ZTRAP",
323: "ZUNMAP",
324: "ZWATCH",
325: "ZWITH",
326: "ZWRITE",
327: NULL
328: };
329:
330: char **command_completion(const char *, int, int);
331: char *command_generator(const char *, int);
332:
333: char **command_completion(const char *text, int start, int end)
334: {
335: if (start > 0) return NULL;
336: rl_attempted_completion_over = 1;
337: return rl_completion_matches (text, command_generator);
338: }
339:
340: char *command_generator(const char *text, int state)
341: {
342: static int list_index, len;
343: char *name;
344:
345: if (!state) {
346: list_index = 0;
347: len = strlen (text);
348: }
349:
350: while ((name = m_commands[list_index++])) {
351: if (strncmp (name, text, len) == 0) {
352: return strdup (name);
353: }
354: }
355:
356: return NULL;
357: }
358: #endif
359:
360: /*
361: * xecline():
362: * typ (where to go on function entry): 1 = restart
363: * 2 = error
364: *
365: */
366: int xecline(int typ)
367: {
368: MACTION ra;
369: short new_and_set = FALSE;
370: short new_object = FALSE;
371: short destructor_run = FALSE;
372: short libcall = FALSE;
373: char *namold;
374: long rouoldc;
375: unsigned long jobtime;
376: char label[256], routine[256];
377:
378: char tracestr[512];
379:
380: char *vn;
381: char *an;
382: char *tmp;
383: char *tmp2;
384: char *tmp3;
385:
386:
387: char *deferrable_codptr;
388: char deferrable_code[512];
389:
390: char *ev_handlers;
391:
392: char *reeval_codptr;
393: char reeval_code[512];
394: char entryref[256];
395:
396: int i;
397: int j;
398: register int ch;
399:
400: int then_ctr = 0;
401:
402: #if defined(HAVE_MWAPI_MOTIF)
403: int syn_event_entry_nstx = 0;
404: int in_syn_event_loop = FALSE;
405: #endif
406:
407: # ifdef DEBUG_NEWSTACK
408: int loop;
409: # endif
410:
411: vn = (char *) malloc ((STRLEN + 1) * sizeof (char));
412: an = (char *) malloc ((STRLEN + 1) * sizeof (char));
413: tmp = (char *) malloc ((STRLEN + 1) * sizeof (char));
414: tmp2 = (char *) malloc ((STRLEN + 1) * sizeof (char));
415: tmp3 = (char *) malloc ((STRLEN + 1) * sizeof (char));
416:
417: NULLPTRCHK(vn,"xecline");
418: NULLPTRCHK(an,"xecline");
419: NULLPTRCHK(tmp,"xecline");
420: NULLPTRCHK(tmp2,"xecline");
421: NULLPTRCHK(tmp3,"xecline");
422:
423: deferrable_codptr = deferrable_code;
424:
425: switch (typ) {
426:
427: case 0:
428: goto next_line;
429:
430: case 1:
431: goto restart;
432:
433: case 2:
434: goto err;
435:
436: case 3:
437: libcall = TRUE;
438: goto restart;
439:
440: }
441:
442: next_line: /* entry point for next command line */
443:
444: if (debug_mode) {
445: debug_mode = debugger (DEBENTRY_LINE, entryref);
446: }
447:
448: job_set_status (pid, JSTAT_INTERPRETER);
449:
450: if (then_ctr > 0) {
451: test = nestlt[nstx];
452: level--;
453: then_ctr--;
454: }
455:
456: while ((roucur < rouend) && (ch = (*roucur++)) != TAB && ch != SP); /* skip label */
457:
458: if (roucur >= rouend) goto quit0; /* end of routine implies QUIT */
459:
460: while ((ch = *roucur) == TAB || ch == SP) roucur++;
461:
462: i = 0;
463: if (ch == '.') { /* get level count */
464:
465: do {
466: i++;
467: while ((ch = (*++roucur)) == SP || ch == TAB);
468: }
469: while (ch == '.');
470:
471: }
472:
473: if (i != level) {
474:
475: if (mcmnd == GOTO) {
476: merr_raise (M45);
477: goto err;
478: }
479:
480: if (i < level) {
481: goto quit0;
482: }
483: else {
484: roucur += stlen (roucur) + 2;
485: goto next_line;
486: }
487: }
488:
489: i = stcpy (code, roucur) + 1;
490: code[i] = EOL;
491: roucur += i + 1;
492: codptr = code;
493:
494: next_cmnd: /* continue line entry point */
495: getraddress (entryref, nstx);
496: if (debug_mode) {
497: debug_mode = debugger (DEBENTRY_CMD, entryref);
498: }
499:
500: if (sigint_in_for) goto for_quit;
501:
502: if (forsw && (forpost[forx][0] != '\0')) {
503:
504: stcpy (reeval_code, code);
505: reeval_codptr = codptr;
506:
507: strcpy (code, forpost[forx]);
508: stcnv_c2m (code);
509: codptr = code;
510:
511: expr (STRING);
512:
513: if (merr () > OK) {
514: stcpy (code, reeval_code);
515: codptr = reeval_codptr;
516:
517: goto err;
518: }
519:
520: if (tvexpr (argptr) == FALSE) {
521: stcpy (code, reeval_code);
522: codptr = reeval_codptr;
523:
524: goto for_quit;
525: }
526:
527: stcpy (code, reeval_code);
528: codptr = reeval_codptr;
529:
530: }
531:
532: job_set_status (pid, JSTAT_INTERPRETER);
533:
534: if (evt_async_enabled == TRUE) {
535:
536: switch (pending_signal_type) {
537:
538: case SIGWINCH:
539: evt_enqueue ("SIGWINCH", EVT_CLS_INTERRUPT, 1);
540: break;
541:
542: case SIGINT:
543: evt_enqueue ("SIGINT", EVT_CLS_INTERRUPT, 0);
544: break;
545:
546: case SIGFPE:
547: evt_enqueue ("SIGFPE", EVT_CLS_INTERRUPT, 0);
548: break;
549:
550: case SIGQUIT:
551: evt_enqueue ("SIGQUIT", EVT_CLS_INTERRUPT, 0);
552: break;
553:
554: }
555:
556: pending_signal_type = -1;
557:
558: /* process async events */
559: ev_handlers = (char *) malloc (STRLEN * sizeof (char));
560: NULLPTRCHK(ev_handlers,"xecline");
561:
562:
563: /* get a comma-delimited list of applicable handlers (e.g. ^HNDL1,^HNDL2,^HNDL3) */
564: ev_handlers[0] = NUL;
565: evt_depth = evt_get_handlers (ev_handlers);
566:
567: stcnv_c2m (ev_handlers);
568: stcpy (tmp3, ev_handlers);
569: free (ev_handlers);
570:
571: /* only execute event handlers if we have at least one such handler registered in ^$JOB($JOB,"EVENTS") */
572: if (evt_depth) {
573:
574: /* per X11-1998/28, async events are to be disabled during the execution of event handlers */
575:
576: /* TODO: this should be done by incrementing the event block counter
577: for all event types, or whatever the event extension says to do.
578:
579: In any event (rimshot here for the obvious pun), turning off all
580: event handlers this way is decidedly non-standard. Or non-what-might-
581: become the standard. Whatever. */
582:
583: evt_async_enabled = FALSE;
584: evt_async_initial = TRUE;
585: evt_async_restore = TRUE;
586:
587: goto evthandler;
588:
589: }
590:
591: }
592:
593:
594: if (merr () > OK) goto err;
595:
596: next0:
597:
598: do {
599: if ((ch = *codptr) == EOL) {
600: if (forsw) goto for_end;
601:
602: goto next_line;
603: }
604:
605: codptr++;
606: }
607: while (ch == SP);
608:
609: /* decode command word */
610:
611: if (ch < 'A') { /* Handle non-alpha first chars */
612:
613: if (ch == ';') { /* COMMENT */
614:
615: ch = *(codptr++);
616:
617: if(ch == '%') { /* DIRECTIVE */
618:
619: int dir_pos = 0;
620: int dir_wc = 0;
621: char dir_words[20][255];
622:
623: while((ch = *(codptr++)) != EOL) {
624:
625: switch (ch) {
626:
627:
628: case SP:
629:
630: dir_words[dir_wc][dir_pos] = NUL;
631:
632: dir_wc++;
633: dir_pos = 0;
634:
635: break;
636:
637:
638: default:
639:
640: dir_words[dir_wc][dir_pos++] = ch;
641:
642: }
643:
644: }
645:
646: dir_words[dir_wc][dir_pos] = NUL;
647:
648: if (strcmp (dir_words[0], "DIALECT") == 0) {
649: short rb_slot;
650:
651: rb_slot = rbuf_slot_from_name (rou_name);
652:
653: if ((strcmp (dir_words[1], "STANDARD") == 0) ||
654: (strcmp (dir_words[1], "MDS") == 0)) {
655: rbuf_flags[rb_slot].standard = TRUE;
656: rbuf_flags[rb_slot].dialect = D_MDS;
657: }
658: else if (strcmp (dir_words[1], "M77") == 0) {
659: rbuf_flags[rb_slot].standard = TRUE;
660: rbuf_flags[rb_slot].dialect = D_M77;
661: }
662: else if (strcmp (dir_words[1], "M84") == 0) {
663: rbuf_flags[rb_slot].standard = TRUE;
664: rbuf_flags[rb_slot].dialect = D_M84;
665: }
666: else if (strcmp (dir_words[1], "M90") == 0) {
667: rbuf_flags[rb_slot].standard = TRUE;
668: rbuf_flags[rb_slot].dialect = D_M90;
669: }
670: else if (strcmp (dir_words[1], "M95") == 0) {
671: rbuf_flags[rb_slot].standard = TRUE;
672: rbuf_flags[rb_slot].dialect = D_M95;
673: }
674: else if (strcmp (dir_words[1], "M5") == 0) {
675: rbuf_flags[rb_slot].standard = TRUE;
676: rbuf_flags[rb_slot].dialect = D_M5;
677: }
678: else if ((strcmp (dir_words[1], "FREEM") == 0) ||
679: (strcmp (dir_words[1], "EXTENDED") == 0)) {
680: rbuf_flags[rb_slot].standard = FALSE;
681: rbuf_flags[rb_slot].dialect = D_FREEM;
682: }
683: else {
684: merr_raise (CMMND);
685: goto err;
686: }
687: goto skip_line;
688: }
689: else {
690: goto skip_line;
691: }
692:
693: }
694:
695: goto skip_line;
696: }
697:
698: if ((!is_standard ()) && (ch == '#')) {
699: goto skip_line;
700: }
701:
702: if ((is_standard ()) && (ch == '#')) {
703: merr_raise (NOSTAND);
704: goto err;
705: }
706:
707: if (ch == '@') {
708: if (!is_standard ()) {
709: goto do_xecute;
710: }
711: else {
712: merr_raise (NOSTAND);
713: goto err;
714: }
715: }
716:
717: if (ch == '!') { /* UNIXCALL */
718:
719: if (restricted_mode) {
720: merr_raise (CMMND);
721: goto err;
722: }
723:
724: /* don't catch child dies signal */
725: sig_attach (SIGUSR1, SIG_IGN);
726:
727: tmp2[stcpy (tmp2, codptr)] = NUL;
728:
729: if (demomode) fputc (d1char, stdout);
730:
731: if (tmp2[0] == '!') {
732:
733: uid_t suid;
734: struct passwd *spw;
735:
736: suid = geteuid ();
737: spw = getpwuid (suid);
738:
739: set_io (UNIX);
740:
741: fprintf (stderr, "Type Ctrl-D to exit from the shell\n");
742:
743: if (strlen (spw->pw_shell)) {
744: zsystem = system (spw->pw_shell);
745: }
746: else {
747: zsystem = system ("/bin/sh");
748: }
749:
750: set_io (MUMPS);
751: sig_attach (SIGUSR1, &oncld); /* restore handler */
752:
753: }
754: else if (tmp2[0] == '<') { /* call write output to %-array */
755:
756: FILE *pipdes;
757: char key[STRLEN];
758: char data[STRLEN];
759: char data_kill[256];
760: data_kill[255] = EOL;
761:
762: for (i = 0; i < STRLEN - 1; i++) vn[i] = EOL;
763:
764: snprintf (key, STRLEN - 1, "^$JOB\202%d\202PIPE_GLVN\201", pid);
765: ssvn (get_sym, key, vn);
766:
767: if (vn[0] == '^') {
768:
769: if (vn[1] == '$') {
770: merr_raise (INVREF);
771: goto err;
772: }
773: else {
774: global (kill_sym, vn, data_kill);
775: }
776:
777: }
778: else {
779: symtab (kill_sym, vn, data);
780: }
781:
782: snprintf (key, STRLEN - 1, "^$JOB\202%d\202PIPE_GLVN\201", pid);
783: ssvn (get_sym, key, vn);
784:
785: data[0] = '0';
786: data[1] = EOL;
787:
788: if (vn[0] == '^') {
789:
790: if (vn[1] == '$') {
791: merr_raise (INVREF);
792: goto err;
793: }
794: else {
795: global (set_sym, vn, data);
796: }
797:
798: }
799: else {
800: symtab (set_sym, vn, data);
801: }
802:
803: set_io (UNIX);
804: if ((pipdes = popen (&tmp2[1], "r")) == NULL) {
805: zsystem = 1;
806: }
807: else {
808: int glvn_len = 0;
809:
810: while (fgets (data, STRLEN, pipdes)) {
811: snprintf (key, STRLEN - 1, "^$JOB\202%d\202PIPE_GLVN\201", pid);
812: ssvn (get_sym, key, vn);
813:
814: glvn_len = stlen (vn);
815: stcpy (key, vn);
816:
817: key[glvn_len] = DELIM;
818:
819: if (vn[0] == '^') {
820:
821: if (vn[1] == '$') {
822: merr_raise (INVREF);
823: goto err;
824: }
825: else {
826: global (getinc, vn, &key[glvn_len + 1]);
827: }
828:
829: }
830: else {
831: symtab (getinc, vn, &key[glvn_len + 1]);
832: }
833:
834: i = strlen (data);
835:
836: data[i] = EOL;
837:
838: if (i > 1 && data[i - 1] == LF) data[i - 1] = EOL;
839:
840: if (vn[0] == '^') {
841:
842: if (vn[1] == '$') {
843: merr_raise (INVREF);
844: goto err;
845: }
846: else {
847: global (set_sym, key, data);
848: }
849:
850: }
851: else {
852: symtab (set_sym, key, data);
853: }
854:
855: if (merr () == STORE) break;
856: }
857:
858: pclose (pipdes);
859:
860: zsystem = 0;
861: }
862: set_io (MUMPS);
863: }
864: else if (tmp2[0] == '>') { /* call read input from %-array */
865: FILE *pipdes;
866: char key[STRLEN + 1 /*was 256 */ ];
867: char data[STRLEN + 1 /*was 256 */ ];
868: int i, k, l;
869:
870: for (i = 0; i < STRLEN + 1; i++) vn[i] = EOL;
871:
872: snprintf (key, STRLEN - 1, "^$JOB\202%d\202PIPE_GLVN\201", pid);
873: ssvn (get_sym, key, vn);
874:
875: if (vn[0] == '^') {
876:
877: if (vn[1] == '$') {
878: merr_raise (INVREF);
879: goto err;
880: }
881: else {
882: global (get_sym, vn, data);
883: }
884:
885: }
886: else {
887: symtab (get_sym, vn, data);
888: }
889:
890: merr_clear ();
891: k = intexpr (data);
892:
893: set_io (UNIX);
894: if (k < 1 || (pipdes = popen (&tmp2[1], "w")) == NULL) {
895: zsystem = 1;
896: }
897: else {
898: int glvn_len = 0;
899:
900: for (i = 1; i <= k; i++) {
901: snprintf (key, STRLEN - 1, "^$JOB\202%d\202PIPE_GLVN\201", pid);
902: ssvn (get_sym, key, vn);
903:
904: glvn_len = stlen (vn);
905: stcpy (key, vn);
906:
907: key[glvn_len] = DELIM;
908:
909: intstr (&key[glvn_len + 1], i);
910:
911: if (vn[0] == '^') {
912:
913: if (vn[1] == '$') {
914: merr_raise (INVREF);
915: goto err;
916: }
917: else {
918: global (get_sym, key, data);
919: }
920:
921: }
922: else {
923: symtab (get_sym, key, data);
924: }
925:
926: l = stlen (data);
927:
928: data[l++] = LF;
929: data[l] = NUL;
930:
931: fputs (data, pipdes);
932: }
933:
934: pclose (pipdes);
935:
936: zsystem = 0;
937: merr_clear ();
938: }
939: set_io (MUMPS);
940:
941: }
942: else {
943: set_io (UNIX);
944: zsystem = system (tmp2);
945: set_io (MUMPS);
946: }
947:
948: if (demomode) fputc (d1char, stdout);
949:
950: sig_attach (SIGUSR1, &oncld); /* restore handler */
951:
952:
953: if (merr () == STORE) {
954: zsystem = 1;
955: goto err;
956: }
957:
958: goto skip_line;
959: }
960:
961: merr_raise (CMMND);
962: goto err;
963: } /* END handling of non-alpha first chars */
964:
965:
966: mcmnd = ch | 0140; /* uppercase to lower case */
967:
968: i = 1;
969:
970: while ((ch = (*codptr)) != SP && ch != ':' && ch != EOL) {
971: tmp3[++i] = ch | 0140;
972: codptr++;
973: }
974:
975: j = i;
976:
977: if (j > 1) {
978: merr_raise (mcmd_tokenize (&ra, tmp3, deferrable_codptr, deferrable_code, &j));
979: MRESCHECK(ra);
980: }
981:
982:
983: if (*codptr == ':') {
984: /* handle postconditional */
985:
986: if (mcmnd == FOR) {
987: char *savcp = codptr;
988:
989: codptr++;
990: i = 0;
991: while ((forpost[forx + 1][i++] = *(codptr++)) != SP);
992:
993: forpost[forx + 1][i - 1] = '\0';
994:
995: codptr = savcp;
996: }
997:
998:
999: /* postcond after FOR,IF,ELSE not allowed in dialects other than D_FREEM */
1000:
1001:
1002: if ((rtn_dialect () != D_FREEM) && (mcmnd == FOR || mcmnd == IF || mcmnd == ELSE)) {
1003: merr_raise (NOSTAND);
1004: goto err;
1005: }
1006:
1007: codptr++;
1008:
1009: expr (STRING);
1010:
1011: if (merr () > OK) goto err;
1012:
1013: ch = *codptr;
1014:
1015: if (ch != SP && ch != EOL) {
1016: merr_raise (SPACER);
1017: goto err;
1018: }
1019:
1020: if (tvexpr (argptr) == FALSE) { /* skip arguments */
1021:
1022: if ((mcmnd == IF) || (mcmnd == THEN) || (mcmnd == ELSE) || (mcmnd == FOR)) {
1023: mcmnd = 0;
1024: goto skip_line;
1025: }
1026:
1027: mcmnd = 0; /* avoid false LEVEL error */
1028:
1029: for (;;) {
1030: if (ch == EOL) goto skip_line;
1031: if ((ch = *++codptr) == SP) goto next_cmnd;
1032: if (ch != '"') continue;
1033:
1034: while (*codptr++ != EOL) {
1035: if (*codptr != ch) continue;
1036: if (*++codptr != ch) break;
1037: }
1038:
1039: if (--codptr == code) goto err;
1040: }
1041: }
1042:
1043: }
1044:
1045: if (*codptr != EOL) { /* beware argumentless cmnds at end of line */
1046: codptr++; /* entry for next argument in list */
1047:
1048: again:
1049: while (*codptr == '@') { /* handle indirection */
1050:
1051: stcpy (tmp, codptr++); /* save code to restore on nameind */
1052: expr (ARGIND);
1053:
1054: if (merr () > OK) goto err;
1055:
1056: if (((ch = (*codptr)) != SP && ch != EOL && ch != ',' && ch != ':' && ch != '=') || (ch == '@' && *(codptr + 1) == '(')) {
1057: stcpy (code, tmp); /* restore code on nameind */
1058: codptr = code;
1059:
1060: break;
1061: }
1062: else {
1063: stcpy (argptr + stlen (argptr), codptr);
1064: stcpy (code, argptr);
1065:
1066: codptr = code;
1067: }
1068: }
1069: }
1070:
1071: if (trace_mode) tracestr[0] = '\0';
1072:
1073: switch (mcmnd) {
1074:
1075: case MAP:
1076: merr_raise (cmd_map (&ra));
1077: MRESCHECK(ra);
1078: break;
1079:
1080: case UNMAP:
1081: merr_raise (cmd_unmap (&ra));
1082: MRESCHECK(ra);
1083: break;
1084:
1085: case THEN:
1086: merr_raise (cmd_then (&ra, &then_ctr));
1087: MRESCHECK(ra);
1088: break;
1089:
1090: case THROW:
1091: merr_raise (cmd_throw (&ra));
1092: MRESCHECK(ra);
1093: break;
1094:
1095: case CONST:
1096: merr_raise (cmd_const (&ra));
1097: MRESCHECK(ra);
1098: break;
1099:
1100: case KVALUE:
1101: merr_raise (cmd_kvalue (&ra));
1102: MRESCHECK(ra);
1103: break;
1104:
1105: case KSUBSC:
1106: merr_raise (cmd_ksubscripts (&ra));
1107: MRESCHECK(ra);
1108: break;
1109:
1110: case TSTART:
1111: merr_raise (cmd_tstart (&ra));
1112: MRESCHECK(ra);
1113: break;
1114:
1115: case TCOMMIT:
1116: merr_raise (cmd_tcommit (&ra));
1117: MRESCHECK(ra);
1118: break;
1119:
1120: case TROLLBACK:
1121: merr_raise (cmd_trollback (&ra));
1122: MRESCHECK(ra);
1123: break;
1124:
1125: case SET:
1126:
1127: set0:
1128: if ((ch = (*codptr)) >= 'A') { /* no set$piece nor multiset */
1129: short setref = FALSE;
1130: short stclass = SC_UNCHANGED;
1131:
1132: expr (NAME);
1133: if (merr () > OK) break;
1134: stcpy (vn, varnam);
1135:
1136: if (isalpha (vn[0]) && *(codptr + 1) == ':') {
1137: char sc_string[255];
1138:
1139: codptr += 2;
1140: expr (NAME);
1141:
1142: stcpy (sc_string, varnam);
1143: for (i = 0; i < stlen (sc_string); i++) {
1144: sc_string[i] = toupper (sc_string[i]);
1145: }
1146:
1147: stcnv_m2c (sc_string);
1148: if (strcmp (sc_string, "PRIVATE") == 0) {
1149: stclass = SC_PRIVATE;
1150: }
1151: else if (strcmp (sc_string, "PUBLIC") == 0) {
1152: stclass = SC_PUBLIC;
1153: }
1154: else {
1155: merr_raise (OBJACINVALID);
1156: break;
1157: }
1158: }
1159:
1160: if ((*++codptr != '=') || (*(codptr + 1) == '=')) {
1161: ch = *codptr;
1162:
1163: /* double char symbol ** (power) is encoded by ' ' */
1164: if (ch == '*' && *(codptr + 1) == ch) {
1165: codptr++;
1166: ch = ' ';
1167: }
1168:
1169: /* negated boolean operator */
1170: else if ((ch == '\'') && (*(codptr + 2) == '=')) ch = SETBIT (*++codptr);
1171:
1172: if (*++codptr != '=') {
1173:
1174: /* unary ++/-- */
1175: if ((ch == '+' || ch == '-') && ch == *codptr) {
1176: codptr++;
1177: setop = ch;
1178: argptr[0] = '1';
1179: argptr[1] = EOL;
1180:
1181: goto set2;
1182: }
1183:
1184: merr_raise (ASSIGNER);
1185: break;
1186: }
1187:
1188: setop = ch;
1189: }
1190:
1191: codptr++;
1192:
1193: ch = *codptr;
1194:
1195: if (ch == '.') {
1196: if (!isdigit (*(codptr + 1))) {
1197: setref = TRUE;
1198: codptr++;
1199: expr (NAME);
1200: }
1201: else {
1202: expr (STRING);
1203: }
1204: }
1205: else {
1206: expr (STRING);
1207: }
1208:
1209:
1210: if (merr () > OK) break;
1211:
1212:
1213: set2:
1214:
1215: if (vn[0] == '^') {
1216:
1217: stcpy (an, argptr);
1218:
1219: if (setref == TRUE) {
1220: merr_raise (INVREF);
1221: goto err;
1222: }
1223:
1224: if (vn[1] == '$') {
1225: ssvn (set_sym, vn, an);
1226: }
1227: else {
1228: global (set_sym, vn, an);
1229: }
1230:
1231: }
1232: else {
1233: stcpy (an, argptr);
1234:
1235: if (setref == TRUE) {
1236: symtab (new_sym, vn, "");
1237: symtab (m_alias, vn, varnam);
1238: codptr++;
1239: }
1240: else {
1241: if (new_object == FALSE) {
1242: symtab (set_sym, vn, an);
1243: switch (stclass) {
1244:
1245: case SC_PUBLIC:
1246: obj_set_field_public (vn);
1247: break;
1248:
1249: case SC_PRIVATE:
1250: obj_set_field_private (vn);
1251: break;
1252:
1253: }
1254: }
1255: }
1256: }
1257:
1258: if (merr () > OK) {
1259: stcpy (varerr, vn);
1260: break;
1261: }
1262:
1263: if (((new_and_set == TRUE) || (new_object == TRUE)) && (*codptr != SP) && (*codptr != EOL)) {
1264: new_and_set = FALSE;
1265: new_object = FALSE;
1266:
1267: merr_raise (INEWMUL);
1268: goto err;
1269: }
1270:
1271: if (new_and_set == TRUE) new_and_set = FALSE;
1272: if (new_object == TRUE) new_object = FALSE;
1273: /*
1274: set1:
1275: */
1276: if (*codptr != ',') break;
1277:
1278: if (*++codptr == '@') goto again;
1279:
1280: goto set0;
1281: }
1282:
1283: /****** special SET syntax: multiple SET, set$piece, special variables */
1284: {
1285: char multiset, vnset[256]; /* multiset variables */
1286: long arg3, arg4; /* 3rd,4th arg in set$piece */
1287:
1288: if ((multiset = (ch == '('))) {
1289: vnset[0] = EOL;
1290: codptr++;
1291: }
1292:
1293: set:
1294: if (*codptr == '$' && (*(codptr + 1) | 0140) == 'p') { /* set$piece */
1295:
1296: if (multiset) {
1297: merr_raise (INVREF);
1298: goto err;
1299: }
1300:
1301: setpiece = 'p';
1302:
1303: while (*++codptr != '(') {
1304:
1305: if (*codptr == EOL) {
1306: merr_raise (INVREF);
1307: goto err;
1308: }
1309:
1310: }
1311:
1312: codptr++;
1313:
1314: expr (NAME);
1315:
1316: if (merr () > OK) goto err;
1317:
1318: stcpy (vn, varnam);
1319:
1320: codptr++;
1321:
1322: if (*codptr++ != ',') {
1323: merr_raise (COMMAER);
1324: goto err;
1325: }
1326:
1327: expr (STRING);
1328:
1329: if (merr () > OK) goto err;
1330:
1331: stcpy (tmp2, argptr);
1332:
1333: if (*codptr != ')') {
1334:
1335: codptr++;
1336:
1337: expr (STRING);
1338:
1339: if (merr () > OK) goto err;
1340:
1341: arg3 = intexpr (argptr);
1342:
1343: if (merr () == MXNUM) {
1344: arg3 = 256;
1345: merr_clear ();
1346: }
1347:
1348: }
1349: else {
1350: arg3 = 1;
1351: }
1352:
1353: if (*codptr != ')') {
1354:
1355: codptr++;
1356:
1357: expr (STRING);
1358:
1359: if (merr () > OK) goto err;
1360:
1361: if (*codptr != ')') {
1362: merr_raise (BRAER);
1363: goto err;
1364: }
1365:
1366: arg4 = intexpr (argptr);
1367:
1368: if (merr () == MXNUM) {
1369: arg4 = 256;
1370: merr_clear ();
1371: }
1372:
1373: }
1374: else {
1375: arg4 = arg3;
1376: }
1377: } /* set$piece */
1378: else if (*codptr == '$' && (*(codptr + 1) | 0140) == 'q' && (*(codptr + 2) | 0140) == 's') { /* TODO: verify this works (jpw) was (*codptr == '$q'...*/
1379: /*SET $QSUBSCRIPT */
1380:
1381: if (multiset) {
1382: merr_raise (INVREF);
1383: goto err;
1384: }
1385:
1386: setpiece = 'q';
1387:
1388: while (*++codptr != '(') {
1389:
1390: if (*codptr == EOL) {
1391: merr_raise (INVREF);
1392: goto err;
1393: }
1394:
1395: }
1396:
1397: codptr++;
1398:
1399: expr (NAME);
1400:
1401: if (merr () > OK) goto err;
1402:
1403: stcpy (vn, varnam);
1404:
1405: if (*++codptr == ',') {
1406: codptr++;
1407:
1408: expr (STRING);
1409:
1410: if (merr () > OK) goto err;
1411:
1412: stcpy (tmp2, argptr);
1413: }
1414:
1415: if (*codptr != ')') {
1416: merr_raise (BRAER);
1417: goto err;
1418: }
1419:
1420: }
1421: else if (*codptr == '$' &&
1422: (*(codptr + 1) | 0140) == 'd' &&
1423: (*(codptr + 2) | 0140) == 'i') {
1424:
1425: short rb_slot;
1426:
1427: rb_slot = rbuf_slot_from_name (rou_name);
1428:
1429: while ((*(++codptr)) != '=');
1430:
1431: codptr++;
1432:
1433: expr (STRING);
1434:
1435: stcnv_m2c (argptr);
1436:
1437: if ((strcmp (argptr, "STANDARD") == 0) ||
1438: (strcmp (argptr, "MDS") == 0)) {
1439: rbuf_flags[rb_slot].standard = TRUE;
1440: rbuf_flags[rb_slot].dialect = D_MDS;
1441: }
1442: else if (strcmp (argptr, "M77") == 0) {
1443: rbuf_flags[rb_slot].standard = TRUE;
1444: rbuf_flags[rb_slot].dialect = D_M77;
1445: }
1446: else if (strcmp (argptr, "M84") == 0) {
1447: rbuf_flags[rb_slot].standard = TRUE;
1448: rbuf_flags[rb_slot].dialect = D_M84;
1449: }
1450: else if (strcmp (argptr, "M90") == 0) {
1451: rbuf_flags[rb_slot].standard = TRUE;
1452: rbuf_flags[rb_slot].dialect = D_M90;
1453: }
1454: else if (strcmp (argptr, "M95") == 0) {
1455: rbuf_flags[rb_slot].standard = TRUE;
1456: rbuf_flags[rb_slot].dialect = D_M95;
1457: }
1458: else if (strcmp (argptr, "M5") == 0) {
1459: rbuf_flags[rb_slot].standard = TRUE;
1460: rbuf_flags[rb_slot].dialect = D_M5;
1461: }
1462: else if ((strcmp (argptr, "FREEM") == 0) ||
1463: (strcmp (argptr, "EXTENDED") == 0)) {
1464: rbuf_flags[rb_slot].standard = TRUE;
1465: rbuf_flags[rb_slot].dialect = D_FREEM;
1466: }
1467: else {
1468: merr_raise (CMMND);
1469: goto err;
1470: }
1471:
1472: goto s_end;
1473:
1474: }
1475: else if (*codptr == '$' && (*(codptr + 1) | 0140) == 'e' && (*(codptr + 2) | 0140) != 't' && (*(codptr + 2) | 0140) != 'c') {
1476:
1477: /* set $extract */
1478: if (multiset) {
1479: merr_raise (INVREF);
1480: goto err;
1481: }
1482:
1483: setpiece = 'e';
1484:
1485: while (*++codptr != '(') {
1486:
1487: if (*codptr == EOL) {
1488: merr_raise (INVREF);
1489: goto err;
1490: }
1491:
1492: }
1493:
1494: codptr++;
1495:
1496: expr (NAME);
1497:
1498: if (merr () > OK) goto err;
1499:
1500: stcpy (vn, varnam);
1501:
1502: codptr++;
1503:
1504: if (*codptr != ')') {
1505: codptr++;
1506:
1507: expr (STRING);
1508:
1509: if (merr () > OK) goto err;
1510:
1511: arg3 = intexpr (argptr);
1512:
1513: if (merr () == MXNUM) {
1514: arg3 = 256;
1515: merr_clear ();
1516: }
1517: }
1518: else {
1519: arg3 = 1;
1520: }
1521:
1522: if (*codptr != ')') {
1523: codptr++;
1524:
1525: expr (STRING);
1526:
1527: if (merr () > OK) goto err;
1528:
1529: if (*codptr != ')') {
1530: merr_raise (BRAER);
1531: goto err;
1532: }
1533:
1534: arg4 = intexpr (argptr);
1535:
1536: if (merr () == MXNUM) {
1537: arg4 = 256;
1538: merr_clear ();
1539: }
1540:
1541: }
1542: else {
1543: arg4 = arg3;
1544: }
1545:
1546: }
1547: else if (*codptr == '$' && (*(codptr + 1) | 0140) == 'e' && (*(codptr + 2) | 0140) == 'c') {
1548: /* set $ecode */
1549:
1550: if (multiset) {
1551: merr_raise (INVREF);
1552: goto err;
1553: }
1554:
1555: while ((*(++codptr)) != '=');
1556:
1557: codptr++;
1558:
1559: expr (STRING);
1560:
1561: if (merr () > OK) goto err;
1562:
1563: switch (argptr[0]) {
1564:
1565: case ',':
1566:
1567: switch (argptr[1]) {
1568:
1569: case ',':
1570: merr_raise (M101);
1571: goto err;
1572:
1573: }
1574:
1575: break;
1576:
1577: }
1578:
1579: merr_raise (merr_set_ecode (argptr));
1580:
1581: #if 0
1582: set_io (UNIX);
1583: stcnv_m2c (ecode);
1584: stcnv_m2c (etrap);
1585: printf ("\n\n*** IN SET $ECODE: ecode = '%s' etrap = '%s'\n", ecode, etrap);
1586: stcnv_c2m (etrap);
1587: stcnv_c2m (ecode);
1588: set_io (MUMPS);
1589: #endif
1590:
1591: if (merr () > OK) goto err;
1592:
1593: goto s_end;
1594:
1595: }
1596: else if (*codptr == '$' && (*(codptr + 1) | 0140) == 'e' && (*(codptr + 2) | 0140) == 't') {
1597: /* set $etrap */
1598:
1599: if (multiset) {
1600: merr_raise (INVREF);
1601: goto err;
1602: }
1603:
1604: while ((*(++codptr)) != '=');
1605:
1606: codptr++;
1607:
1608: expr (STRING);
1609:
1610: if (merr () > OK) goto err;
1611:
1612: stcpy (etrap, argptr);
1613:
1614: #if 0
1615: set_io (UNIX);
1616: stcnv_m2c (ecode);
1617: stcnv_m2c (etrap);
1618: printf ("\n\n***IN SET $ETRAP: ecode = '%s' etrap = '%s'\n", ecode, etrap);
1619: stcnv_c2m (etrap);
1620: stcnv_c2m (ecode);
1621: set_io (MUMPS);
1622: #endif
1623:
1624: goto s_end;
1625:
1626: }
1627: else if (*codptr == '$' && (*(codptr + 1) | 0140) == 'g' && cset) { /* set$get */
1628:
1629: if (multiset) {
1630: merr_raise (INVREF);
1631: goto err;
1632: }
1633:
1634: setpiece = 'g';
1635:
1636: while (*++codptr != '(') {
1637:
1638: if (*codptr == EOL) {
1639: merr_raise (INVREF);
1640: goto err;
1641: }
1642: }
1643:
1644: codptr++;
1645:
1646: expr (NAME);
1647:
1648: if (merr () > OK) goto err;
1649:
1650: stcpy (vn, varnam);
1651:
1652: if (*++codptr == ',') {
1653: codptr++;
1654:
1655: expr (STRING);
1656:
1657: if (merr () > OK) goto err;
1658:
1659: stcpy (tmp2, argptr);
1660: }
1661: else {
1662: tmp2[0] = EOL;
1663: }
1664:
1665: if (*codptr != ')') {
1666: merr_raise (BRAER);
1667: goto err;
1668: }
1669: }
1670: else {
1671: if (*codptr == '$') {
1672: codptr++;
1673:
1674: expr (NAME);
1675:
1676: if (merr () > OK) goto err;
1677:
1678: stcpy (tmp, varnam);
1679:
1680: varnam[0] = '$';
1681:
1682: stcpy (&varnam[1], tmp);
1683:
1684: i = 0;
1685: while ((ch = varnam[++i]) != EOL) {
1686: if (ch >= 'A' && ch <= 'Z') {
1687: varnam[i] |= 0140; /*to lowercase */
1688: }
1689: }
1690: }
1691: else {
1692: expr (NAME);
1693:
1694: if (merr () > OK) goto err;
1695: }
1696:
1697: stcpy (vn, varnam);
1698: }
1699:
1700: if (multiset) {
1701: vnset[i = stlen (vnset)] = SOH;
1702:
1703: stcpy (&vnset[++i], vn);
1704:
1705: if (*++codptr == ',') {
1706: codptr++;
1707: goto set;
1708: }
1709:
1710: if (*codptr != ')') {
1711: merr_raise (COMMAER);
1712: goto err;
1713: }
1714: }
1715:
1716: if (*++codptr != '=') {
1717: ch = *codptr;
1718:
1719: if (!cset || *++codptr != '=' || multiset || setpiece || varnam[0] == '$') {
1720: merr_raise (ASSIGNER);
1721: break;
1722: }
1723:
1724: setop = ch;
1725: }
1726:
1727: codptr++;
1728:
1729: expr (STRING);
1730:
1731: if (merr () > OK) goto err;
1732:
1733: if (multiset)
1734: multi:
1735: {
1736: i = 0;
1737: while (vnset[i] == SOH) i++;
1738:
1739: j = 0;
1740: while ((vn[j] = vnset[i]) != SOH && vnset[i] != EOL) {
1741: vnset[i++] = SOH;
1742: j++;
1743: }
1744:
1745: vn[j] = EOL;
1746:
1747: if (j == 0) goto s_end;
1748: }
1749:
1750: if (setpiece == 'p') {
1751: long m, n;
1752:
1753: if (arg4 < arg3 || arg4 < 1) {
1754: setpiece = FALSE;
1755: break;
1756: }
1757:
1758: if (arg3 <= 0) arg3 = 1;
1759:
1760: if (vn[0] == '^') {
1761: if (vn[1] == '$') {
1762: ssvn (get_sym, vn, tmp3);
1763: }
1764: else {
1765: global (get_sym, vn, tmp3);
1766: }
1767: }
1768: else {
1769: symtab (get_sym, vn, tmp3);
1770: }
1771:
1772:
1773: if (merr () == UNDEF || merr () == M6 || merr () == M7) {
1774: tmp3[0] = EOL;
1775: merr_clear ();
1776: }
1777: else if (merr () != OK) {
1778: stcpy (varerr, vn);
1779: }
1780:
1781: ch = 0;
1782: m = 0;
1783: n = 0;
1784:
1785: j = stlen (tmp2);
1786:
1787: while (n < arg3 - 1) {
1788:
1789: if ((ch = find (&tmp3[m], tmp2)) <= 0) {
1790:
1791: while (++n < arg3) {
1792: if (stcat (tmp3, tmp2) == 0) {
1793: merr_raise (M75);
1794: goto err;
1795: }
1796: }
1797:
1798: arg3 = arg4 = stlen (tmp3);
1799:
1800: goto set10;
1801: }
1802:
1803: n++;
1804: m += j + ch - 1;
1805: }
1806:
1807: if (arg3 > 1) {
1808: arg3 = m;
1809: }
1810: else {
1811: arg3 = 0;
1812: }
1813:
1814: while (n++ < arg4) {
1815:
1816: if ((ch = find (&tmp3[m], tmp2)) <= 0) {
1817: arg4 = stlen (tmp3);
1818:
1819: goto set10;
1820: }
1821:
1822: m += j + ch - 1;
1823: }
1824:
1825: arg4 = m - j;
1826:
1827: set10:
1828:
1829: stcpy0 (tmp2, tmp3, (long) arg3);
1830:
1831: tmp2[arg3] = EOL;
1832:
1833: if (stcat (tmp2, argptr) == 0) {
1834: merr_raise (M75);
1835: goto err;
1836: }
1837:
1838: if (stcat (tmp2, &tmp3[arg4]) == 0) {
1839: merr_raise (M56); /* snw */
1840: goto err;
1841: }
1842:
1843: stcpy (argptr, tmp2);
1844:
1845: setpiece = FALSE;
1846: }
1847: else if (setpiece == 'q') { /* SET$QSUBSCRIPT */
1848:
1849: setpiece = FALSE;
1850:
1851: if (vn[0] == '^') {
1852: if (vn[1] == '$') {
1853: ssvn (get_sym, vn, tmp3);
1854: }
1855: else {
1856: global (get_sym, vn, tmp3);
1857: }
1858: }
1859: else {
1860: symtab (get_sym, vn, tmp3);
1861: }
1862:
1863: if (merr () == UNDEF || merr () == M6 || merr () == M7) {
1864: tmp3[0] = EOL;
1865: merr_clear ();
1866: }
1867: else if (merr () != OK) {
1868: stcpy (varerr, vn);
1869: }
1870:
1871: if (merr () == OK) {
1872: /* 2nd $QS argument */
1873: if ((arg4 = intexpr (tmp2)) < -1) merr_raise (ARGER);
1874: if (merr () != OK) break;
1875:
1876: /* special if source is empty */
1877: if (tmp3[0] != EOL || (arg4 != 0)) {
1878: /* special: Set env to empty: no |""| */
1879: if ((arg4 == -1) && (*argptr == EOL)) {
1880: tmp2[0] = EOL;
1881: }
1882: else if ((arg4 != 0) && !znamenumeric (argptr)) {
1883: /* put replacement string in tmp2 with */
1884: /* quotes around env or subscript, unless numeric */
1885: i = 0;
1886: j = -1;
1887: tmp2[0] = '"';
1888:
1889: while ((tmp2[++i] = argptr[++j]) != EOL) {
1890: if (tmp2[i] == '"') tmp2[++i] = '"';
1891:
1892: if (i >= (STRLEN - 2)) {
1893: merr_raise (M75);
1894: break;
1895: }
1896: }
1897:
1898: tmp2[i] = '"';
1899: tmp2[++i] = EOL;
1900: }
1901: else {
1902: stcpy (tmp2, argptr);
1903: }
1904:
1905: /* source is tmp3, dest is argptr, replacement is tmp2 */
1906: {
1907: int ch, cpflag, quote, piececounter;
1908:
1909: piececounter = 0;
1910: i = 0;
1911: j = 0;
1912: quote = FALSE;
1913: cpflag = FALSE;
1914:
1915: /* if source has no env, process right now */
1916: if ((arg4 == -1) && (tmp3[tmp3[0] == '^'] != '|') && tmp2[0] != EOL) {
1917:
1918: if (tmp3[0] == '^') {
1919: argptr[j++] = '^';
1920: i = 1;
1921: }
1922:
1923: argptr[j++] = '|';
1924: ch = 0;
1925:
1926: while ((argptr[j] = tmp2[ch++]) != EOL) j++;
1927:
1928: argptr[j++] = '|';
1929:
1930: }
1931: else if (arg4 == 0) { /* '^'+name may be separated by env */
1932: if (tmp2[0] == '^') argptr[j++] = '^';
1933: if (tmp3[0] == '^') i++;
1934: }
1935:
1936: while ((ch = tmp3[i++]) != EOL) {
1937: if (ch == '"') quote = !quote;
1938:
1939: if (!quote) {
1940:
1941: if (ch == ',') {
1942: piececounter++;
1943: argptr[j++] = ch;
1944:
1945: continue;
1946: }
1947:
1948: if ((ch == '(' && piececounter == 0)) {
1949: if (!cpflag && (arg4 == 0)) {
1950: i--;
1951: }
1952: else {
1953: piececounter = 1;
1954: argptr[j++] = ch;
1955:
1956: continue;
1957: }
1958: }
1959:
1960: if (ch == '|') {
1961: if (piececounter == 0) {
1962: piececounter = (-1);
1963: }
1964: else if (piececounter == (-1)) {
1965: piececounter = 0;
1966: }
1967:
1968: if (tmp2[0] != EOL || piececounter > 0) argptr[j++] = ch;
1969:
1970: continue;
1971: }
1972: }
1973:
1974: if (piececounter == arg4) {
1975: if (cpflag) continue;
1976:
1977: cpflag = TRUE;
1978: ch = 0;
1979:
1980: if (arg4 == 0 && tmp2[0] == '^') ch = 1;
1981:
1982: while ((argptr[j] = tmp2[ch++]) != EOL) j++;
1983: }
1984: else {
1985: argptr[j++] = ch;
1986: }
1987:
1988: if (j >= (STRLEN - 1)) {
1989: merr_raise (M75);
1990: break;
1991: }
1992: } /* while ((ch = tmp3[i++]) != EOL) ... */
1993:
1994: if (piececounter && (piececounter == arg4)) argptr[j++] = ')';
1995:
1996: if (piececounter < arg4) {
1997:
1998: if (piececounter == 0) {
1999: argptr[j++] = '(';
2000: }
2001: else {
2002: argptr[j - 1] = ',';
2003: }
2004:
2005: while (++piececounter < arg4) {
2006: argptr[j++] = '"';
2007: argptr[j++] = '"';
2008: argptr[j++] = ',';
2009:
2010: if (j >= STRLEN) {
2011: merr_raise (M75);
2012: break;
2013: }
2014:
2015: }
2016: }
2017:
2018: ch = 0;
2019:
2020: if (argptr[j - 1] != ')') {
2021: while ((argptr[j++] = tmp2[ch++]) != EOL);
2022: argptr[j - 1] = ')';
2023: }
2024: }
2025:
2026: argptr[j] = EOL;
2027:
2028: if (j >= STRLEN) {
2029: merr_raise (M75);
2030: break;
2031: }
2032:
2033: }
2034: }
2035: else {
2036: break;
2037: }
2038: } /* set$qsubscript */
2039: else if (setpiece == 'e') { /* SETtable $EXTRACT *//* parameters ok?? */
2040:
2041: if (arg3 > arg4 || arg4 < 1) {
2042: setpiece = FALSE;
2043: break;
2044: }
2045:
2046: if (arg3 <= 0) arg3 = 1;
2047:
2048: if (arg3 > STRLEN) {
2049: merr_raise (M75);
2050: goto err;
2051: }
2052:
2053: /* get value of glvn */
2054: if (vn[0] == '^') {
2055: if (vn[1] == '$') {
2056: ssvn (get_sym, vn, tmp3);
2057: }
2058: else {
2059: global (get_sym, vn, tmp3);
2060: }
2061: }
2062: else {
2063: symtab (get_sym, vn, tmp3);
2064: }
2065:
2066:
2067: /* if UNDEF assume null string */
2068: if (merr () == UNDEF || merr () == M6 || merr () == M7) {
2069: tmp3[0] = EOL;
2070: merr_clear ();
2071: }
2072: else if (merr () != OK) {
2073: stcpy (varerr, vn);
2074: }
2075:
2076: j = stlen (tmp3);
2077:
2078: /* pad with SPaces if source string is too short */
2079: while (j < arg3) tmp3[j++] = SP;
2080:
2081: tmp3[j] = EOL;
2082:
2083: if (stlen (tmp3) > arg4) {
2084: stcpy (tmp2, &tmp3[arg4]);
2085: }
2086: else {
2087: tmp2[0] = EOL;
2088: }
2089:
2090: tmp3[arg3 - 1] = EOL;
2091:
2092: /* compose new value of glvn */
2093: if (stcat (tmp3, argptr) == 0) {
2094: merr_raise (M75);
2095: goto err;
2096: }
2097:
2098: if (stcat (tmp3, tmp2) == 0) {
2099: merr_raise (M75);
2100: goto err;
2101: }
2102:
2103: stcpy (argptr, tmp3);
2104: setpiece = FALSE;
2105: }
2106: else if (setpiece == 'g') { /* SETtable $GET */
2107: setpiece = FALSE;
2108: ch = (stcmp (tmp2, argptr) == 0) ? killone : set_sym;
2109:
2110: if (vn[0] == '^') {
2111: stcpy (an, argptr);
2112: if (vn[1] == '$') {
2113: ssvn (ch, vn, an);
2114: }
2115: else {
2116: global (ch, vn, an);
2117: }
2118: }
2119: else {
2120: stcpy (an, argptr);
2121: symtab (ch, vn, an);
2122: }
2123:
2124: if (merr () != OK) stcpy (varerr, vn);
2125: break;
2126: }
2127:
2128: if (vn[0] == '^') { /* global variables and SSVNs */
2129: stcpy (an, argptr);
2130:
2131: if (vn[1] == '$') {
2132: ssvn (set_sym, vn, an);
2133: }
2134: else {
2135: global (set_sym, vn, an);
2136: }
2137:
2138:
2139: if (merr () > OK) {
2140: stcpy (varerr, vn);
2141: goto err;
2142: }
2143: }
2144: else if (vn[0] != '$') { /* local variables */
2145: stcpy (an, argptr);
2146: symtab (set_sym, vn, an);
2147:
2148: if (merr () > OK) {
2149: stcpy (varerr, vn);
2150: goto err;
2151: }
2152: }
2153: else { /* $-variables */
2154:
2155: if (vn[1] == 'x') { /* set $X */
2156: j = intexpr (argptr);
2157:
2158: if (merr () == MXNUM) {
2159: j = 256;
2160: merr_clear ();
2161: }
2162:
2163: if (j < 0) {
2164: merr_raise (M43);
2165: goto err;
2166: }
2167:
2168: if (io == HOME) {
2169: argptr[0] = ESC;
2170: argptr[1] = '[';
2171: argptr[2] = EOL;
2172:
2173: if (ypos[HOME] > 1) {
2174: intstr (tmp3, ypos[HOME] + 1);
2175: stcat (argptr, tmp3);
2176: }
2177:
2178: if (j > 0) {
2179: stcat (argptr, ";\201");
2180: intstr (tmp3, j + 1);
2181: stcat (argptr, tmp3);
2182: }
2183:
2184: stcat (argptr, "H\201");
2185: write_m (argptr);
2186: }
2187:
2188: xpos[io] = j;
2189: goto s_end;
2190: }
2191: else if (vn[1] == 'y') { /* set $Y */
2192:
2193: j = intexpr (argptr);
2194:
2195: if (merr () == MXNUM) {
2196: j = 256;
2197: merr_clear ();
2198: }
2199:
2200: if (j < 0) {
2201: merr_raise (M43);
2202: goto err;
2203: }
2204:
2205: if (io == HOME) {
2206:
2207: argptr[0] = ESC;
2208: argptr[1] = '[';
2209: argptr[2] = EOL;
2210:
2211: if (j > 0) {
2212: intstr (tmp3, j + 1);
2213: stcat (argptr, tmp3);
2214: }
2215:
2216: if (xpos[HOME] > 0) {
2217: stcat (argptr, ";\201");
2218: intstr (tmp3, xpos[HOME] + 1);
2219: stcat (argptr, tmp3);
2220: }
2221:
2222: stcat (argptr, "H\201");
2223: write_m (argptr);
2224: }
2225:
2226: ypos[io] = j;
2227: goto s_end;
2228: }
2229: else if (vn[1] == 't') { /* set $t */
2230: test = tvexpr (argptr);
2231: goto s_end;
2232: }
2233: else if (vn[1] == 'j') { /* set $job */
2234: pid = intexpr (argptr);
2235: lock (" \201", -1, 's');
2236: goto s_end;
2237: }
2238: #if !defined(_SCO_DS)
2239: else if (vn[1] == 'h') { /* set $horolog */
2240: long int day;
2241: long int sec;
2242: struct timespec sh_ts;
2243:
2244: if (!is_horolog (argptr)) {
2245: merr_raise (ZINVHORO);
2246: goto err;
2247: }
2248:
2249: sec = 0L;
2250:
2251: for (i = 0; argptr[i] != EOL; i++) {
2252:
2253: if (argptr[i] == ',') {
2254: sec = intexpr (&argptr[i + 1]);
2255: break;
2256: }
2257:
2258: }
2259:
2260: if (sec < 0 || sec >= 86400L) {
2261: merr_raise (ARGER);
2262: goto err;
2263: }
2264:
2265: day = intexpr (argptr) - 47117L;
2266:
2267: if (day < 0 || day > 49710L) {
2268: merr_raise (ARGER);
2269: goto err;
2270: }
2271:
2272: sec += day * 86400 + FreeM_timezone;
2273: day = FreeM_timezone;
2274:
2275: sh_ts.tv_sec = sec;
2276:
2277: #if defined(__linux__)
2278: if (clock_settime (CLOCK_REALTIME, &sh_ts) != 0) {
2279: merr_raise (PROTECT);
2280: goto err;
2281: }
2282: #endif
2283:
2284: #ifndef LINUX
2285: /* daylight savings time status may have changed */
2286: {
2287: struct tm *ctdata;
2288: long clock;
2289:
2290: clock = time (0L);
2291: ctdata = localtime (&clock);
2292:
2293: if (day -= (FreeM_timezone = ctdata->tm_tzadj)) {
2294: sec -= day;
2295: tzoffset += day;
2296: stime (&sec);
2297: }
2298: }
2299: #endif /* LINUX */
2300: goto s_end;
2301:
2302:
2303: }
2304: #endif /* _SCO_DS */
2305: else if ((vn[1] == 'r') || ((vn[1] == 'z') && (vn[2] == 'r') && vn[3] == EOL)) { /* set $reference */
2306:
2307: if (argptr[0] == EOL) {
2308: zref[0] = EOL;
2309: break;
2310: }
2311:
2312: stcpy (tmp4, codptr);
2313: stcpy (code, argptr);
2314:
2315: codptr = code;
2316:
2317: expr (NAME);
2318: stcpy (code, tmp4);
2319:
2320: codptr = code;
2321:
2322: if (argptr[0] != '^') merr_raise (INVREF);
2323: if (ierr <= OK) nakoffs = stcpy (zref, argptr); /* save reference */ /* SMW - TODO */
2324:
2325: goto s_end;
2326: }
2327: else if (vn[1] == 'z') { /* $Z.. variables *//* if not intrinsic: make it user defined */
2328:
2329: i = stcpy (&tmp[1], &vn[1]) + 1;
2330:
2331: if (vn[3] == DELIM) i = 3; /* set $zf() function keys */
2332:
2333: tmp[0] = SP;
2334: tmp[i] = SP;
2335: tmp[++i] = EOL;
2336:
2337: if (find (zsvn, tmp) == FALSE) {
2338:
2339: i = 2;
2340: while (vn[i] != EOL) {
2341:
2342: if (vn[i++] == DELIM) {
2343: merr_raise (INVREF);
2344: goto err;
2345: }
2346:
2347: }
2348:
2349: udfsvn (set_sym, &vn[2], argptr);
2350: break;
2351: }
2352:
2353: if ((!stcmp (&vn[2], "l\201")) || (!stcmp (&vn[2], "local\201"))) { /* set $zlocal */
2354:
2355: if (argptr[0] == EOL) {
2356: zloc[0] = EOL;
2357: break;
2358: }
2359:
2360: stcpy (tmp4, codptr);
2361: stcpy (code, argptr);
2362:
2363: codptr = code;
2364:
2365: expr (NAME);
2366: stcpy (code, tmp4);
2367:
2368: codptr = code;
2369:
2370: if (argptr[0] == '^') merr_raise (INVREF);
2371: if (ierr <= OK) stcpy (zloc, argptr); /* save reference */
2372:
2373: break;
2374: }
2375: if ((!stcmp (&vn[2], "t\201")) || (!stcmp (&vn[2], "tr\201")) || (!stcmp (&vn[2], "trap\201"))) { /* set $ztrap */
2376:
2377: if (stlen (argptr) > ZTLEN) {
2378: merr_raise (M75);
2379: goto err;
2380: }
2381:
2382: /* DSM V.2 error trapping */
2383: #ifdef DEBUG_NEWSTACK
2384: printf ("Setting Ztrap, DSM2err [%d]\r\n", DSM2err);
2385: #endif
2386:
2387:
2388: if (DSM2err) {
2389: stcpy (ztrap[NESTLEVLS + 1], argptr);
2390: }
2391: else {
2392: stcpy (ztrap[nstx], argptr);
2393: }
2394:
2395: }
2396: else if (!stcmp (&vn[2], "p\201") || !stcmp (&vn[2], "precision\201")) { /* set $zprecision */
2397:
2398: short tmp_zprecise;
2399:
2400: if ((tmp_zprecise = intexpr (argptr)) < 0) {
2401: merr_raise (MXNUM);
2402: goto err;
2403: }
2404:
2405: if (!fp_mode) {
2406:
2407: if (merr () == MXNUM) goto err;
2408:
2409: if (tmp_zprecise > 20000) {
2410: merr_raise (MXNUM);
2411: goto err;
2412: }
2413:
2414: }
2415: #if !defined(_AIX)
2416: else {
2417:
2418: if (tmp_zprecise > DBL_DIG) {
2419: merr_raise (MXNUM);
2420: goto err;
2421: }
2422:
2423: sprintf (fp_conversion, "%%.%df\201", tmp_zprecise);
2424:
2425: }
2426: #endif
2427:
2428: zprecise = tmp_zprecise;
2429:
2430:
2431: }
2432: else if (vn[2] == 'f' && vn[3] == DELIM) { /* set $zf() function keys */
2433:
2434: i = intexpr (&vn[4]) - 1;
2435:
2436: if (i < 0 || i > 43) {
2437: merr_raise (FUNARG);
2438: goto err;
2439: }
2440:
2441: if (stlen (argptr) > FUNLEN) {
2442: merr_raise (M75);
2443: goto err;
2444: }
2445:
2446: stcpy (zfunkey[i], argptr);
2447:
2448: }
2449: else if (vn[2] == 'm' && vn[4] == EOL && (vn[3] == 'c' || vn[3] == 'n' || vn[3] == 'p' || vn[3] == 'l' || vn[3] == 'u')) { /* set $zm_ loadable match; sort match code */
2450:
2451: short k;
2452:
2453: i = 0;
2454:
2455: for (ch = 0; ch <= 255; ch++) {
2456: j = argptr - partition;
2457:
2458: while ((k = partition[j++]) != EOL) {
2459:
2460: if (UNSIGN (k) == ch) {
2461: tmp[i++] = k;
2462: break;
2463: }
2464:
2465: }
2466:
2467: }
2468:
2469: tmp[i] = EOL;
2470:
2471: switch (vn[3]) {
2472:
2473: case 'c':
2474: stcpy (zmc, tmp);
2475: break;
2476:
2477: case 'n':
2478: stcpy (zmn, tmp);
2479: break;
2480:
2481: case 'p':
2482: stcpy (zmp, tmp);
2483: break;
2484: /* 'a': always union of zml+zmu */
2485:
2486: case 'l':
2487: stcpy (zml, tmp);
2488: break;
2489:
2490: case 'u':
2491: stcpy (zmu, tmp);
2492: break;
2493: /* 'e': always 'everything' */
2494: }
2495:
2496: }
2497: else {
2498: merr_raise (INVREF);
2499: break;
2500: }
2501: }
2502: else {
2503: merr_raise (INVREF);
2504: goto err;
2505: } /* end of processing for $Z.. intrinsic special variables */
2506: } /* svns=$vars */
2507:
2508: if (multiset) goto multi;
2509: } /* end of scope for special SET syntaxes */
2510:
2511: s_end:
2512: if (*codptr != ',') break;
2513: if (*++codptr == '@') goto again;
2514:
2515: goto set0;
2516:
2517: case IF:
2518: merr_raise (cmd_if (&ra));
2519: MRESCHECK(ra);
2520: break;
2521:
2522:
2523: case OO_USING:
2524: merr_raise (cmd_using (&ra));
2525: MRESCHECK(ra);
2526: break;
2527:
2528: case OO_WITH:
2529: merr_raise (cmd_with (&ra));
2530: MRESCHECK(ra);
2531: break;
2532:
2533: case WRITE:
2534: merr_raise (cmd_write(&ra, &i));
2535: MRESCHECK(ra);
2536: break;
2537:
2538: case READ:
2539: merr_raise (cmd_read (&ra));
2540: MRESCHECK(ra);
2541: break;
2542:
2543: case ELSE:
2544: merr_raise (cmd_else (&ra));
2545: MRESCHECK(ra);
2546: break;
2547:
2548: case ZQUIT:
2549:
2550: {
2551: int zq_lvlct;
2552:
2553: if (rtn_dialect () != D_FREEM) {
2554: merr_raise (NOSTAND);
2555: goto err;
2556: }
2557:
2558: if (*codptr == EOL) {
2559: zq_lvlct = nstx;
2560: }
2561: else {
2562: expr (STRING);
2563:
2564: zq_lvlct = intexpr (argptr);
2565:
2566: if (merr () > OK) goto err;
2567:
2568: if (zq_lvlct < 0 || zq_lvlct > nstx) {
2569: merr_raise (LVLERR);
2570: goto err;
2571: }
2572: else if (zq_lvlct != nstx) {
2573: repQUIT = nstx - zq_lvlct;
2574: }
2575: else {
2576: merr_raise (LVLERR);
2577: goto err;
2578: }
2579: }
2580:
2581: break;
2582: }
2583:
2584: case QUIT:
2585:
2586: if (trace_mode) {
2587: fprintf (stderr, ">> TRACE: $STACK = %d QUIT CMD = %c\r\n", nstx, nestc[nstx]);
2588: }
2589:
2590: if (tp_level > 0) {
2591: merr_raise (M42);
2592: goto err;
2593: }
2594:
2595: #ifdef DEBUG_NEWSTACK
2596: printf ("At QUIT command, checking stack...\r\n");
2597: #endif
2598:
2599:
2600:
2601: #ifdef DEBUG_NEWSTACK
2602: printf ("nestc[nstx] is (%d)\r\n", nestc[nstx]);
2603: #endif
2604:
2605: if (*codptr != EOL && *codptr != SP && nestc[nstx] != '$') {
2606: #ifdef DEBUG_NEWSTACK
2607: printf ("IERR\r\n");
2608: #endif
2609:
2610: merr_raise (ARGER);
2611: break;
2612: }
2613:
2614:
2615:
2616: if (nestc[nstx] == '$') { /* extrinsic function/variable */
2617:
2618:
2619: if (trace_mode) {
2620: fprintf (stderr, ">> TRACE: QUIT FROM EXTRINSIC\r\n");
2621: }
2622:
2623: #ifdef DEBUG_NEWSTACK
2624: printf ("EXTRINSIC\r\n");
2625: #endif
2626: if (*codptr == EOL || *codptr == SP) {
2627:
2628: #ifdef DEBUG_NEWSTACK
2629: printf ("CODPTR is [%d]\r\n", *codptr);
2630: #endif
2631:
2632: if (exfdefault[0] == EOL) {
2633: *argptr = EOL;
2634: merr_raise (NOVAL);
2635: }
2636: else { /* there is a default expression... */
2637: stcpy (&code[1], exfdefault);
2638: expr (STRING);
2639:
2640: if (ierr != OK - CTRLB && merr () != OK && merr () != INRPT) {
2641:
2642: #ifdef DEBUG_NEWSTACK
2643: printf ("Break at 1st IERR\r\n");
2644: #endif
2645: break;
2646: }
2647: }
2648: }
2649: else {
2650:
2651: expr (STRING);
2652:
2653: if (trace_mode) {
2654: fprintf (stderr, ">> TRACE: QUIT FROM SUBROUTINE\r\n");
2655: }
2656:
2657: if (ierr != OK - CTRLB && merr () != OK && merr () != INRPT) {
2658:
2659: #ifdef DEBUG_NEWSTACK
2660: printf ("Break at 2nd IERR\r\n");
2661: #endif
2662:
2663: break;
2664: }
2665:
2666: if (dt_check (extr_types[nstx], argptr, 0) == FALSE) {
2667: extr_types[nstx] = DT_STRING;
2668: merr_raise (TYPMISMATCH);
2669: break;
2670: }
2671:
2672:
2673: }
2674:
2675: #ifdef DEBUG_NEWSTACK
2676: printf ("CHECK 01 (Stack POP)\r\n");
2677: #endif
2678:
2679:
2680:
2681: if (nestn[nstx]) { /* reload routine */
2682: namptr = nestn[nstx];
2683:
2684: stcpy (rou_name, namptr);
2685: zload (rou_name);
2686:
2687: ssvn_job_update ();
2688:
2689: dosave[0] = 0;
2690:
2691: namptr--;
2692: }
2693:
2694: if (nestnew[nstx]) unnew (); /* un-NEW variables */
2695:
2696: /* restore old pointers */
2697: level = nestlt[nstx]; /* pop level */
2698: roucur = nestr[nstx] + rouptr;
2699:
2700: extr_types[nstx] = DT_STRING;
2701:
2702: stcpy (codptr = code, cmdptr = nestp[nstx--]);
2703: estack--;
2704:
2705: forsw = (nestc[nstx] == FOR);
2706: loadsw = TRUE;
2707:
2708: return 0;
2709:
2710:
2711: }
2712:
2713:
2714: if (nestc[nstx] == BREAK) {
2715: merr_clear ();
2716: merr_set_break ();
2717: goto zgo;
2718: } /*cont. single step */
2719:
2720:
2721: quit0:
2722:
2723: #ifdef DEBUG_NEWSTACK
2724: printf ("CHECK 02 (Stack POP)\r\n");
2725: #endif
2726:
2727: if (evt_depth) {
2728:
2729: evt_depth--;
2730:
2731: if (evt_depth == 0 && evt_async_restore == TRUE) {
2732: evt_async_enabled = TRUE;
2733: evt_async_restore = FALSE;
2734: }
2735:
2736: }
2737:
2738: if (etrap_lvl) etrap_lvl--;
2739:
2740: if (nstx == 0) goto restore; /* nothing to quit */
2741:
2742: if (nestc[nstx] == FOR) {
2743:
2744: stcpy (code, cmdptr = nestp[nstx--]);
2745:
2746: estack--;
2747:
2748: codptr = code;
2749:
2750: ftyp = fortyp[--forx];
2751: fvar = forvar[forx];
2752: finc = forinc[forx];
2753: fpost = forpost[forx];
2754: flim = forlim[forx];
2755: fi = fori[forx];
2756:
2757: if ((forsw = (nestc[nstx] == FOR))) goto for_end;
2758:
2759: goto next_line;
2760: }
2761:
2762: if (nestn[nstx]) { /* reload routine */
2763: namptr = nestn[nstx];
2764:
2765: if ((nestc[nstx] != XECUTE) || loadsw) {
2766:
2767: stcpy (rou_name, namptr);
2768: zload (rou_name);
2769:
2770: ssvn_job_update ();
2771:
2772: dosave[0] = 0;
2773: }
2774:
2775: namptr--;
2776: }
2777:
2778: if (nestnew[nstx]) unnew (); /* un-NEW variables */
2779:
2780: /* restore old pointers */
2781: if ((mcmnd = nestc[nstx]) == BREAK) goto restore; /* cont. single step */
2782:
2783: if (mcmnd == DO_BLOCK) {
2784: test = nestlt[nstx];
2785: level--;
2786: }
2787: else { /* pop $TEST */
2788: level = nestlt[nstx]; /* pop level */
2789: }
2790:
2791: if (nstx) {
2792: roucur = nestr[nstx] + rouptr;
2793: }
2794: else {
2795: roucur = buff + (NO_OF_RBUF * PSIZE0 + 1);
2796: }
2797:
2798: stcpy (codptr = code, cmdptr = nestp[nstx--]);
2799: estack--;
2800: forsw = (nestc[nstx] == FOR);
2801:
2802: loadsw = TRUE;
2803:
2804: if (deferred_ierr > OK) { /* smw - TODO: how to handle deferred_ierr now */
2805: merr_raise (deferred_ierr);
2806: }
2807:
2808: #if defined(HAVE_MWAPI_MOTIF)
2809: if ((in_syn_event_loop == TRUE) && (nstx == syn_event_entry_nstx)) goto syn_evt_loop_bottom;
2810: #endif
2811:
2812: break;
2813:
2814: case FOR:
2815:
2816: if ((ch = *codptr) == EOL) goto skip_line; /* ignore empty line */
2817:
2818: #ifdef DEBUG_NEWSTACK
2819: printf ("CHECK 03 (Stack PUSH)\r\n");
2820: #endif
2821:
2822: if (++nstx > NESTLEVLS) {
2823: nstx--;
2824: merr_raise (STKOV);
2825:
2826: break;
2827: }
2828: else {
2829: estack++;
2830: }
2831:
2832: fvar = forvar[++forx];
2833: finc = forinc[forx];
2834: fpost = forpost[forx];
2835: flim = forlim[forx];
2836: fi = fori[forx];
2837: nestc[nstx] = FOR; /* stack set-up */
2838:
2839: #ifdef DEBUG_NEWSTACK
2840: if (!cmdptr) printf ("CMDPTR is ZERO!\r\n");
2841: #endif
2842:
2843: nestp[nstx] = cmdptr;
2844: nestn[nstx] = 0; /* no overring of routine */
2845: nestr[nstx] = roucur - rouptr; /* save roucur: only for $V(26) needed */
2846: ztrap[nstx][0] = EOL;
2847:
2848:
2849: forsw = TRUE;
2850: ftyp = 0; /* no args is FOREVER */
2851:
2852: if (ch == SP) {
2853: goto for_go;
2854: }
2855: else { /* find local variable */
2856:
2857: if (ch == '^') {
2858: merr_raise (GLOBER);
2859: break;
2860: }
2861:
2862: if (ch == '$') {
2863: merr_raise (INVREF);
2864: break;
2865: }
2866:
2867: if (*(codptr + 1) == '=') { /* single char local variable */
2868:
2869: if ((ch < 'A' && ch != '%') || (ch > 'Z' && ch < 'a') || ch > 'z') {
2870: merr_raise (INVREF);
2871: break;
2872: }
2873:
2874: fvar[0] = ch;
2875: fvar[1] = EOL;
2876:
2877: codptr += 2;
2878: }
2879: else {
2880: expr (NAME);
2881:
2882: if (*++codptr != '=') merr_raise (ASSIGNER);
2883: if (merr () != OK) break;
2884:
2885: stcpy (fvar, varnam);
2886:
2887: codptr++;
2888: }
2889:
2890: ftyp++;
2891: }
2892:
2893: for_nxt_arg:
2894:
2895: expr (STRING);
2896:
2897: if (merr () != OK) break;
2898:
2899: stcpy (tmp, argptr);
2900:
2901: if ((ch = *codptr) != ':') {
2902:
2903: if (ch == ',' || ch == SP || ch == EOL) {
2904: ftyp = 1;
2905: goto for_init;
2906: }
2907:
2908: merr_raise (ARGLIST);
2909: break;
2910: }
2911:
2912: numlit (tmp); /* numeric interpretation */
2913:
2914: codptr++;
2915: expr (STRING);
2916:
2917: if (merr () != OK) break;
2918:
2919: numlit (argptr);
2920: stcpy (finc, argptr); /* increment */
2921:
2922: if ((ch = *codptr) != ':') {
2923:
2924: if (ch == ',' || ch == EOL || ch == SP) {
2925: ftyp = 2;
2926: goto for_init;
2927: }
2928:
2929: merr_raise (ARGLIST);
2930: break;
2931:
2932: }
2933:
2934: codptr++;
2935:
2936: expr (STRING);
2937: if (merr () != OK) break;
2938:
2939: numlit (argptr);
2940: stcpy (flim, argptr); /* limit */
2941:
2942: ftyp = 3;
2943:
2944: if ((ch = *codptr) != ',' && ch != SP && ch != EOL) {
2945: merr_raise (ARGLIST);
2946: break;
2947: }
2948:
2949: if ((*finc != '-' && comp (flim, tmp)) || (*finc == '-' && comp (tmp, flim))) {
2950:
2951: symtab (set_sym, fvar, tmp);
2952:
2953: if (merr () > OK) {
2954: stcpy (varerr, vn);
2955: break;
2956: }
2957:
2958: goto for_quit;
2959: }
2960:
2961: for_init:
2962:
2963: symtab (set_sym, fvar, tmp);
2964:
2965: if (merr () > OK) {
2966: stcpy (varerr, fvar);
2967: break;
2968: }
2969:
2970: /* optimize frequent special case: */
2971: /* increment by one and no additional FOR arguments */
2972: /* if limit value it must be a positive integer */
2973: if (ftyp > 1 && finc[0] == '1' && finc[1] == EOL) {
2974: j = TRUE;
2975:
2976: if (ftyp == 3) {
2977: i = 0;
2978:
2979: while ((ch = flim[i]) != EOL) {
2980:
2981: if (ch < '0' || ch > '9') j = FALSE;
2982:
2983: i++;
2984: }
2985:
2986: fi = i;
2987: fori[forx] = i;
2988: }
2989:
2990: if (j && ((ch = *codptr) == SP || ch == EOL)) {
2991: ftyp += 2;
2992: if (ch == SP) codptr++;
2993: }
2994: }
2995:
2996: for_go:
2997:
2998: fortyp[forx] = ftyp;
2999:
3000:
3001: #ifdef DEBUG_NEWSTACK
3002: if (!cmdptr) printf ("CMDPTR is ZERO!\r\n");
3003: #endif
3004:
3005: nestp[nstx] = cmdptr;
3006:
3007: cmdptr += stcpy (cmdptr, codptr) + 1;
3008:
3009: if (ftyp > 3) goto next_cmnd;
3010:
3011: /* skip following for arguments if there are any */
3012:
3013: for10:
3014:
3015: if (*codptr == SP) goto next_cmnd;
3016:
3017: i = 0;
3018:
3019: while ((((ch = *codptr) != SP) || i) && ch != EOL) {
3020: if (ch == '"') i = !i;
3021:
3022: codptr++;
3023: } /* skip rest of FOR list */
3024:
3025: goto next_cmnd;
3026:
3027: for_end: /* end of line return */
3028:
3029: #ifdef DEBUG_NEWSTACK
3030: printf ("For_end: nstx: %d, Nestp: (%d)\r\n", nstx, nestp[nstx]);
3031: #endif
3032:
3033: stcpy (codptr = code, nestp[nstx]); /* restore old pointers */
3034:
3035:
3036:
3037: switch (ftyp) {
3038:
3039: case 5: /* frequent special case: increment 1 */
3040: symtab (getinc, fvar, tmp);
3041:
3042: /* compare fvar-value to flim-value */
3043: /* fi: i=0; while (flim[i]>='0') i++; */
3044: /* Note: EOL<'-'<'.'<'0' tmp has at least one character */
3045: ch = '0';
3046: j = 1;
3047:
3048: while (tmp[j] >= ch) j++;
3049:
3050: if (j < fi) goto next_cmnd;
3051:
3052: if (j == fi) {
3053: j = 0;
3054:
3055: while (tmp[j] == flim[j]) {
3056: if (tmp[j] == EOL) goto next_cmnd;
3057: j++;
3058: }
3059:
3060: if (tmp[j] <= flim[j]) goto next_cmnd;
3061: }
3062:
3063: if (flim[0] != '-' && tmp[0] == '-') goto next_cmnd;
3064:
3065: stcpy (tmp2, "-1\201"); /* correct last inc */
3066: add (tmp, tmp2);
3067: symtab (set_sym, fvar, tmp);
3068:
3069: goto for_quit;
3070:
3071: case 4: /* frequent special case: increment 1 without limit */
3072: symtab (getinc, fvar, tmp);
3073:
3074:
3075: case 0: /* argumentless FOR */
3076:
3077: if(argless_forsw_quit == TRUE) {
3078: /* if we have a positive QUIT condition, bail from the FOR loop */
3079: argless_forsw_quit = FALSE;
3080: goto for_quit;
3081: }
3082: else {
3083:
3084: /* otherwise, just keep on truckin' */
3085: goto next_cmnd;
3086: }
3087:
3088: case 3: /* FOR with increment and limit test */
3089: symtab (get_sym, fvar, tmp);
3090: numlit (tmp);
3091: stcpy (tmp2, finc); /* add may change forinc */
3092: add (tmp, tmp2);
3093:
3094: if (*finc != '-') {
3095: if (comp (flim, tmp)) goto for_quit;
3096: }
3097: else {
3098: if (comp (tmp, flim)) goto for_quit;
3099: }
3100:
3101: symtab (set_sym, fvar, tmp);
3102:
3103: goto for10;
3104:
3105: case 2: /* FOR with increment without limit test */
3106: symtab (get_sym, fvar, tmp);
3107: numlit (tmp);
3108: stcpy (tmp2, finc); /* add may change forinc */
3109: add (tmp, tmp2);
3110:
3111: symtab (set_sym, fvar, tmp);
3112: goto for10;
3113: } /* end switch */
3114:
3115: for_quit:
3116:
3117: cmdptr = nestp[nstx];
3118:
3119:
3120: if (*codptr++ == ',') goto for_nxt_arg;
3121:
3122: forpost[forx][0] = '\0';
3123:
3124: nstx--;
3125: estack--;
3126:
3127: forx--;
3128: ftyp = fortyp[forx];
3129: fvar = forvar[forx];
3130: finc = forinc[forx];
3131: flim = forlim[forx];
3132: fi = fori[forx];
3133:
3134:
3135: if ((forsw = (nestc[nstx] == FOR))) goto for_end;
3136:
3137: if (sigint_in_for) {
3138: merr_raise (INRPT);
3139: sigint_in_for = FALSE;
3140: }
3141:
3142: if (merr () > OK) goto err;
3143: goto next_line;
3144:
3145: case MERGE:
3146:
3147: {
3148: char lhs[256];
3149: char rhs[256];
3150:
3151: char k_buf[STRLEN];
3152:
3153: if ((rtn_dialect () != D_M95) &&
3154: (rtn_dialect () != D_MDS) &&
3155: (rtn_dialect () != D_M5) &&
3156: (rtn_dialect () != D_FREEM)) {
3157: merr_raise (NOSTAND);
3158: goto err;
3159: }
3160:
3161: expr (NAME);
3162: if (merr () > OK) break;
3163:
3164: key_to_name (lhs, varnam, 255);
3165: stcnv_c2m (lhs);
3166:
3167: if (*++codptr != '=') {
3168: merr_raise (ASSIGNER);
3169: break;
3170: }
3171:
3172: codptr++;
3173:
3174: expr (NAME);
3175: if (merr () > OK) break;
3176:
3177: codptr++;
3178:
3179: key_to_name (rhs, varnam, 255);
3180: stcnv_c2m (rhs);
3181:
3182: stcpy (k_buf, "%INTMERGELHS\201\201");
3183: symtab (set_sym, k_buf, lhs);
3184:
3185: stcpy (k_buf, "%INTMERGERHS\201\201");
3186: symtab (set_sym, k_buf, rhs);
3187:
3188: stcpy (&tmp3[1], "SYSWMERGE \201");
3189: goto private;
3190:
3191: break;
3192:
3193: }
3194:
3195:
3196: case RLOAD:
3197: if ((rtn_dialect () != D_MDS) &&
3198: (rtn_dialect () != D_FREEM)) {
3199: merr_raise (NOSTAND);
3200: goto err;
3201: }
3202: stcpy (&tmp3[1], "zrload \201");
3203: goto private;
3204:
3205:
3206: case RSAVE:
3207: if ((rtn_dialect () != D_MDS) &&
3208: (rtn_dialect () != D_FREEM)) {
3209: merr_raise (NOSTAND);
3210: goto err;
3211: }
3212:
3213: stcpy (&tmp3[1], "zrsave \201");
3214: goto private;
3215:
3216:
3217: case XECUTE:
3218:
3219:
3220: do_xecute:
3221: expr (STRING);
3222:
3223: if (merr () > OK) break;
3224:
3225: stcpy (tmp, argptr);
3226:
3227: if (*codptr == ':') { /* argument postcond */
3228: codptr++;
3229: expr (STRING);
3230:
3231: if (merr () > OK) break;
3232: if (tvexpr (argptr) == FALSE) break;
3233: }
3234:
3235: if (++nstx > NESTLEVLS) {
3236: nstx--;
3237: merr_raise (STKOV);
3238:
3239: break;
3240: }
3241: else {
3242: estack++;
3243: }
3244:
3245:
3246: #ifdef DEBUG_NEWSTACK
3247: if (!cmdptr) printf ("CMDPTR is ZERO!\r\n");
3248: #endif
3249:
3250: nestc[nstx] = XECUTE;
3251: nestp[nstx] = cmdptr; /* command stack address */
3252: nestr[nstx] = roucur - rouptr; /* save roucur */
3253: nestlt[nstx] = level;
3254:
3255: level = 0; /* save level */
3256: nestnew[nstx] = 0;
3257: ztrap[nstx][0] = EOL;
3258:
3259: while ((*(namptr++)) != EOL);
3260:
3261: stcpy ((nestn[nstx] = namptr), rou_name); /* save routine name */
3262:
3263: forsw = FALSE;
3264: loadsw = FALSE;
3265: cmdptr += stcpy (cmdptr, codptr) + 1;
3266:
3267: stcpy (code, tmp);
3268:
3269: roucur = buff + (NO_OF_RBUF * PSIZE0 + 1);
3270: codptr = code;
3271:
3272: goto next_cmnd;
3273:
3274:
3275: case DO:
3276:
3277: if (evt_async_initial == TRUE) {
3278: evt_async_initial = FALSE;
3279: }
3280: else {
3281: evt_depth++;
3282: }
3283:
3284: rouoldc = roucur - rouptr;
3285: namold = 0;
3286:
3287: case GOTO:
3288:
3289: do_goto:
3290:
3291: if (trace_mode) {
3292: char rn[256];
3293: stcpy (rn, rou_name);
3294: stcnv_m2c (rn);
3295:
3296: switch (mcmnd) {
3297: case DO:
3298: snprintf (tracestr, sizeof (tracestr) - 1, "rtn = %s $stack = %d do ", rn, nstx);
3299: break;
3300: case GOTO:
3301: snprintf (tracestr, sizeof (tracestr) - 1, "rtn = %s $stack = %d goto ", rn, nstx);
3302: break;
3303: }
3304: }
3305:
3306: offset = 0;
3307: label[0] = routine[0] = EOL;
3308: dofram0 = 0;
3309:
3310: if (((ch = *codptr) != '+') && (ch != '^')) { /* parse label */
3311:
3312: if (ch == SP || ch == EOL) { /* no args: blockstructured DO */
3313:
3314: if (mcmnd != DO) {
3315: merr_raise (ARGLIST);
3316: break;
3317: }
3318:
3319: /* direct mode: DO +1 */
3320:
3321:
3322: if (nstx == 0 && roucur >= rouend) {
3323: roucu0 = rouptr;
3324: goto off1;
3325: }
3326:
3327: mcmnd = DO_BLOCK;
3328: roucu0 = roucur; /* continue with next line */
3329: forsw = FALSE;
3330:
3331: goto off2;
3332: }
3333:
3334: expr (LABEL);
3335:
3336: if (merr () > OK) goto err;
3337:
3338: stcpy (label, varnam);
3339:
3340: if (trace_mode) {
3341: char ttt[256];
3342: stcpy (ttt, label);
3343: stcnv_m2c (ttt);
3344:
3345: strcat (tracestr, ttt);
3346: }
3347:
3348: ch = *++codptr;
3349: }
3350:
3351: if (ch == '+') { /* parse offset */
3352:
3353: codptr++;
3354: expr (OFFSET);
3355:
3356: if (merr () > OK) goto err;
3357:
3358: offset = intexpr (argptr);
3359: dosave[0] = EOL;
3360:
3361: /* unless argument is numeric, expr returns wrong codptr */
3362: if ((ch = *codptr) != SP && (ch != EOL) && (ch != ',') && (ch != '^')) ch = *++codptr;
3363:
3364: if (trace_mode) {
3365: char ttt[256];
3366: snprintf (ttt, 255, "+%d", offset);
3367: strcat (tracestr, ttt);
3368: }
3369: }
3370:
3371: if (ch == '^') { /* parse routine */
3372: codptr++;
3373: expr (LABEL);
3374:
3375: if (merr () > OK) goto err;
3376:
3377: stcpy (routine, varnam);
3378:
3379: if (trace_mode) {
3380: char ttt[256];
3381: char ttx[256];
3382:
3383: stcpy (ttt, routine);
3384: stcnv_m2c (ttt);
3385: snprintf (ttx, 255, "^%s", ttt);
3386: strcat (tracestr, ttx);
3387: }
3388:
3389: dosave[0] = EOL;
3390: ch = *++codptr;
3391: loadsw = TRUE;
3392: }
3393:
3394: if (trace_mode) {
3395: fprintf (stderr, ">> TRACE: %s\r\n", tracestr);
3396: }
3397:
3398: if (ch == '(' && mcmnd == DO) { /* parse parameter */
3399:
3400: if (offset) {
3401: merr_raise (ARGLIST);
3402: goto err;
3403: }
3404:
3405: if (*++codptr == ')') {
3406: ch = *++codptr;
3407: }
3408: else {
3409: dofram0 = dofrmptr;
3410: i = 0;
3411:
3412: for (;;) {
3413: setpiece = TRUE; /* to avoid error on closing bracket */
3414:
3415: if (*codptr == '.' && (*(codptr + 1) < '0' || *(codptr + 1) > '9')) {
3416: codptr++;
3417:
3418: expr (NAME);
3419: codptr++;
3420:
3421: *dofrmptr++ = DELIM; /* to indicate call by name */
3422: dofrmptr += stcpy (dofrmptr, varnam) + 1;
3423: }
3424: else {
3425: expr (STRING);
3426: dofrmptr += stcpy (dofrmptr, argptr) + 1;
3427: }
3428:
3429: setpiece = FALSE;
3430: i++;
3431:
3432: if (merr () > OK) {
3433: dofrmptr = dofram0;
3434: goto err;
3435: }
3436:
3437: ch = *codptr++;
3438: if (ch == ',') continue;
3439:
3440: if (ch != ')') {
3441: merr_raise (COMMAER);
3442: dofrmptr = dofram0;
3443:
3444: goto err;
3445: }
3446:
3447: ch = *codptr;
3448: break;
3449: }
3450: }
3451: }
3452:
3453: if (ch == ':') { /* parse postcond */
3454:
3455: codptr++;
3456: expr (STRING);
3457:
3458: if (merr () > OK) {
3459: if (dofram0) dofrmptr = dofram0; /* reset frame pointer */
3460: goto err;
3461: }
3462:
3463: if (tvexpr (argptr) == FALSE) {
3464: if (*codptr != ',') mcmnd = 0; /* avoid false LEVEL Error */
3465: if (dofram0) dofrmptr = dofram0; /* reset frame pointer */
3466:
3467: break;
3468: }
3469: }
3470:
3471: if (mcmnd == GOTO) { /* GOTO: clear FORs from stack */
3472:
3473: #ifdef DEBUG_NEWSTACK
3474: printf ("CHECK 05 Multi-POP on FOR\r\n");
3475: #endif
3476:
3477:
3478:
3479: while (nestc[nstx] == FOR) {
3480:
3481: #ifdef DEBUG_NEWSTACK
3482: printf ("POP");
3483: #endif
3484:
3485: cmdptr = nestp[nstx--];
3486: estack--;
3487:
3488: forx--;
3489: ftyp = fortyp[forx];
3490: fvar = forvar[forx];
3491: finc = forinc[forx];
3492: flim = forlim[forx];
3493: fi = fori[forx];
3494: }
3495:
3496: #ifdef DEBUG_NEWSTACK
3497: printf ("\r\n");
3498: #endif
3499:
3500:
3501: loadsw = TRUE;
3502: }
3503:
3504: job_entry: /* entry called from successful JOB */
3505:
3506: if (routine[0] != EOL) {
3507:
3508: #ifdef DEBUG_NEWSTACK
3509: printf ("CHECK 06\r\n");
3510: #endif
3511:
3512: if (mcmnd == DO) {
3513:
3514: while ((*(namptr++)) != EOL);
3515:
3516: namold = namptr;
3517: stcpy (namptr, rou_name);
3518:
3519: ssvn_job_update ();
3520:
3521: }
3522:
3523: /* if (GOTO label^rou) under a (DO label) */
3524: /* save away old routine to restore on quit */
3525:
3526:
3527:
3528: else if (nstx > 0) {
3529:
3530: #ifdef DEBUG_NEWSTACK
3531: printf ("CHECK 06, stack is greater than 0\r\n");
3532: #endif
3533:
3534: while (nestc[nstx] == FOR) {
3535: #ifdef DEBUG_NEWSTACK
3536: printf ("POP");
3537: #endif
3538:
3539: nstx--;
3540: estack--;
3541: forx--;
3542: ftyp = fortyp[forx];
3543: fvar = forvar[forx];
3544: finc = forinc[forx];
3545: flim = forlim[forx];
3546: fi = fori[forx];
3547: }
3548:
3549: if (nestn[nstx] == 0) {
3550: while ((*(namptr++)) != EOL);
3551:
3552: stcpy ((nestn[nstx] = namptr), rou_name);
3553: }
3554: }
3555:
3556: zload (routine);
3557: if (merr () > OK) goto err; /* load file */
3558:
3559: ssvn_job_update ();
3560:
3561: } /* if (routine[0] != EOL) */
3562: {
3563: char *reg, *reg1;
3564:
3565: reg1 = rouptr;
3566: reg = reg1;
3567:
3568: if (label[0] != EOL) {
3569:
3570: if (forsw && mcmnd == DO && stcmp (label, dosave) == 0) {
3571: roucu0 = xdosave;
3572: goto off1;
3573: }
3574:
3575: while (reg < rouend) {
3576: reg++;
3577: j = 0;
3578:
3579: while (*reg == label[j]) {
3580: reg++;
3581: j++;
3582: }
3583:
3584: if (label[j] == EOL) {
3585:
3586: if (*reg == TAB || *reg == SP) goto off;
3587:
3588: /* call of procedure without specifying a parameter list */
3589: if (*reg == '(') {
3590: if (dofram0 == 0) dofram0 = dofrmptr;
3591: goto off;
3592: }
3593:
3594: }
3595:
3596: reg = (reg1 = reg1 + UNSIGN (*reg1) + 2);
3597: }
3598: {
3599: merr_raise (M13);
3600: stcpy (varerr, label); /* to be included in error message */
3601:
3602: if (dofram0) dofrmptr = dofram0; /* reset frame pointer */
3603:
3604: zload (rou_name);
3605: ssvn_job_update ();
3606: goto err;
3607: }
3608: }
3609: off:
3610: if (label[0] == EOL && offset > 0) offset--;
3611: while (offset-- > 0) reg1 = reg1 + (UNSIGN (*reg1) + 2);
3612:
3613: if (forsw) {
3614: xdosave = reg1;
3615: stcpy (dosave, label);
3616: }
3617:
3618: roucu0 = reg1;
3619: }
3620:
3621: if (roucu0 >= rouend) {
3622: merr_raise (M13);
3623: stcpy (varerr, label); /* to be included in error message */
3624:
3625: if (dofram0) dofrmptr = dofram0; /* reset frame pointer */
3626:
3627: zload (rou_name);
3628: ssvn_job_update ();
3629: goto err;
3630: }
3631:
3632: off1:
3633: if (routine[0] != EOL) stcpy (rou_name, routine);
3634:
3635: ssvn_job_update ();
3636:
3637: roucu0++;
3638: forsw = FALSE;
3639:
3640: if (mcmnd != DO) { /* i.e. GOTO or JOB */
3641: roucur = roucu0;
3642: goto off3;
3643: }
3644:
3645: off2:
3646:
3647: #ifdef DEBUG_NEWSTACK
3648: printf ("CHECK 07 (Stack PUSH)\r\n");
3649: #endif
3650:
3651:
3652:
3653: if (++nstx > NESTLEVLS) {
3654: nstx--;
3655: merr_raise (STKOV);
3656:
3657: goto err;
3658: }
3659: else {
3660: on_frame_entry ();
3661: estack++;
3662: }
3663:
3664: nestc[nstx] = mcmnd;
3665:
3666: #ifdef DEBUG_NEWSTACK
3667: if (!cmdptr) printf ("CMDPTR is ZERO!\r\n");
3668: #endif
3669:
3670: nestp[nstx] = cmdptr;
3671: nestn[nstx] = namold;
3672: nestr[nstx] = rouoldc;
3673: nestnew[nstx] = 0;
3674:
3675: if (mcmnd != DO_BLOCK) {
3676: nestlt[nstx] = level;
3677: level = 0;
3678: }
3679: else { /* push level ; clr level */
3680: nestlt[nstx] = test;
3681: level++;
3682: } /* push $TEST ; inc level */
3683:
3684: ztrap[nstx][0] = EOL;
3685:
3686:
3687: cmdptr += stcpy (cmdptr, codptr) + 1;
3688: roucur = roucu0;
3689:
3690: /* processing for private Z-Command: */
3691: if (privflag) {
3692:
3693:
3694:
3695: #ifdef DEBUG_NEWPTR
3696: printf ("Xecline 01 (using NEWPTR): ");
3697: printf ("[nstx] is [%d], [nestnew] is [%d]", nstx, nestnew[nstx]);
3698: printf ("- Initialized to newptr\r\n");
3699: #endif /* Debug */
3700:
3701: nestnew[nstx] = newptr;
3702:
3703:
3704: stcpy (vn, zargdefname);
3705:
3706: /*was: vn[0] = '%'; vn[1] = EOL; */
3707:
3708: symtab (new_sym, vn, "");
3709: /*djw change 'input variable for Z command' to get value of $V(202) */
3710: /*was: vn[0] = '%'; vn[1] = EOL; */
3711:
3712: stcpy (vn, zargdefname);
3713: symtab (set_sym, vn, tmp2);
3714:
3715: privflag = FALSE;
3716: }
3717:
3718: off3:
3719:
3720: if (dofram0) {
3721: char *reg, *reg1;
3722:
3723: reg = roucu0;
3724: reg1 = dofram0;
3725:
3726: while ((ch = (*reg++)) != '(') {
3727: if (ch == SP || ch == TAB || ch == EOL) break;
3728: }
3729:
3730: if (ch != '(') {
3731: merr_raise (TOOPARA);
3732: dofrmptr = dofram0;
3733:
3734: goto err;
3735: }
3736:
3737: j = 0;
3738:
3739: while ((ch = (*reg++)) != EOL) {
3740:
3741: if ((ch == ',' && j) || ch == ')') {
3742: varnam[j] = EOL;
3743:
3744:
3745:
3746: #ifdef DEBUG_NEWPTR
3747: printf ("Xecline 02: ");
3748: printf ("[nstx] is [%d], [nestnew] is [%d]\r\n", nstx, nestnew[nstx]);
3749: #endif
3750:
3751: if (nestnew[nstx] == 0) nestnew[nstx] = newptr;
3752:
3753:
3754:
3755: if (reg1 < dofrmptr) {
3756:
3757: if (*reg1 == DELIM) { /* call by reference */
3758:
3759: if (stcmp (reg1 + 1, varnam)) { /* are they different?? */
3760: symtab (new_sym, varnam, "");
3761: symtab (m_alias, varnam, reg1 + 1);
3762: }
3763:
3764: }
3765: else {
3766: symtab (new_sym, varnam, ""); /* call by value */
3767: symtab (set_sym, varnam, reg1);
3768: }
3769:
3770: reg1 += stlen (reg1) + 1;
3771: }
3772: else {
3773: symtab (new_sym, varnam, "");
3774: }
3775:
3776: if (ch == ')') break;
3777:
3778: j = 0;
3779: continue;
3780: }
3781:
3782: if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9' && j) || (ch == '%' && j == 0)) {
3783: varnam[j++] = ch;
3784: continue;
3785: }
3786:
3787: merr_raise (ARGLIST);
3788: dofrmptr = dofram0; /* reset frame pointer */
3789:
3790: goto err;
3791: }
3792:
3793: if (reg1 < dofrmptr) {
3794: merr_raise (TOOPARA);
3795: dofrmptr = dofram0;
3796:
3797: goto err;
3798: }
3799:
3800: dofrmptr = dofram0;
3801: }
3802:
3803: goto next_line;
3804:
3805: /* ZJOB *//* same as JOB, but without timeout */
3806: /* not recommended; just for backward compatibility */
3807: case ZJOB:
3808: if (is_standard ()) {
3809: merr_raise (NOSTAND);
3810: goto err;
3811: }
3812:
3813: case JOB:
3814:
3815: if (rtn_dialect () == D_M77) {
3816: merr_raise (NOSTAND);
3817: goto err;
3818: }
3819:
3820: if (*codptr == SP || *codptr == EOL) {
3821: merr_raise (M13);
3822: varerr[0] = EOL; /* to be included in error message */
3823:
3824: break;
3825: }
3826:
3827: loadsw = TRUE;
3828: offset = 0;
3829: frm_timeout = (-1L);
3830: label[0] = routine[0] = EOL;
3831:
3832: if (((ch = *codptr) != '+') && (ch != '^')) { /* parse label */
3833: expr (LABEL);
3834: if (merr () > OK) goto err;
3835:
3836: stcpy (label, varnam);
3837:
3838: ch = *++codptr;
3839: }
3840:
3841: if (ch == '+') { /* parse offset */
3842: codptr++;
3843:
3844: expr (OFFSET);
3845: if (merr () > OK) goto err;
3846:
3847: offset = intexpr (argptr);
3848:
3849: /* unless argument is numeric, expr returns wrong codptr */
3850: if ((ch = *codptr) != SP && (ch != EOL) && (ch != ',') && (ch != '^')) ch = *++codptr;
3851:
3852: }
3853:
3854: if (ch == '^') { /* parse routine */
3855: codptr++;
3856:
3857: expr (LABEL);
3858: if (merr () > OK) goto err;
3859:
3860: stcpy (routine, varnam);
3861:
3862: dosave[0] = EOL;
3863: ch = *++codptr;
3864: }
3865:
3866: dofram0 = NULL;
3867: if (ch == '(') { /* parse parameter */
3868:
3869: if (offset) {
3870: merr_raise (ARGLIST);
3871: goto err;
3872: }
3873:
3874: codptr++;
3875: dofram0 = dofrmptr;
3876:
3877: i = 0;
3878: for (;;) {
3879: setpiece = TRUE; /* to avoid error on closing bracket */
3880:
3881: if (*codptr == '.' && (*(codptr + 1) < '0' || *(codptr + 1) > '9')) {
3882: codptr++;
3883:
3884: expr (NAME);
3885:
3886: codptr++;
3887:
3888: *dofrmptr++ = DELIM; /* to indicate call by name */
3889: dofrmptr += stcpy (dofrmptr, varnam) + 1;
3890: }
3891: else {
3892: expr (STRING);
3893: dofrmptr += stcpy (dofrmptr, argptr) + 1;
3894: }
3895:
3896: setpiece = FALSE;
3897: i++;
3898:
3899: if (merr () > OK) {
3900: dofrmptr = dofram0;
3901: goto err;
3902: }
3903:
3904: ch = *codptr++;
3905: if (ch == ',') continue;
3906:
3907: if (ch != ')') {
3908: merr_raise (COMMAER);
3909: dofrmptr = dofram0;
3910:
3911: goto err;
3912: }
3913:
3914: ch = *codptr;
3915: break;
3916: }
3917: }
3918:
3919: if (ch == ':' && *(codptr + 1) == ch) {
3920: codptr++; /* timeout,no jobparams */
3921: }
3922: else if (ch == ':' && *(codptr + 1) == '(') { /* parse any 'job parameters', but ignore them otherwise */
3923: codptr++;
3924: setpiece = TRUE; /* to avoid bracket error at end of jobparameters */
3925:
3926: for (;;) {
3927: if (*++codptr != ':') expr (STRING);
3928: if (*codptr == ':') continue;
3929: if (*codptr++ != ')') merr_raise (ARGER);
3930:
3931: break;
3932: }
3933:
3934: setpiece = FALSE;
3935: ch = (*codptr);
3936: }
3937:
3938: if (ch == ':') { /* timeout */
3939: codptr++;
3940: expr (STRING);
3941:
3942: if ((frm_timeout = intexpr (argptr)) < 0L) frm_timeout = 0L;
3943: if (merr () > OK) goto err;
3944:
3945: test = TRUE;
3946: }
3947:
3948: if (mcmnd == ZJOB) frm_timeout = 0L; /* ZJOB-command has timeout 0 */
3949:
3950: close_all_globals (); /* close all globals */
3951: j = getpid (); /* job number of father process */
3952:
3953: if (lonelyflag) { /* single user */
3954: if (frm_timeout < 0L) {
3955: merr_raise (PROTECT); /* error without timeout */
3956: }
3957: else {
3958: test = FALSE; /* timeout always fails */
3959: }
3960:
3961: break;
3962: }
3963:
3964: while ((i = fork ()) == -1) {
3965:
3966: if (frm_timeout == 0L) {
3967: test = FALSE;
3968: break;
3969: }
3970:
3971: if (frm_timeout > 0L) frm_timeout--;
3972:
3973: sleep (1);
3974:
3975: }
3976:
3977: if (mcmnd == ZJOB && zjobflag) {
3978:
3979: if (i == 0) { /* we are in child process */
3980: intstr (zb, j); /* $JOB of father job */
3981:
3982: father = j;
3983: pid = getpid (); /* this is our new job number */
3984:
3985: jobtime = time (0L);;
3986:
3987:
3988: nstx = 0; /* clear stack */
3989: estack = 0;
3990:
3991: forx = 0;
3992: forsw = FALSE;
3993: level = 0;
3994: cmdptr = cmdstack; /* - command stack pointer */
3995: namptr = namstck; /* - routine name stack pointer */
3996: usermode = 0; /* application mode */
3997: merr_clear ();
3998:
3999: lock (" \201", -1, 'j'); /* tell lock about JOB */
4000: goto job_entry;
4001: }
4002:
4003: /* ignore signal while here */
4004: sig_attach (SIGUSR1, SIG_IGN);
4005:
4006: while (wait (&zsystem) != i);
4007:
4008: sig_attach (SIGUSR1, &oncld); /* restore handler */
4009:
4010: merr_clear (); /* there might be a INRPT from other job */
4011:
4012: set_io (MUMPS);
4013: break;
4014: }
4015:
4016: if (i == 0) { /* we are in child process */
4017:
4018: intstr (zb, j); /* $JOB of father job */
4019: father = j;
4020:
4021: pid = getpid (); /* $J = process ID */
4022: usermode = 0; /* no programmer mode */
4023: DSW |= BIT0; /* disable echo */
4024: zbreakon = DISABLE; /* disable CTRL/B */
4025: breakon = DISABLE; /* disable CTRL/C */
4026: hardcopy = DISABLE; /* disable hardcopy function */
4027:
4028: fclose (stdin); /* close normal input */
4029:
4030: jour_flag = 0; /* no protocol */
4031:
4032:
4033: nstx = 0; /* clear stack */
4034: estack = 0;
4035:
4036: forx = 0;
4037: forsw = FALSE;
4038: level = 0;
4039:
4040: cmdptr = cmdstack; /* - command stack pointer */
4041: namptr = namstck; /* - routine name stack pointer */
4042:
4043: /* init random number */
4044: if ((nrandom = time (0L) * getpid ()) < 0) nrandom = (-nrandom);
4045:
4046: merr_clear ();
4047: lock (" \201", -1, 'j'); /* tell lock about JOB */
4048:
4049: goto job_entry;
4050: }
4051:
4052: intstr (zb, i); /* $JOB of the process just started */
4053: break;
4054:
4055: case KILL:
4056:
4057: /* argumentless: KILL all local variables */
4058: if (((ch = *codptr) == SP) || ch == EOL) {
4059: symtab (kill_all, "", "");
4060: break;
4061: }
4062:
4063: if (ch != '(') {
4064: char destc[255];
4065: register int cd;
4066:
4067: destc[0] = '\0';
4068:
4069: expr (NAME);
4070:
4071: /* aviod a disaster if someone types KILL ^PATDAT[TEST] ! */
4072: if (((ch = *++codptr) != SP) && ch != EOL && ch != ',') merr_raise (INVREF);
4073: if (merr () > OK) goto err;
4074:
4075: if (varnam[0] == '^') {
4076: if (varnam[1] != '$') {
4077: global (kill_sym, varnam, tmp);
4078: }
4079: else {
4080: ssvn (kill_sym, varnam, tmp);
4081: }
4082: break;
4083: }
4084:
4085: symtab (kill_sym, varnam, tmp);
4086:
4087: if (destructor_ct) {
4088:
4089: for (cd = 0; cd < destructor_ct; cd++) {
4090: if (strlen (destructors[cd]) > 0) {
4091: strcat (destc, destructors[cd]);
4092: strcat (destc, ",");
4093: }
4094: }
4095:
4096: destructor_ct = 0;
4097: destc[strlen(destc) - 1] = '\201';
4098:
4099: stcpy (&tmp3[1], destc);
4100: destructor_run = TRUE;
4101:
4102: goto private;
4103: }
4104:
4105:
4106: break;
4107: }
4108:
4109: /* exclusive kill */
4110: tmp[0] = SP;
4111: tmp[1] = EOL;
4112:
4113: for (;;) {
4114:
4115: codptr++;
4116: expr (NAME);
4117:
4118: if (merr () > OK) goto err;
4119:
4120: if (varnam[0] == '^') {
4121: merr_raise (GLOBER);
4122: goto err;
4123: }
4124:
4125: i = 0;
4126: while (varnam[i] != EOL) {
4127:
4128: if (varnam[i] == DELIM) {
4129: merr_raise (SBSCR);
4130: goto err;
4131: }
4132:
4133: i++;
4134: }
4135:
4136: if (stcat (tmp, varnam) == 0) {
4137: merr_raise (M75);
4138: goto err;
4139: }
4140:
4141: if (stcat (tmp, " \201") == 0) {
4142: merr_raise (M75);
4143: goto err;
4144: }
4145:
4146: if ((ch = *++codptr) == ')') {
4147: codptr++;
4148: break;
4149: }
4150:
4151: if (ch != ',') {
4152: merr_raise (COMMAER);
4153: goto err;
4154: }
4155: }
4156:
4157: symtab (killexcl, tmp, "");
4158: break;
4159:
4160: case NEWCMD:
4161: if ((rtn_dialect () == D_M77) ||
4162: (rtn_dialect () == D_M84)) {
4163: merr_raise (NOSTAND);
4164: goto err;
4165: }
4166: /*case ZNEW:*/
4167:
4168: /* argumentless: NEW all local variables */
4169: if (((ch = *codptr) == SP) || ch == EOL) {
4170: ch = nstx;
4171:
4172: while (nestc[ch] == FOR) ch--; /* FOR does not define a NEW level */
4173:
4174: #ifdef DEBUG_NEWPTR
4175: printf ("Xecline 03: (TODO - NEW ALL) ");
4176: printf ("[ch] is %d, [nestnew] is %d\r\n", ch, nestnew[ch]);
4177: #endif
4178:
4179: if (nestnew[ch] == 0) nestnew[ch] = newptr;
4180:
4181: symtab (new_all, "", "");
4182: break;
4183: }
4184:
4185: if (ch != '(') {
4186: expr (NAME);
4187:
4188: if (merr () > OK) goto err;
4189:
4190: codptr++;
4191:
4192: if (varnam[0] == '^') {
4193: merr_raise (GLOBER);
4194: goto err;
4195: }
4196:
4197: if (varnam[0] == '$') {
4198: i = 0;
4199:
4200: while ((ch = varnam[++i]) != EOL) if (ch >= 'A' && ch <= 'Z') varnam[i] = ch + 32;
4201:
4202: /* set $reference */
4203: if ((stcmp (&varnam[1], "r\201")) && (stcmp (&varnam[1], "reference\201")) && (stcmp (&varnam[1], "zr\201")) && (stcmp (&varnam[1], "zreference\201")) &&
4204: (stcmp (&varnam[1], "t\201")) && (stcmp (&varnam[1], "test\201")) && (stcmp (&varnam[1], "j\201")) && (stcmp (&varnam[1], "job\201")) &&
4205: (stcmp (&varnam[1], "zi\201")) && (stcmp (&varnam[1], "zinrpt\201")) && (stcmp (&varnam[1], "et\201")) && (stcmp (&varnam[1], "etrap\201")) &&
4206: (stcmp (&varnam[1], "es\201")) && (stcmp (&varnam[1], "estack\201"))) {
4207: merr_raise (INVREF);
4208: goto err;
4209: }
4210: }
4211:
4212: /* new and set, new object */
4213: if (*codptr == '=') {
4214:
4215: if ((rtn_dialect () != D_FREEM)) {
4216: merr_raise (NOSTAND);
4217: goto err;
4218: }
4219:
4220: codptr++;
4221: stcpy (vn, varnam);
4222:
4223: if (*codptr != '$') {
4224: /* this is a new-and-set */
4225: expr (STRING);
4226: new_and_set = TRUE;
4227: }
4228: else {
4229: if ((*codptr == '$') &&
4230: (*(codptr + 1) == '#') &&
4231: (*(codptr + 2) == '^')) {
4232:
4233: char class[255];
4234: char constructor[255];
4235: char objvar[255];
4236: char datres[5];
4237: int dat_res;
4238:
4239: stcpy (objvar, vn);
4240:
4241: symtab (fra_dat, objvar, datres);
4242: dat_res = atoi (datres);
4243:
4244: if (dat_res > 0) {
4245: merr_raise (OBJCONFLICT);
4246: goto err;
4247: }
4248:
4249: stcnv_m2c (objvar);
4250:
4251: codptr += 2;
4252:
4253: /* this is probably an object instantiation */
4254: expr (NAME);
4255: if (merr () > OK) goto err;
4256:
4257: stcpy (class, varnam);
4258: stcnv_m2c (class);
4259: new_object = TRUE;
4260: codptr++;
4261:
4262: obj_get_constructor (constructor, class, objvar);
4263:
4264: for (dat_res = 0; dat_res < strlen (class); dat_res++) {
4265: if (class[dat_res] == '\202') {
4266: class[dat_res] = '\0';
4267: break;
4268: }
4269: }
4270:
4271: obj_create_symbols (objvar, class);
4272:
4273: if (merr () > OK) goto err;
4274:
4275: /* TODO: check this snprintf for proper sizing */
4276: snprintf (&tmp3[1], 255, "%s\201", &constructor[1]);
4277: goto private;
4278:
4279: }
4280: else {
4281: if (*codptr == '$') {
4282: expr (STRING);
4283: new_and_set = TRUE;
4284: }
4285: else {
4286: merr_raise (ILLFUN);
4287: goto err;
4288: }
4289: }
4290: }
4291:
4292:
4293: goto set2;
4294: }
4295:
4296: /*
4297: post_new:
4298: */
4299: ch = nstx;
4300:
4301: while (nestc[ch] == FOR) ch--; /* FOR does not define a NEW level */
4302:
4303: #ifdef DEBUG_NEWPTR
4304: printf ("Xecline 04 (DANGER): ");
4305: printf ("[ch] is %d, [nestnew] is %d\r\n", ch, nestnew[ch]);
4306: #endif
4307:
4308: if (nestnew[ch] == 0) nestnew[ch] = newptr;
4309:
4310: symtab (new_sym, varnam, "");
4311: break;
4312: }
4313:
4314: /* exclusive new */
4315: tmp[0] = SP;
4316: tmp[1] = EOL;
4317:
4318: for (;;) {
4319: codptr++;
4320: expr (NAME);
4321:
4322: if (merr () > OK) goto err;
4323:
4324: if (varnam[0] == '^') {
4325: merr_raise (GLOBER);
4326: goto err;
4327: }
4328:
4329: if (varnam[0] == '$') {
4330: merr_raise (INVREF);
4331: goto err;
4332: }
4333:
4334: i = 0;
4335: while (varnam[i] != EOL) {
4336:
4337: if (varnam[i] == DELIM) {
4338: merr_raise (SBSCR);
4339: goto err;
4340: }
4341:
4342: i++;
4343: }
4344:
4345: if (stcat (tmp, varnam) == 0) {
4346: merr_raise (M75);
4347: goto err;
4348: }
4349:
4350: if (stcat (tmp, " \201") == 0) {
4351: merr_raise (M75);
4352: goto err;
4353: }
4354:
4355: if ((ch = *++codptr) == ')') {
4356: codptr++;
4357: break;
4358: }
4359:
4360: if (ch != ',') {
4361: merr_raise (COMMAER);
4362: goto err;
4363: }
4364: }
4365:
4366: ch = nstx;
4367: while (nestc[ch] == FOR) ch--; /* FOR does not define a NEW level */
4368:
4369: #ifdef DEBUG_NEWPTR
4370: printf ("Xecline 05 (TODO): ");
4371: printf ("[ch] is %d, [nestnew] is %d\r\n", ch, nestnew[ch]);
4372: #endif
4373:
4374: if (nestnew[ch] == 0) nestnew[ch] = newptr;
4375:
4376: symtab (newexcl, tmp, "");
4377: break;
4378:
4379: case LOCK:
4380:
4381: /* argumentless: UNLOCK */
4382: if ((ch = *codptr) == SP || ch == EOL) {
4383: locktab_unlock_all ();
4384: break;
4385: }
4386:
4387: if (ch == '+' || ch == '-') {
4388:
4389: if ((rtn_dialect () == D_M77) ||
4390: (rtn_dialect () == D_M84)) {
4391: merr_raise (NOSTAND);
4392: goto err;
4393: }
4394:
4395: tmp[0] = ch;
4396: ch = (*++codptr);
4397: }
4398: else {
4399: tmp[0] = SP;
4400: }
4401:
4402: if (ch != '(') {
4403: expr (NAME);
4404:
4405: if (merr () > OK) goto err;
4406:
4407: stcpy (&tmp[1], varnam);
4408: stcat (tmp, "\001\201");
4409: }
4410: else { /* multiple lock */
4411: tmp[1] = EOL;
4412:
4413: for (;;) {
4414: codptr++;
4415: expr (NAME);
4416:
4417: if (merr () > OK) goto err;
4418:
4419: stcat (tmp, varnam);
4420: stcat (tmp, "\001\201");
4421:
4422: if ((ch = *++codptr) == ')') break;
4423:
4424: if (ch != ',') {
4425: merr_raise (COMMAER);
4426: goto err;
4427: }
4428: }
4429:
4430: }
4431:
4432: frm_timeout = (-1L); /* no timeout */
4433:
4434: if (*++codptr == ':') {
4435: codptr++;
4436: expr (STRING);
4437:
4438: frm_timeout = intexpr (argptr);
4439:
4440: if (merr () > OK) goto err;
4441: if (frm_timeout < 0L) frm_timeout = 0L;
4442: }
4443:
4444: lock (tmp, frm_timeout, LOCK);
4445: break;
4446:
4447: case USE:
4448:
4449: if (*codptr == SP || *codptr == EOL) {
4450: merr_raise (ARGER);
4451: goto err;
4452: }
4453:
4454: expr (STRING);
4455: j = intexpr (argptr);
4456:
4457: if (j > MAXSEQ && j < MAXDEV) {
4458: io = j;
4459: goto use_socket;
4460: }
4461:
4462: if (j < 0 || j > MAXDEV) {
4463: merr_raise (NODEVICE);
4464: }
4465: else if (j != HOME && devopen[j] == 0) {
4466: merr_raise (NOPEN);
4467: }
4468:
4469: if (merr () > OK) goto err;
4470:
4471: io = j;
4472:
4473: if (io == HOME && *codptr == ':' && *(codptr + 1) == '(') {
4474:
4475: use0: /* entry point for processing of device parameters */
4476:
4477: codptr += 2;
4478: j = 1;
4479: setpiece = TRUE; /* so a surplus closing bracket will not be an error */
4480:
4481: while (*codptr != ')') {
4482:
4483: if (*codptr == ':') {
4484: codptr++;
4485: j++;
4486:
4487: continue;
4488: }
4489:
4490: expr (STRING);
4491:
4492: if (merr () > OK) {
4493: setpiece = FALSE;
4494: goto err;
4495: }
4496:
4497: switch (j) {
4498:
4499: case 1:
4500: i = intexpr (argptr);
4501:
4502: if (i < 0) i = 0;
4503: if (i > 255) i = 255;
4504:
4505: RightMargin = i;
4506: break;
4507:
4508: case 3:
4509: i = intexpr (argptr);
4510:
4511: if (i < 0) i = 0;
4512: if (i > 255) i = 255;
4513:
4514: InFieldLen = i;
4515: break;
4516:
4517: case 5:
4518: DSW = intexpr (argptr);
4519: break;
4520:
4521: case 7:
4522: i = intexpr (argptr);
4523: ypos[HOME] = i / 256;
4524: xpos[HOME] = i % 256;
4525:
4526: if (DSW & BIT7) {
4527:
4528: i = io;
4529: io = HOME;
4530: argptr[0] = ESC;
4531: argptr[1] = '[';
4532: argptr[2] = EOL;
4533:
4534: if (ypos[HOME]) {
4535: intstr (&argptr[2], ypos[HOME] + 1);
4536: }
4537:
4538: if (xpos[HOME]) {
4539: tmp3[0] = ';';
4540:
4541: intstr (&tmp3[1], xpos[HOME] + 1);
4542: stcat (argptr, tmp3);
4543: }
4544:
4545: stcat (argptr, "H\201");
4546: write_m (argptr);
4547:
4548: io = i;
4549: }
4550: break;
4551:
4552: case 9:
4553: i = 0;
4554: j = 0;
4555:
4556: while ((ch = argptr[i++]) != EOL) LineTerm[j++] = ch;
4557:
4558: LineTerm[j] = EOL;
4559: break;
4560:
4561: case 10:
4562: BrkKey = (*argptr);
4563:
4564: /* make new break active */
4565: set_io (UNIX);
4566: set_io (MUMPS);
4567: }
4568: }
4569:
4570: setpiece = FALSE;
4571: codptr++;
4572:
4573: break;
4574: }
4575: else if (*codptr == ':') {
4576: codptr++;
4577:
4578: if (io == HOME) { /* old syntax: enable/disable echo */
4579: expr (STRING);
4580:
4581: if (merr () > OK) goto err;
4582:
4583: if (tvexpr (argptr)) {
4584: DSW &= ~BIT0;
4585: }
4586: else {
4587: DSW |= BIT0;
4588: }
4589:
4590: }
4591: else {
4592:
4593: if (*codptr == '(') {
4594: codptr++;
4595: setpiece = TRUE;
4596: }
4597:
4598: j = 1;
4599:
4600: while (*codptr != ')') {
4601:
4602: if (*codptr == ':') {
4603: codptr++;
4604: j++;
4605:
4606: continue;
4607: }
4608: else if (setpiece == FALSE) {
4609: merr_raise (SPACER);
4610: goto err;
4611: }
4612:
4613: expr (STRING);
4614:
4615: if (merr () > OK) {
4616: setpiece = FALSE;
4617: goto err;
4618: }
4619:
4620: switch (j) {
4621:
4622: case 1:
4623: fseek (opnfile[io], (long) intexpr (argptr), 0);
4624: break;
4625:
4626: case 2:
4627: frm_crlf[io] = tvexpr (argptr);
4628: break;
4629:
4630: case 3:
4631: fm_nodelay[io] = tvexpr (argptr);
4632: break;
4633: }
4634:
4635: if (setpiece == FALSE) break;
4636: }
4637:
4638: if (setpiece) {
4639: codptr++;
4640: setpiece = FALSE;
4641: }
4642:
4643: break;
4644: }
4645: }
4646: break;
4647:
4648:
4649: use_socket:
4650: {
4651: char use_parm[256];
4652: int upct = 0;
4653:
4654: if (*codptr == ':') {
4655: codptr++;
4656: }
4657: else {
4658: while ((ch = *(codptr++)) != SP && ch != EOL);
4659: codptr--;
4660: break;
4661: }
4662:
4663: if (*codptr != '/') {
4664: merr_raise (ARGLIST);
4665: goto err;
4666: }
4667:
4668: codptr++;
4669:
4670: while ((ch = *codptr++) != SP && ch != EOL && isalpha (ch)) {
4671: use_parm[upct++] = ch;
4672: }
4673:
4674: use_parm[upct] = NUL;
4675:
4676: for (upct = 0; upct < strlen (use_parm); upct++) {
4677: use_parm[upct] = toupper (use_parm[upct]);
4678: }
4679:
4680: if (strcmp (use_parm, "CONNECT") == 0) {
4681:
4682: msck_connect (io);
4683:
4684: if (merr () > OK) goto err;
4685:
4686: }
4687: else if (strcmp (use_parm, "BIND") == 0) {
4688: write_m("BIND\r\n\201");
4689: }
4690: else {
4691: merr_raise (ARGLIST);
4692: goto err;
4693: }
4694:
4695: break;
4696:
4697: }
4698:
4699: case OPEN:
4700:
4701: {
4702: short k;
4703:
4704: if (*codptr == SP || *codptr == EOL) {
4705: merr_raise (FILERR);
4706: goto err;
4707: }
4708:
4709: expr (STRING);
4710: k = intexpr (argptr);
4711:
4712: if (merr () > OK) goto err;
4713:
4714:
4715: if (k < 0 || k > MAXDEV) {
4716: merr_raise (NODEVICE);
4717: goto err;
4718: }
4719:
4720: if (k > MAXSEQ) goto open_socket;
4721:
4722: if (restricted_mode) {
4723: merr_raise (CMMND);
4724: goto err;
4725: }
4726:
4727: /* need to evaluate the following 6 lines carefully - smw 2023-10-15 */
4728: if (k != HOME) {
4729: frm_crlf[k] = FALSE;
4730: fm_nodelay[k] = FALSE;
4731: xpos[k] = 0;
4732: ypos[k] = 0;
4733: }
4734:
4735: /* OPEN implies a previous CLOSE on same channel */
4736: if ((k != HOME) && devopen[k]) {
4737:
4738: fclose (opnfile[k]);
4739: devopen[k] = 0;
4740:
4741: if (io == k) io = HOME;
4742: }
4743:
4744: /* process device parameters on HOME at USE command. */
4745: if (k == HOME && *codptr == ':' && *(codptr + 1) == '(') goto use0;
4746:
4747: if (*codptr != ':') {
4748:
4749: if (k == HOME) break;
4750:
4751: if (dev[k][0] == EOL) {
4752: merr_raise (FILERR);
4753: merr_set_iochan_err (k, FILERR, "file not found");
4754: goto err;
4755: }
4756:
4757: goto open10;
4758: }
4759:
4760: codptr++;
4761:
4762: if (k == HOME) {
4763:
4764: if (*codptr != ':') { /* turn echo on/off */
4765:
4766: expr (STRING);
4767:
4768: if (merr () > OK) goto err;
4769:
4770: if (tvexpr (argptr)) {
4771: DSW &= ~BIT0;
4772: }
4773: else {
4774: DSW |= BIT0;
4775: }
4776: }
4777:
4778: if (*codptr == ':') { /* dummy timeout on HOME */
4779: codptr++;
4780:
4781: if (*codptr != SP && *codptr != EOL) {
4782: expr (STRING);
4783:
4784: if (merr () > OK) goto err;
4785:
4786: test = TRUE;
4787: break;
4788: }
4789: else {
4790: merr_raise (INVEXPR);
4791: goto err;
4792: }
4793: }
4794: }
4795: else {
4796: int op_pos;
4797:
4798: expr (STRING);
4799:
4800: if (merr () > OK) goto err;
4801:
4802: stcpy (dev[k], argptr);
4803: frm_timeout = (-1L);
4804:
4805: if (*codptr == ':') {
4806:
4807: codptr++;
4808:
4809: expr (STRING);
4810: frm_timeout = intexpr (argptr);
4811:
4812: if (merr () > OK) goto err;
4813: if (frm_timeout < 0L) frm_timeout = 0L;
4814: }
4815:
4816: open10:
4817:
4818: j = stcpy (tmp, dev[k]);
4819: i = dev[k][j - 1];
4820:
4821: while (--j >= 0) {
4822: if (dev[k][j] == '/') break;
4823: }
4824:
4825: stcpy (tmp2, dev[k]);
4826:
4827: if (j <= 0) {
4828: tmp2[stlen (tmp2)] = NUL;
4829: tmp[1] = 'r';
4830: i = '+';
4831: }
4832: else { /* default is read+write */
4833: tmp2[j] = NUL;
4834:
4835: j = stcpy (&tmp[1], &tmp[j + 1]);
4836:
4837: tmp[0] = SP;
4838: tmp[j + 1] = SP;
4839: tmp[j + 2] = EOL;
4840:
4841: j = 0;
4842:
4843: while ((ch = tmp[++j]) != EOL) if (ch >= 'A' && ch <= 'Z') tmp[j] = ch + 32;
4844:
4845: if (find (" r w a r+ w+ a+ read write append read+ write+ append+ \201", tmp) == FALSE) {
4846: tmp[1] = 'r';
4847: i = '+';
4848:
4849: tmp2[strlen (tmp2)] = '/';
4850: }
4851: }
4852:
4853: tmp[0] = tmp[1];
4854: tmp[1] = NUL; /* NUL not EOL !!! */
4855:
4856: if (i == '+') {
4857: tmp[1] = i;
4858: tmp[2] = NUL;
4859: }
4860:
4861: op_pos = 0;
4862:
4863: open20:
4864:
4865: if (oucpath[op_pos] != EOL) {
4866:
4867: j = stlen (dev[k]);
4868:
4869: while (--j >= 0) if (dev[k][j] == '/') break;
4870: while (--j >= 0) if (dev[k][j] == '/') break;
4871:
4872: if (j < 0) {
4873:
4874: strcpy (tmp3, tmp2);
4875: stcpy (tmp2, &oucpath[op_pos]);
4876:
4877: j = 0;
4878: while (tmp2[j] != ':' && tmp2[j] != EOL) j++;
4879:
4880: tmp2[j] = EOL;
4881:
4882: stcpy (act_oucpath[k], tmp2);
4883: op_pos += j;
4884:
4885: if (j) tmp2[j++] = '/';
4886:
4887: strcpy (&tmp2[j], tmp3);
4888: }
4889: }
4890:
4891: /* r = READ only access;
4892: * w = WRITE new file;
4893: * a = WRITE append;
4894: * r+ = READ/WRITE access;
4895: * w+ = WRITE new file;
4896: * a+ = WRITE append;
4897: */
4898: j = tmp[0];
4899: sq_modes[k] = j;
4900:
4901: if (j == 'r' && tmp[1] == '+') {
4902: sq_modes[k] = '+';
4903: }
4904:
4905: if (j == 'r' && frm_timeout < 0L) {
4906:
4907: errno = 0;
4908:
4909: while ((opnfile[k] = fopen (tmp2, tmp)) == NULL) {
4910:
4911: if (errno == EINTR) {
4912: errno = 0;
4913: continue;
4914: } /* interrupt */
4915:
4916: if (errno == EMFILE || errno == ENFILE) {
4917: close_all_globals ();
4918: continue;
4919: }
4920:
4921: if (dev[k][0] != '/' && oucpath[op_pos++] != EOL) {
4922: strcpy (tmp2, tmp3);
4923: goto open20;
4924: }
4925:
4926: act_oucpath[k][0] = EOL;
4927: merr_raise ((errno == ENOENT ? FILERR : PROTECT));
4928:
4929: switch (merr ()) {
4930:
4931: case FILERR:
4932: merr_set_iochan_err (k, FILERR, "file not found");
4933: break;
4934:
4935: case PROTECT:
4936: merr_set_iochan_err (k, PROTECT, "file protection violation");
4937: break;
4938:
4939: }
4940:
4941: goto err;
4942: }
4943:
4944: ssvn_job_add_device (k, tmp2);
4945:
4946: devopen[k] = ((i == '+') ? i : j);
4947: break;
4948: }
4949:
4950: if (j == 'r' || j == 'w' || j == 'a') {
4951:
4952: if (frm_timeout >= 0L) {
4953:
4954: test = TRUE;
4955:
4956: if (setjmp (sjbuf)) {
4957: test = FALSE;
4958: goto endopn;
4959: }
4960:
4961: sig_attach (SIGALRM, &ontimo);
4962: alarm ((unsigned) (frm_timeout < 3 ? 3 : frm_timeout));
4963: }
4964:
4965: for (;;) {
4966: errno = 0;
4967:
4968: if ((opnfile[k] = fopen (tmp2, tmp)) != NULL) break;
4969: if (merr () == INRPT) goto err;
4970: if (errno == EINTR) continue; /* interrupt */
4971:
4972: if (errno == EMFILE || errno == ENFILE) {
4973: close_all_globals ();
4974: continue;
4975: }
4976:
4977: if (frm_timeout < 0L) {
4978:
4979: if (dev[k][0] != '/' && oucpath[op_pos++] != EOL) {
4980: strcpy (tmp2, tmp3);
4981: goto open20;
4982: }
4983:
4984: if (errno == ENOENT) continue;
4985:
4986: act_oucpath[k][0] = EOL;
4987: merr_raise (PROTECT);
4988:
4989: merr_set_iochan_err (k, PROTECT, "file protection violation");
4990:
4991: goto err;
4992: }
4993:
4994: if (frm_timeout == 0L) {
4995: test = FALSE;
4996: goto endopn;
4997: }
4998:
4999: sleep (1);
5000: frm_timeout--;
5001: }
5002:
5003: devopen[k] = ((i == '+') ? i : j);
5004: endopn:;
5005:
5006: alarm (0); /* reset alarm request */
5007: }
5008: else {
5009: merr_raise (ARGLIST);
5010: merr_set_iochan_err (k, ARGLIST, "invalid argument");
5011: goto err;
5012: }
5013: }
5014:
5015:
5016: open_socket:
5017: if (*codptr != ':') {
5018: if (j == 'w') {
5019: merr_raise (FILEXWR);
5020: merr_set_iochan_err (k, FILEXWR, "cannot open existing file for WRITE");
5021: }
5022: else {
5023: merr_raise (ARGLIST);
5024: merr_set_iochan_err (k, ARGLIST, "invalid argument");
5025: }
5026: goto err;
5027: }
5028:
5029: codptr++;
5030: expr (STRING);
5031:
5032: if (merr () > OK) goto err;
5033:
5034:
5035: stcpy (vn, argptr);
5036: stcnv_m2c (vn);
5037:
5038: msck_open (k, vn);
5039:
5040: if (merr () > OK) goto err;
5041:
5042: ssvn_job_add_device (k, vn);
5043:
5044: break;
5045: }
5046: break;
5047:
5048:
5049:
5050:
5051:
5052: case CLOSE:
5053:
5054: /* no arguments: close all exept HOME */
5055: if (*codptr == SP || *codptr == EOL) {
5056:
5057: if (rtn_dialect () != D_FREEM) {
5058: merr_raise (NOSTAND);
5059: break;
5060: }
5061:
5062: j = 1;
5063:
5064: while (j <= MAXDEV) {
5065:
5066: if (j < FIRSTSCK) {
5067: if (jour_flag && (j == 2)) {
5068: j++;
5069: continue;
5070: }
5071:
5072: if (devopen[j]) fclose (opnfile[j]);
5073:
5074: ssvn_job_remove_device (j);
5075:
5076: devopen[j++] = 0;
5077: }
5078: else {
5079: msck_close (j++);
5080: }
5081:
5082: }
5083:
5084: io = HOME;
5085: break;
5086: }
5087:
5088: expr (STRING);
5089: j = intexpr (argptr);
5090:
5091: if (merr () > OK) break;
5092:
5093: if (j >= FIRSTSCK && j < MAXDEV) {
5094: msck_close (j);
5095: ssvn_job_remove_device (j);
5096: break;
5097: }
5098:
5099: /*ignore close on illgal units */
5100: if ((j >= 0 && j <= MAXDEV && j != HOME) && (jour_flag == 0 || (j != 2))) { /*ignore close on protocol channel */
5101:
5102: if (devopen[j]) fclose (opnfile[j]);
5103:
5104: devopen[j] = 0;
5105:
5106: ssvn_job_remove_device (j);
5107:
5108: if (io == j) io = HOME;
5109:
5110: }
5111:
5112: /* parse any 'device parameters', but ignore them otherwise */
5113: if (*codptr == ':') {
5114: if (*++codptr != '(') {
5115: expr (STRING);
5116: }
5117: else {
5118: setpiece = TRUE; /* to avoid bracket error at end of deviceparameters */
5119: for (;;)
5120: {
5121: if (*++codptr != ':')
5122: expr (STRING);
5123: if (*codptr == ':')
5124: continue;
5125: if (*codptr++ != ')')
5126: merr_raise (ARGER);
5127: break;
5128: }
5129: setpiece = FALSE;
5130: }
5131: }
5132:
5133: break;
5134:
5135: case ZHALT: /* ZHALT */
5136:
5137: if (is_standard ()) {
5138: merr_raise (NOSTAND);
5139: goto err;
5140: }
5141:
5142: case HA: /* HALT or HANG */
5143:
5144:
5145: /* no arguments: HALT */
5146: if (*codptr == SP || *codptr == EOL || mcmnd == ZHALT) {
5147:
5148: if (mcmnd == ZHALT && *codptr != SP && *codptr != EOL) {
5149: expr (STRING);
5150: i = intexpr (argptr);
5151:
5152: if (merr () > OK) break;
5153: }
5154: else {
5155: halt:
5156: i = 0;
5157: }
5158:
5159: set_io (UNIX);
5160: cleanup ();
5161:
5162: if (father) { /* advertise death to parent *//* make sure father is waiting !!! */
5163: if ((time (0L) - jobtime) < 120) sleep (2);
5164:
5165: kill (father, SIGUSR1);
5166: }
5167:
5168: exit (i); /* terminate mumps */
5169: };
5170: /* with arguments: HANG */
5171:
5172:
5173: case HANG: /* HANG */
5174:
5175: {
5176: unsigned long int waitsec;
5177: int millisec;
5178:
5179: #ifdef USE_GETTIMEOFDAY
5180: struct timeval timebuffer;
5181: #else
5182: struct timeb timebuffer;
5183: #endif
5184:
5185: expr (STRING);
5186: numlit (argptr);
5187:
5188: if (merr () > OK) break;
5189:
5190: #if !defined(__linux__)
5191: if (argptr[0] == '-') break; /* negative values without effect */
5192: if (argptr[0] == '0') break; /* zero without effect */
5193: #else
5194: /* on linux, return scheduler timeslice to kernel scheduler for hang 0 and hang with negative values
5195: for compatibility with Reference Standard M, only when process is using a realtime scheduling policy */
5196: if ((argptr[0] == '-') || (argptr[0] == '0')) {
5197: int policy;
5198:
5199: policy = sched_getscheduler (0);
5200: if ((policy == -1) || ((policy != SCHED_FIFO) && (policy != SCHED_RR))) break;
5201:
5202: sched_yield ();
5203: }
5204: #endif
5205:
5206: waitsec = 0;
5207: millisec = 0;
5208: i = 0;
5209:
5210: for (;;) { /* get integer and fractional part */
5211:
5212: if ((ch = argptr[i++]) == EOL) break;
5213:
5214: if (ch == '.') {
5215: millisec = (argptr[i++] - '0') * 100;
5216:
5217: if ((ch = argptr[i++]) != EOL) {
5218: millisec += (ch - '0') * 10;
5219:
5220: if ((ch = argptr[i]) != EOL) {
5221: millisec += (ch - '0');
5222: }
5223: }
5224:
5225: break;
5226: }
5227:
5228: waitsec = waitsec * 10 + ch - '0';
5229: }
5230:
5231: if ((i = waitsec) > 2) i -= 2;
5232:
5233: #ifdef USE_GETTIMEOFDAY
5234: gettimeofday (&timebuffer, NULL); /* get current time */
5235:
5236: waitsec += timebuffer.tv_sec; /* calculate target time */
5237: millisec += timebuffer.tv_usec;
5238: #else
5239: ftime (&timebuffer); /* get current time */
5240:
5241: waitsec += timebuffer.time; /* calculate target time */
5242: millisec += timebuffer.millitm;
5243: #endif
5244:
5245: if (millisec >= 1000) {
5246: waitsec++;
5247: millisec -= 1000;
5248: }
5249:
5250: /* do the bulk of the waiting with sleep() */
5251: while (i > 0) {
5252: j = time (0L);
5253: sleep ((unsigned) (i > 32767 ? 32767 : i)); /* sleep max. 2**15-1 sec */
5254: i -= time (0L) - j; /* subtract actual sleeping time */
5255:
5256: if (merr () == INRPT) goto err;
5257:
5258: if (evt_async_enabled && (merr () == ASYNC)) goto err;
5259: }
5260:
5261: /* do the remainder of the waiting watching the clock */
5262: for (;;) {
5263:
5264: #ifdef USE_GETTIMEOFDAY
5265:
5266: gettimeofday (&timebuffer, NULL);
5267:
5268: if (timebuffer.tv_sec > waitsec) break;
5269: if (timebuffer.tv_sec == waitsec && timebuffer.tv_usec >= millisec) break;
5270: #else
5271: ftime (&timebuffer);
5272:
5273: if (timebuffer.time > waitsec) break;
5274: if (timebuffer.time == waitsec && timebuffer.millitm >= millisec) break;
5275: #endif
5276: if (merr () == INRPT) goto err;
5277:
5278: }
5279: }
5280: break;
5281:
5282:
5283: case HALT: /* HALT */
5284:
5285: if (*codptr == SP || *codptr == EOL) goto halt;
5286:
5287: merr_raise (ARGLIST);
5288: break;
5289:
5290:
5291: case BREAK:
5292:
5293:
5294: if (*codptr == SP || *codptr == EOL) {
5295:
5296: if (breakon == FALSE) break; /* ignore BREAK */
5297:
5298: if (usermode == 0) {
5299: merr_raise (BKERR);
5300: goto err;
5301: }
5302:
5303: zbflag = TRUE;
5304: merr_raise (OK - CTRLB);
5305: zb_entry:loadsw = TRUE;
5306:
5307: #ifdef DEBUG_NEWSTACK
5308: printf ("CHECK 08 (Stack PUSH)\r\n");
5309: #endif
5310:
5311:
5312:
5313: if (++nstx > NESTLEVLS) {
5314: nstx--;
5315: merr_raise (STKOV);
5316:
5317: goto err;
5318: }
5319: else {
5320: estack++;
5321: }
5322:
5323: nestc[nstx] = BREAK;
5324:
5325: #ifdef DEBUG_NEWSTACK
5326:
5327: if (!cmdptr) printf ("CMDPTR is ZERO!\r\n");
5328:
5329: #endif
5330:
5331: nestp[nstx] = cmdptr; /* command stack address */
5332: nestn[nstx] = 0; /*!!! save name */
5333: nestr[nstx] = roucur - rouptr; /* save roucur */
5334: nestnew[nstx] = 0;
5335: ztrap[nstx][0] = EOL;
5336: nestlt[nstx] = level;
5337: level = 0; /* save level */
5338: /* save BREAK information */
5339: brkstk[nstx] = (((ECHOON ? 1 : 0) << 1) | test) << 3 | io;
5340:
5341: io = HOME;
5342: forsw = FALSE;
5343: cmdptr += stcpy (cmdptr, codptr) + 1;
5344: zerr = BKERR;
5345: goto restart;
5346: }
5347:
5348: if (is_standard ()) {
5349: merr_raise (NOSTAND);
5350: goto err;
5351: }
5352:
5353: expr (STRING);
5354: if (merr () > OK) break;
5355:
5356: {
5357: char brkstr[256];
5358:
5359: stcpy (brkstr, argptr);
5360: stcnv_m2c (brkstr);
5361:
5362: if (strcmp (brkstr, "DEBUG") == 0) {
5363: debug_mode = TRUE;
5364: }
5365: else {
5366: switch (intexpr (argptr)) {
5367:
5368: case 2:
5369: DSM2err = TRUE;
5370: break; /* enable DSM V 2 error processing */
5371:
5372: case -2:
5373: DSM2err = FALSE;
5374: break; /* enable normal error processing */
5375:
5376: case 0:
5377: breakon = FALSE;
5378: break; /* disable CTRL/C */
5379:
5380: default:
5381: breakon = TRUE;
5382: break; /* enable CTRL/C */
5383: }
5384: }
5385: }
5386:
5387: break;
5388:
5389: case VIEW:
5390:
5391: view_com ();
5392:
5393: if (repQUIT) { /* VIEW 26: repeated QUIT action */
5394:
5395: while (repQUIT-- > 0) {
5396:
5397: #ifdef DEBUG_NEWSTACK
5398: printf ("CHECK 09 (Stack POP)\r\n");
5399: #endif
5400:
5401: if (nestc[nstx] == BREAK) {
5402: if (repQUIT) continue;
5403: merr_raise (OK - CTRLB);
5404:
5405: goto zgo; /*cont. single step */
5406: }
5407:
5408: if (nestc[nstx] == FOR) {
5409:
5410: stcpy (code, cmdptr = nestp[nstx--]);
5411: estack--;
5412:
5413: codptr = code;
5414: ftyp = fortyp[--forx];
5415: fvar = forvar[forx];
5416: finc = forinc[forx];
5417: flim = forlim[forx];
5418: fi = fori[forx];
5419:
5420: if (repQUIT) continue;
5421: if ((forsw = (nestc[nstx] == FOR))) goto for_end;
5422:
5423: goto next_line;
5424: }
5425:
5426: if (nestn[nstx]) { /* reload routine */
5427: namptr = nestn[nstx];
5428:
5429: if ((nestc[nstx] != XECUTE) || loadsw) {
5430: stcpy (rou_name, namptr);
5431: zload (rou_name);
5432:
5433: ssvn_job_update ();
5434:
5435: dosave[0] = 0;
5436: }
5437:
5438: namptr--;
5439: }
5440:
5441: if (nestnew[nstx]) unnew (); /* un-NEW variables */
5442:
5443: /* restore old pointers */
5444: if ((mcmnd = nestc[nstx]) == BREAK) {
5445: if (repQUIT) continue;
5446:
5447: goto restore;
5448: } /*cont. single step */
5449:
5450: if (mcmnd == DO_BLOCK) {
5451: test = nestlt[nstx];
5452: level--;
5453: }
5454: else { /* pop $TEST */
5455: level = nestlt[nstx]; /* pop level */
5456: }
5457:
5458: roucur = nestr[nstx] + rouptr;
5459: stcpy (codptr = code, cmdptr = nestp[nstx--]);
5460: estack--;
5461: forsw = (nestc[nstx] == FOR);
5462:
5463:
5464: loadsw = TRUE;
5465:
5466: if (mcmnd == '$') {
5467: if (repQUIT) return 0;
5468: merr_raise (NOVAL);
5469: }
5470: }
5471: repQUIT = 0;
5472: }
5473: break;
5474:
5475: /* Z-COMMANDS */
5476: case ZEDIT:
5477: merr_raise (cmd_zedit (&ra));
5478: MRESCHECK(ra);
5479: break;
5480:
5481: case ZGO:
5482:
5483: /* ZGO with arguments: same as GOTO but with BREAK on */
5484: if (*codptr != EOL && *codptr != SP) {
5485: mcmnd = GOTO;
5486: zbflag = TRUE;
5487: merr_raise (OK - CTRLB);
5488:
5489: goto do_goto;
5490: }
5491:
5492: /* argumentless ZGO resume execution after BREAK */
5493:
5494: if (nestc[nstx] != BREAK) {
5495: merr_raise (LVLERR);
5496: break;
5497: }
5498:
5499:
5500:
5501: merr_clear (); /* stop BREAKing */
5502:
5503: zgo:
5504:
5505: #ifdef DEBUG_NEWSTACK
5506: printf ("Zgoing: (Stack POP)\r\n");
5507: #endif
5508:
5509:
5510:
5511: if (nestn[nstx]) { /* reload routine */
5512: stcpy (rou_name, (namptr = nestn[nstx]));
5513: zload (rou_name);
5514:
5515: ssvn_job_update ();
5516:
5517: if (merr () > OK) break;
5518: }
5519:
5520: level = nestlt[nstx];
5521: roucur = nestr[nstx] + rouptr;
5522: io = brkstk[nstx];
5523:
5524: if (io & 020) {
5525: DSW &= ~BIT0;
5526: }
5527: else {
5528: DSW |= BIT0; /* restore echo state */
5529: }
5530:
5531: test = (io & 010) >> 3; /* restore $TEST */
5532:
5533: /* restore $IO; default to HOME if channel not OPEN */
5534: if ((io &= 07) != HOME && devopen[io] == 0) io = HOME;
5535:
5536: stcpy (codptr = code, cmdptr = nestp[nstx--]);
5537: estack--;
5538:
5539: forsw = (nestc[nstx] == FOR);
5540:
5541:
5542: loadsw = TRUE;
5543: zbflag = FALSE;
5544:
5545: goto next0;
5546:
5547:
5548: case ZBREAK:
5549:
5550: if (*codptr == SP || *codptr == EOL) {
5551: merr_raise (ARGLIST);
5552: break;
5553: }
5554:
5555: expr (STRING);
5556: if (merr () > OK) break;
5557:
5558: zbreakon = tvexpr (argptr);
5559: if (hardcopy == DISABLE) set_zbreak (zbreakon ? STX : -1); /* enable/disable CTRL/B */
5560:
5561: zbflag = FALSE;
5562: break;
5563:
5564:
5565:
5566:
5567: case ZLOAD:
5568:
5569: if (*codptr == EOL || *codptr == SP) {
5570: stcpy (varnam, rou_name);
5571: }
5572: else {
5573: expr (NAME);
5574:
5575: if (merr () > OK) break;
5576:
5577: codptr++;
5578: }
5579:
5580: dosave[0] = EOL;
5581:
5582: if (varnam[0] == EOL) {
5583: varerr[0] = EOL;
5584: merr_raise (NOPGM);
5585: break;
5586: } /*error */
5587:
5588: loadsw = TRUE;
5589:
5590: /* a ZLOAD on the active routine always loads from disk */
5591: if (stcmp (varnam, rou_name) == 0) {
5592: for (i = 0; i < NO_OF_RBUF; i++) {
5593:
5594: if (rouptr == (buff + (i * PSIZE0))) {
5595: pgms[i][0] = EOL;
5596:
5597: break;
5598: }
5599: }
5600: }
5601:
5602: zload (varnam);
5603:
5604: if (merr () > OK) break; /* load file */
5605:
5606: stcpy (rou_name, varnam);
5607: ssvn_job_update ();
5608:
5609: break;
5610:
5611: case ZSAVE:
5612:
5613: if (*codptr == EOL || *codptr == SP) {
5614:
5615: if (rou_name[0] == EOL) {
5616: varerr[0] = EOL;
5617: merr_raise (NOPGM);
5618:
5619: break;
5620: } /* error */
5621:
5622: stcpy (varnam, rou_name);
5623: }
5624: else {
5625: expr (NAME);
5626:
5627: if (varnam[0] == '^') merr_raise (GLOBER);
5628: if (varnam[0] == '$') merr_raise (INVREF);
5629: if (merr () > OK) break;
5630:
5631: stcpy (rou_name, varnam);
5632: ssvn_job_update ();
5633:
5634: codptr++;
5635: }
5636:
5637: zsave (varnam);
5638: ssvn_routine_update ();
5639: break;
5640:
5641:
5642: case ZREMOVE:
5643:
5644: {
5645: char *beg, *end;
5646:
5647: dosave[0] = EOL;
5648:
5649: if (*codptr == SP || *codptr == EOL) { /* no args is ZREMOVE all */
5650: loadsw = TRUE;
5651:
5652: for (i = 0; i < NO_OF_RBUF; i++) {
5653:
5654: if (rouptr == buff + (i * PSIZE0)) {
5655: pgms[i][0] = EOL;
5656: break;
5657: }
5658:
5659: }
5660:
5661: rouptr = buff + (i * PSIZE0);
5662: rouend = rouins = rouptr;
5663: roucur = buff + (NO_OF_RBUF * PSIZE0 + 1);
5664:
5665: *(rouptr) = EOL;
5666: *(rouptr + 1) = EOL;
5667: *(rouptr + 2) = EOL;
5668:
5669: argptr = partition;
5670: rou_name[0] = EOL;
5671:
5672: ssvn_job_update ();
5673:
5674: break;
5675: }
5676: if (*codptr == ':') {
5677: beg = rouptr;
5678: }
5679: else if (*codptr == '*') {
5680: beg = rouptr;
5681:
5682: while ((end = (beg + UNSIGN (*beg) + 2)) < rouins) beg = end;
5683:
5684: codptr++;
5685: }
5686: else {
5687: lineref (&beg);
5688: if (merr () > OK) break;
5689: }
5690:
5691: if ((end = beg) == 0) {
5692: merr_raise (M13);
5693: break;
5694: }
5695:
5696: if (*codptr == ':') { /* same as above */
5697: codptr++;
5698:
5699: if (*codptr == '*') {
5700: end = rouins;
5701: codptr++;
5702: }
5703: else if (*codptr == ',' || *codptr == SP || *codptr == EOL) {
5704: end = rouend;
5705: }
5706: else {
5707: lineref (&end);
5708:
5709: if (end == 0) merr_raise (M13);
5710: if (merr () > OK) break;
5711:
5712: end = end + UNSIGN (*end) + 2;
5713: }
5714: }
5715: else {
5716: end = end + UNSIGN (*end) + 2;
5717: }
5718:
5719: if (beg < rouend) { /* else there's nothing to zremove */
5720:
5721: if (end >= rouend) {
5722: end = rouend = beg;
5723: }
5724: else {
5725: rouins = beg;
5726:
5727: while (end <= rouend) *beg++ = (*end++);
5728:
5729: i = beg - end;
5730: rouend += i;
5731:
5732: if (roucur > end) roucur += i;
5733: }
5734:
5735: *end = EOL;
5736: *(end + 1) = EOL;
5737:
5738: for (i = 0; i < NO_OF_RBUF; i++) {
5739: if (rouptr == (buff + (i * PSIZE0))) {
5740: ends[i] = rouend;
5741: break;
5742: }
5743: }
5744:
5745: }
5746: break;
5747: }
5748:
5749: case ZINSERT:
5750:
5751: {
5752: char *beg;
5753:
5754: if (*codptr == EOL || *codptr == SP) {
5755: merr_raise (ARGLIST);
5756: break;
5757: } /* error */
5758:
5759: dosave[0] = EOL;
5760:
5761: /* parse strlit */
5762: expr (STRING);
5763:
5764: if (merr () > OK) break;
5765:
5766: if (*codptr != ':') {
5767: zi (argptr, rouins);
5768: break;
5769: }
5770:
5771: stcpy (tmp, argptr);
5772: codptr++;
5773: lineref (&beg);
5774:
5775: if (merr () > OK) break; /* parse label */
5776:
5777: if (beg) {
5778: beg = beg + UNSIGN (*beg) + 2;
5779: }
5780: else {
5781: beg = rouptr;
5782: }
5783:
5784: if (beg > rouend + 1) {
5785: merr_raise (M13);
5786: break;
5787: }
5788:
5789: /* insert stuff */
5790: zi (tmp, beg);
5791: break;
5792: }
5793:
5794:
5795: /* PRINT is convenient -
5796: * but non-standard ZPRINT should be used instead */
5797: case 'p':
5798:
5799: if (is_standard ()) {
5800: merr_raise (NOSTAND);
5801: break;
5802: }
5803:
5804:
5805: case ZPRINT:
5806:
5807: {
5808: char *beg, *end;
5809:
5810: if (*codptr == SP || *codptr == EOL) { /* no args is ZPRINT all */
5811: beg = rouptr;
5812: end = rouend;
5813: }
5814: else {
5815: if (*codptr == ':') {
5816: beg = rouptr; /* from begin */
5817: }
5818: else if (*codptr == '*') { /* from 'linepointer' */
5819: beg = rouptr;
5820:
5821: while ((end = (beg + UNSIGN (*beg) + 2)) < rouins) beg = end;
5822: codptr++;
5823: }
5824: else {
5825: lineref (&beg);
5826: if (merr () > OK) break;
5827: } /* line reference */
5828:
5829: if (beg == 0) {
5830: beg = rouptr;
5831: rouins = beg;
5832:
5833: if (*codptr != ':') break;
5834: }
5835:
5836: if (*codptr == ':') {
5837: codptr++; /* to end */
5838:
5839: if (*codptr == SP || *codptr == ',' || *codptr == EOL)
5840: end = rouend;
5841: else {
5842: if (*codptr == '*') {
5843: end = rouins;
5844: codptr++;
5845: }
5846: else { /* to 'linepointer' */
5847: lineref (&end);
5848:
5849: if (merr () > OK) break; /* line reference */
5850: end = end + UNSIGN (*end) + 2;
5851: }
5852: }
5853: }
5854: else {
5855: end = beg + 1;
5856: }
5857: }
5858: if (rouend < end) end = rouend - 1;
5859:
5860: for (; beg < end; beg += UNSIGN (*beg) + 2) {
5861:
5862: if (frm_crlf[io]) {
5863: write_m ("\012\201");
5864: }
5865: else {
5866: write_m ("\012\015\201");
5867: }
5868:
5869: if ((*(beg + 1)) == EOL) break;
5870:
5871: write_m (beg + 1);
5872: if (merr () > OK) break;
5873: }
5874:
5875: rouins = beg;
5876: }
5877:
5878: if (frm_crlf[io]) {
5879: write_m ("\012\201");
5880: }
5881: else {
5882: write_m ("\012\015\201");
5883: }
5884:
5885: break;
5886:
5887: case WATCH:
5888: {
5889: char op;
5890:
5891:
5892: if (((ch = *codptr) == SP) || ch == EOL) {
5893:
5894: set_io(UNIX);
5895:
5896: if (dbg_enable_watch) {
5897: printf ("Watchpoints disabled.\n");
5898: dbg_enable_watch = 0;
5899: }
5900: else {
5901: printf ("Watchpoints enabled.\n");
5902: dbg_enable_watch = 1;
5903: }
5904:
5905: break;
5906:
5907: }
5908:
5909: if ((ch = *codptr) == '(') {
5910: merr_raise (ARGLIST);
5911: goto err;
5912: }
5913:
5914: for (;;) {
5915:
5916: switch (ch) {
5917:
5918: case '?':
5919: case '+':
5920: case '-':
5921: op = ch;
5922: codptr++;
5923: break;
5924:
5925: default:
5926: merr_raise (ARGLIST);
5927: goto err;
5928: }
5929:
5930: expr (NAME); /* try to interpret an mname */
5931:
5932: if (merr () > OK) goto err;
5933:
5934: stcpy (vn, varnam);
5935:
5936: switch (op) {
5937:
5938: case '+':
5939: dbg_add_watch (vn);
5940: break;
5941:
5942: case '-':
5943: dbg_remove_watch (vn);
5944: break;
5945:
5946: case '?':
5947: dbg_dump_watch (vn);
5948: break;
5949:
5950: }
5951:
5952: if (merr () > OK) goto err;
5953:
5954: if ((ch = *(codptr + 1)) == EOL) {
5955: codptr++;
5956: break;
5957: }
5958: else if ((ch = *(codptr + 1)) == ',') {
5959: codptr += 2;
5960: ch = *codptr;
5961: }
5962: else {
5963: merr_raise (ARGLIST);
5964: goto err;
5965: }
5966: }
5967:
5968:
5969: break;
5970: }
5971:
5972:
5973: case ASSERT_TKN:
5974: {
5975: expr (STRING);
5976:
5977: if (merr () > OK) goto err;
5978:
5979: if (tvexpr (argptr) == 0) {
5980: merr_raise (ASSERT);
5981: goto err;
5982: }
5983:
5984: break;
5985: }
5986:
5987: case ZWRITE:
5988: {
5989: short k;
5990: char w_tmp[512];
5991: char zwmode;
5992:
5993:
5994: if (io != HOME && devopen[io] == 'r') {
5995: merr_raise (NOWRITE);
5996: goto err;
5997: }
5998:
5999: tmp3[0] = SP;
6000: tmp3[1] = EOL;
6001:
6002: if ((ch = (*codptr)) == '(') { /* exclusive zwrite */
6003:
6004: for (;;) {
6005:
6006: codptr++;
6007: expr (NAME);
6008:
6009: if (merr () > OK) goto err;
6010: if (varnam[0] == '^') {
6011: merr_raise (GLOBER);
6012: goto err;
6013: }
6014:
6015: i = 0;
6016:
6017: while (varnam[i] != EOL) {
6018:
6019: if (varnam[i] == DELIM) {
6020: merr_raise (SBSCR);
6021: goto err;
6022: }
6023:
6024: i++;
6025: }
6026:
6027: if (stcat (tmp3, varnam) == 0) {
6028: merr_raise (M75);
6029: goto err;
6030: }
6031:
6032: if (stcat (tmp3, " \201") == 0) {
6033: merr_raise (M75);
6034: goto err;
6035: }
6036:
6037: if ((ch = *++codptr) == ')') {
6038: codptr++;
6039: break;
6040: }
6041:
6042: if (ch != ',') {
6043: merr_raise (COMMAER);
6044: goto err;
6045: }
6046: }
6047: }
6048: else {
6049: if (ch != SP && ch != EOL) goto zwritep;
6050: }
6051:
6052: /* no arguments: write local symbol table. */
6053: stcpy (tmp, " $\201");
6054:
6055: for (;;) {
6056: ordercnt = 1L;
6057:
6058: symtab (bigquery, &tmp[1], tmp2);
6059:
6060: if (*tmp2 == EOL || merr () == INRPT) break;
6061: w_tmp[0] = '=';
6062:
6063: /* subscripts: internal format different from external one */
6064: k = 0;
6065: i = 1;
6066: j = 0;
6067:
6068: while ((ch = tmp2[k++]) != EOL) {
6069:
6070: if (ch == '"') {
6071:
6072: if (j && tmp2[k] == ch) {
6073: k++;
6074: }
6075: else {
6076: toggle (j);
6077: continue;
6078: }
6079:
6080: }
6081:
6082: if (j == 0) {
6083:
6084: if (ch == '(' || ch == ',') {
6085: tmp[i++] = DELIM;
6086:
6087: continue;
6088: }
6089:
6090: if (ch == ')') break;
6091: }
6092:
6093: tmp[i++] = ch;
6094: }
6095:
6096: tmp[i] = EOL;
6097: if (kill_ok (tmp3, tmp) == 0) continue;
6098:
6099: write_m (tmp2);
6100: symtab (get_sym, &tmp[1], &w_tmp[1]);
6101: write_m (w_tmp);
6102: write_m ("\012\015\201");
6103: }
6104:
6105: break;
6106:
6107: zwritep:
6108:
6109: expr (NAME);
6110:
6111: if (merr () > OK) goto err;
6112:
6113: codptr++;
6114:
6115: if (varnam[0] == '$') {
6116:
6117: if ((varnam[1] | 0140) == 'z' && (varnam[2] | 0140) == 'f') {
6118: w_tmp[0] = '$';
6119: w_tmp[1] = 'Z';
6120: w_tmp[2] = 'F';
6121: w_tmp[3] = '(';
6122:
6123: for (i = 0; i < 44; i++) {
6124:
6125: if (zfunkey[i][0] != EOL) {
6126: intstr (&w_tmp[4], i + 1);
6127: stcat (w_tmp, ")=\201");
6128: write_m (w_tmp);
6129: write_m (zfunkey[i]);
6130: write_m ("\012\015\201");
6131: }
6132:
6133: }
6134:
6135: break;
6136: }
6137: else {
6138: break; /* do not zwrite special variables etc. other than $ZF */
6139: }
6140: }
6141:
6142: if (varnam[0] != '^') {
6143: symtab (fra_dat, varnam, tmp2);
6144: zwmode = 'L';
6145: }
6146: else {
6147: if (varnam[1] == '$') {
6148: ssvn (fra_dat, varnam, tmp2);
6149: zwmode = '$';
6150: }
6151: else {
6152: global (fra_dat, varnam, tmp2);
6153: zwmode = '^';
6154: }
6155: }
6156:
6157: if (tmp2[0] == '0') break; /* variable not defined */
6158:
6159: /* if $D(@varnam)=10 get next entry */
6160: if (tmp2[1] == '0') {
6161: ordercnt = 1L;
6162:
6163: if (varnam[0] != '^') {
6164: symtab (fra_query, varnam, tmp2);
6165: zwmode = 'L';
6166: }
6167: else {
6168: if (varnam[1] == '$') {
6169: ssvn (fra_query, varnam, tmp2);
6170: zwmode = '$';
6171: }
6172: else {
6173: global (fra_query, varnam, tmp2);
6174: zwmode = '^';
6175: }
6176: }
6177: }
6178: else {
6179: k = 0;
6180: i = 0;
6181: j = 0;
6182:
6183: while ((ch = varnam[k++]) != EOL) {
6184:
6185: if (ch == DELIM) {
6186:
6187: if (j) {
6188: tmp2[i++] = '"';
6189: tmp2[i++] = ',';
6190: tmp2[i++] = '"';
6191:
6192: continue;
6193: }
6194:
6195: j++;
6196:
6197: tmp2[i++] = '(';
6198: tmp2[i++] = '"';
6199:
6200: continue;
6201: }
6202:
6203: if ((tmp2[i++] = ch) == '"')
6204: tmp2[i++] = ch;
6205: }
6206:
6207: if (j) {
6208: tmp[i++] = '"';
6209: tmp2[i++] = ')';
6210: }
6211:
6212: tmp2[i] = EOL;
6213: }
6214:
6215: for (;;) { /* subscripts: internal format different from external one */
6216: k = 0;
6217: i = 0;
6218: j = 0;
6219:
6220: while ((ch = tmp2[k++]) != EOL) {
6221:
6222: if (ch == '"') {
6223: if (j && tmp2[k] == ch)
6224: k++;
6225: else {
6226: toggle (j);
6227: continue;
6228: }
6229: }
6230:
6231: if (j == 0) {
6232:
6233: if (ch == '(' || ch == ',') {
6234: tmp[i++] = DELIM;
6235:
6236: continue;
6237: }
6238:
6239: if (ch == ')') break;
6240: }
6241:
6242: tmp[i++] = ch;
6243: }
6244:
6245: tmp[i] = EOL;
6246: i = 0;
6247:
6248: while (tmp[i] == varnam[i]) {
6249:
6250: if (varnam[i] == EOL) break;
6251:
6252: i++;
6253: }
6254:
6255: if (varnam[i] != EOL) break;
6256: if (tmp[i] != EOL && tmp[i] != DELIM) break;
6257:
6258: tmp3[0] = EOL;
6259:
6260: switch (zwmode) {
6261:
6262: case 'L':
6263: symtab (fra_dat, tmp, tmp3);
6264: symtab (get_sym, tmp, &w_tmp[1]);
6265:
6266: break;
6267:
6268:
6269: case '$':
6270: ssvn (fra_dat, tmp, tmp3);
6271: ssvn (get_sym, tmp, &w_tmp[1]);
6272:
6273: break;
6274:
6275:
6276: case '^':
6277: global (fra_dat, tmp, tmp3);
6278: global (get_sym, tmp, &w_tmp[1]);
6279:
6280: break;
6281: }
6282:
6283: if (tmp3[0] != '0' && tmp3[1] != '0') {
6284:
6285: write_m (tmp2);
6286:
6287: w_tmp[0] = '=';
6288:
6289: write_m (w_tmp);
6290: write_m ("\012\015\201");
6291:
6292: }
6293:
6294: ordercnt = 1L;
6295:
6296: switch (zwmode) {
6297:
6298: case 'L':
6299: symtab (fra_query, tmp, tmp2);
6300:
6301: break;
6302:
6303:
6304: case '$':
6305: ssvn (fra_query, tmp, tmp2);
6306:
6307: break;
6308:
6309:
6310: case '^':
6311: global (fra_query, tmp, tmp2);
6312:
6313: break;
6314:
6315: }
6316:
6317: if (merr () == INRPT) break;
6318: }
6319:
6320: break;
6321: }
6322:
6323:
6324: case ZTRAP:
6325:
6326: if (*codptr == SP || *codptr == EOL) {
6327: merr_raise (ZTERR);
6328: varnam[0] = EOL;
6329:
6330: break;
6331: }
6332:
6333: expr (NAME);
6334: stcpy (varerr, varnam);
6335:
6336: if (merr ()) break;
6337:
6338: if (*++codptr == ':') { /* parse postcond */
6339: codptr++;
6340:
6341: expr (STRING);
6342:
6343: if (merr () > OK) goto err;
6344:
6345: if (tvexpr (argptr) == FALSE) break;
6346: }
6347:
6348: merr_raise (ZTERR);
6349: break;
6350:
6351:
6352: /* user defined Z-COMMAND */
6353: case PRIVATE:
6354:
6355: private: /* for in-MUMPS defined commands */
6356: i = 0;
6357: j = 0;
6358: ch = 0;
6359:
6360: while ((tmp2[i] = *codptr) != EOL) {
6361:
6362: if (tmp2[i] == SP && !j) {
6363: tmp2[i] = EOL;
6364: break;
6365: }
6366:
6367: if (tmp2[i] == '"') j = (!j);
6368:
6369: if (!j) {
6370:
6371: if (tmp2[i] == '(') ch++;
6372: if (tmp2[i] == ')') ch--;
6373:
6374: if (!ch && tmp2[i] == ',') { /* next argument: */
6375:
6376: tmp2[i] = EOL; /* call afterwards again */
6377: i = 0;
6378:
6379: while (tmp3[i] != EOL) i++;
6380:
6381: j = i;
6382: ch = 1;
6383:
6384: while (ch < i) tmp3[j++] = tmp3[ch++];
6385:
6386: tmp3[j - 1] = SP;
6387: tmp3[j] = EOL;
6388:
6389: codptr++;
6390:
6391: j = 0;
6392: ch = 0;
6393:
6394: break;
6395: }
6396: }
6397:
6398: i++;
6399: codptr++;
6400: }
6401:
6402: if (j || ch) {
6403: merr_raise (INVREF);
6404: goto err;
6405: }
6406:
6407: stcat (tmp3, codptr);
6408:
6409: if (destructor_run) {
6410: stcpy (code, "d \201");
6411: destructor_run = FALSE;
6412: }
6413: else {
6414: if (new_object) {
6415: stcpy (code, "d ^\201");
6416: new_object = FALSE;
6417: }
6418: else {
6419: stcpy (code, "d ^%\201");
6420: }
6421: }
6422:
6423: stcat (code, &tmp3[1]);
6424:
6425: codptr = code;
6426: privflag = TRUE;
6427:
6428: goto next_cmnd;
6429:
6430: evthandler: /* for event handlers */
6431: i = 0;
6432: j = 0;
6433: ch = 0;
6434:
6435: while ((tmp2[i] = *codptr) != EOL) {
6436:
6437: if (tmp2[i] == SP && !j) {
6438: tmp2[i] = EOL;
6439: break;
6440: }
6441:
6442: if (tmp2[i] == '"') j = (!j);
6443:
6444: if (!j) {
6445:
6446: if (tmp2[i] == '(') ch++;
6447: if (tmp2[i] == ')') ch--;
6448:
6449: if (!ch && tmp2[i] == ',') { /* next argument: */
6450:
6451: tmp2[i] = EOL; /* call afterwards again */
6452: i = 0;
6453:
6454: while (tmp3[i] != EOL) i++;
6455:
6456: j = i;
6457: ch = 1;
6458:
6459: while (ch < i) tmp3[j++] = tmp3[ch++];
6460:
6461: tmp3[j - 1] = SP;
6462: tmp3[j] = EOL;
6463:
6464: codptr++;
6465:
6466: j = 0;
6467: ch = 0;
6468:
6469: break;
6470: }
6471: }
6472:
6473: i++;
6474: codptr++;
6475: }
6476:
6477: if (j || ch) {
6478: merr_raise (INVREF);
6479: goto err;
6480: }
6481:
6482: stcpy (code, "d \201");
6483: stcat (code, tmp3);
6484:
6485: codptr = code;
6486: privflag = TRUE;
6487:
6488: goto next_cmnd;
6489:
6490: case ABLOCK:
6491: case AUNBLOCK:
6492: {
6493: short evt_mask[EVT_MAX];
6494:
6495: if ((rtn_dialect () != D_MDS) &&
6496: (rtn_dialect () != D_FREEM)) {
6497: merr_raise (NOSTAND);
6498: goto err;
6499: }
6500:
6501: /* declare and initialize table of events to be blocked/unblocked with this command */
6502:
6503:
6504: for (i = 0; i < EVT_MAX; i++) evt_mask[i] = 0;
6505:
6506:
6507: /* argumentless ABLOCK/AUNBLOCK: block/unblock everything */
6508: if (((ch = *codptr) == SP) || ch == EOL) {
6509:
6510: for (i = 0; i < EVT_MAX; i++) evt_mask[i] = 1;
6511:
6512: }
6513: else if (*codptr == '(') {
6514: /* exclusive ABLOCK/AUNBLOCK */
6515:
6516: short evt_exclusions[EVT_MAX];
6517:
6518: codptr++;
6519:
6520:
6521: for (i = 0; i < EVT_MAX; i++) evt_exclusions[i] = FALSE;
6522:
6523: for (;;) {
6524:
6525: expr (STRING);
6526:
6527: if (merr () == BRAER) merr_clear ();
6528: if (merr () > OK) goto err;
6529:
6530: codptr++;
6531:
6532: stcpy (vn, argptr);
6533:
6534: if (stcmp (vn, "COMM\201") == 0) {
6535: evt_exclusions[EVT_CLS_COMM] = TRUE;
6536: }
6537: else if (stcmp (vn, "HALT\201") == 0) {
6538: evt_exclusions[EVT_CLS_HALT] = TRUE;
6539: }
6540: else if (stcmp (vn, "IPC\201") == 0) {
6541: evt_exclusions[EVT_CLS_IPC] = TRUE;
6542: }
6543: else if (stcmp (vn, "INTERRUPT\201") == 0) {
6544: evt_exclusions[EVT_CLS_INTERRUPT] = TRUE;
6545: }
6546: else if (stcmp (vn, "POWER\201") == 0) {
6547: evt_exclusions[EVT_CLS_POWER] = TRUE;
6548: }
6549: else if (stcmp (vn, "TIMER\201") == 0) {
6550: evt_exclusions[EVT_CLS_TIMER] = TRUE;
6551: }
6552: else if (stcmp (vn, "USER\201") == 0) {
6553: evt_exclusions[EVT_CLS_USER] = TRUE;
6554: }
6555: else if (stcmp (vn, "WAPI\201") == 0) {
6556: evt_exclusions[EVT_CLS_WAPI] = TRUE;
6557: }
6558: else {
6559: merr_raise (CMMND);
6560: goto err;
6561: }
6562:
6563: if ((ch = *(codptr + 1)) == EOL || ch == SP) {
6564: codptr++;
6565: break;
6566: }
6567: if ((ch = *(codptr + 1)) == ')') {
6568: codptr++;
6569: break;
6570: }
6571:
6572: }
6573:
6574: for (i = 0; i < EVT_MAX; i++) {
6575:
6576: if (evt_exclusions[i] == FALSE) evt_mask[i] = 1;
6577:
6578: }
6579:
6580: }
6581: else {
6582: /* inclusive ABLOCK/AUNBLOCK */
6583:
6584: for (;;) {
6585:
6586: expr (STRING); /* try to interpret a string */
6587: if (merr () > OK) goto err;
6588:
6589: codptr++;
6590:
6591: stcpy (vn, argptr);
6592:
6593: if (stcmp (vn, "COMM\201") == 0) {
6594: evt_mask[EVT_CLS_COMM] = 1;
6595: }
6596: else if (stcmp (vn, "HALT\201") == 0) {
6597: evt_mask[EVT_CLS_HALT] = 1;
6598: }
6599: else if (stcmp (vn, "IPC\201") == 0) {
6600: evt_mask[EVT_CLS_IPC] = 1;
6601: }
6602: else if (stcmp (vn, "INTERRUPT\201") == 0) {
6603: evt_mask[EVT_CLS_INTERRUPT] = 1;
6604: }
6605: else if (stcmp (vn, "POWER\201") == 0) {
6606: evt_mask[EVT_CLS_POWER] = 1;
6607: }
6608: else if (stcmp (vn, "TIMER\201") == 0) {
6609: evt_mask[EVT_CLS_TIMER] = 1;
6610: }
6611: else if (stcmp (vn, "TRIGGER\201") == 0) {
6612: evt_mask[EVT_CLS_TRIGGER] = 1;
6613: }
6614: else if (stcmp (vn, "USER\201") == 0) {
6615: evt_mask[EVT_CLS_USER] = 1;
6616: }
6617: else if (stcmp (vn, "WAPI\201") == 0) {
6618: evt_mask[EVT_CLS_WAPI] = 1;
6619: }
6620: else {
6621: merr_raise (CMMND);
6622: goto err;
6623: }
6624:
6625: if (merr () > OK) goto err;
6626:
6627:
6628: if ((ch = *(codptr)) == EOL || ch == SP) {
6629: break;
6630: }
6631:
6632: }
6633:
6634: }
6635:
6636: for (i = 0; i < EVT_MAX; i++) {
6637:
6638: if (evt_mask[i] > 0) {
6639:
6640: if (mcmnd == ABLOCK) {
6641: evt_ablock (i);
6642: }
6643: else {
6644: evt_aunblock (i);
6645: }
6646: }
6647:
6648: }
6649:
6650:
6651: break;
6652: }
6653:
6654:
6655: case ASSIGN:
6656: merr_raise (CMMND);
6657: break;
6658:
6659:
6660: case ASTOP:
6661: case ASTART:
6662: {
6663: short evt_mask[EVT_MAX];
6664: short new_status;
6665:
6666: if ((rtn_dialect () != D_MDS) &&
6667: (rtn_dialect () != D_FREEM)) {
6668: merr_raise (NOSTAND);
6669: goto err;
6670: }
6671:
6672: /* declare and initialize table of events to be enabled with this command */
6673:
6674: if (mcmnd == ASTART) {
6675: new_status = EVT_S_ASYNC;
6676: }
6677: else {
6678: new_status = EVT_S_DISABLED;
6679: }
6680:
6681:
6682: for (i = 0; i < EVT_MAX; i++) evt_mask[i] = EVT_S_NOMODIFY;
6683:
6684:
6685: /* argumentless ASTART/ASTOP: enable/disable everything */
6686: if (((ch = *codptr) == SP) || ch == EOL) {
6687:
6688: for (i = 0; i < EVT_MAX; i++) evt_mask[i] = new_status;
6689:
6690: }
6691: else if (*codptr == '(') {
6692: /* exclusive ASTART */
6693:
6694: short evt_exclusions[EVT_MAX];
6695:
6696: codptr++;
6697:
6698: for (i = 0; i < EVT_MAX; i++) evt_exclusions[i] = FALSE;
6699:
6700: for (;;) {
6701:
6702: expr (STRING);
6703:
6704: if (merr () == BRAER) merr_clear ();
6705: if (merr () > OK) goto err;
6706:
6707: codptr++;
6708:
6709: stcpy (vn, argptr);
6710:
6711: if (stcmp (vn, "COMM\201") == 0) {
6712: evt_exclusions[EVT_CLS_COMM] = TRUE;
6713: }
6714: else if (stcmp (vn, "HALT\201") == 0) {
6715: evt_exclusions[EVT_CLS_HALT] = TRUE;
6716: }
6717: else if (stcmp (vn, "IPC\201") == 0) {
6718: evt_exclusions[EVT_CLS_IPC] = TRUE;
6719: }
6720: else if (stcmp (vn, "INTERRUPT\201") == 0) {
6721: evt_exclusions[EVT_CLS_INTERRUPT] = TRUE;
6722: }
6723: else if (stcmp (vn, "POWER\201") == 0) {
6724: evt_exclusions[EVT_CLS_POWER] = TRUE;
6725: }
6726: else if (stcmp (vn, "TIMER\201") == 0) {
6727: evt_exclusions[EVT_CLS_TIMER] = TRUE;
6728: }
6729: else if (stcmp (vn, "USER\201") == 0) {
6730: evt_exclusions[EVT_CLS_USER] = TRUE;
6731: }
6732: else if (stcmp (vn, "WAPI\201") == 0) {
6733: evt_exclusions[EVT_CLS_WAPI] = TRUE;
6734: }
6735: else if (stcmp (vn, "TRIGGER\201") == 0) {
6736: evt_exclusions[EVT_CLS_TRIGGER] = TRUE;
6737: }
6738: else {
6739: merr_raise (CMMND);
6740: goto err;
6741: }
6742:
6743: if ((ch = *(codptr + 1)) == EOL || ch == SP) {
6744: codptr++;
6745: break;
6746: }
6747: if ((ch = *(codptr + 1)) == ')') {
6748: codptr++;
6749: break;
6750: }
6751:
6752: }
6753:
6754: for (i = 0; i < EVT_MAX; i++) {
6755:
6756: if (evt_exclusions[i] == FALSE) evt_mask[i] = new_status;
6757:
6758: }
6759:
6760: }
6761: else {
6762: /* inclusive ASTART */
6763:
6764: for (;;) {
6765:
6766: expr (STRING); /* try to interpret a string */
6767: if (merr () > OK) goto err;
6768:
6769: codptr++;
6770:
6771: stcpy (vn, argptr);
6772:
6773: if (stcmp (vn, "COMM\201") == 0) {
6774: evt_mask[EVT_CLS_COMM] = new_status;
6775: }
6776: else if (stcmp (vn, "HALT\201") == 0) {
6777: evt_mask[EVT_CLS_HALT] = new_status;
6778: }
6779: else if (stcmp (vn, "IPC\201") == 0) {
6780: evt_mask[EVT_CLS_IPC] = new_status;
6781: }
6782: else if (stcmp (vn, "INTERRUPT\201") == 0) {
6783: evt_mask[EVT_CLS_INTERRUPT] = new_status;
6784: }
6785: else if (stcmp (vn, "POWER\201") == 0) {
6786: evt_mask[EVT_CLS_POWER] = new_status;
6787: }
6788: else if (stcmp (vn, "TIMER\201") == 0) {
6789: evt_mask[EVT_CLS_TIMER] = new_status;
6790: }
6791: else if (stcmp (vn, "USER\201") == 0) {
6792: evt_mask[EVT_CLS_USER] = new_status;
6793: }
6794: else if (stcmp (vn, "WAPI\201") == 0) {
6795: evt_mask[EVT_CLS_WAPI] = new_status;
6796: }
6797: else if (stcmp (vn, "TRIGGER\201") == 0) {
6798: evt_mask[EVT_CLS_TRIGGER] = new_status;
6799: }
6800: else {
6801: merr_raise (CMMND);
6802: goto err;
6803: }
6804:
6805: if (merr () > OK) goto err;
6806:
6807:
6808: if ((ch = *(codptr)) == EOL || ch == SP) {
6809: break;
6810: }
6811:
6812: }
6813:
6814: }
6815:
6816: for (i = 0; i < EVT_MAX; i++) {
6817:
6818: if (evt_status[i] == EVT_S_SYNC && evt_mask[i] == EVT_S_ASYNC) {
6819:
6820: /* cannot enable both synchronous and asynchronous
6821: event processing on the same event class at the
6822: same time */
6823:
6824: merr_raise (M102);
6825: goto err;
6826:
6827: }
6828: else {
6829:
6830: if (evt_mask[i] > EVT_S_NOMODIFY) {
6831: evt_status[i] = evt_mask[i];
6832: }
6833:
6834: }
6835:
6836: }
6837:
6838: if (mcmnd == ASTART) {
6839: evt_async_enabled = TRUE;
6840: }
6841: else {
6842: short disabled_evt_count = 0;
6843:
6844: for (i = 0; i < EVT_MAX; i++) {
6845: if (evt_status[i] == EVT_S_DISABLED) {
6846: disabled_evt_count++;
6847: }
6848: }
6849:
6850: if (disabled_evt_count == (EVT_MAX - 1)) evt_async_enabled = FALSE;
6851:
6852: }
6853:
6854: break;
6855: }
6856:
6857:
6858:
6859:
6860: case ETRIGGER:
6861:
6862: merr_raise (CMMND);
6863: break;
6864:
6865:
6866: #if defined(HAVE_MWAPI_MOTIF)
6867: case ESTART:
6868: if ((rtn_dialect () != D_MDS) &&
6869: (rtn_dialect () != D_FREEM)) {
6870: merr_raise (NOSTAND);
6871: goto err;
6872: }
6873:
6874: {
6875: if (in_syn_event_loop == TRUE) break;
6876:
6877: int evt_count;
6878: char *syn_handlers = (char *) malloc (STRLEN * sizeof (char));
6879:
6880: /* stack ^$EVENT */
6881: char key[100] = "^$EVENT\202\201";
6882: symtab (new_sym, key, " \201");
6883:
6884: evt_sync_enabled = TRUE;
6885: in_syn_event_loop = TRUE;
6886:
6887: while (evt_sync_enabled) {
6888:
6889:
6890: /* run the next iteration of GTK's event loop */
6891: /* TODO: replace with libXt event loop */
6892: /* gtk_main_iteration_do (TRUE); */
6893:
6894: /* dequeue any events */
6895: evt_count = mwapi_dequeue_events (syn_handlers);
6896:
6897: if (evt_count) {
6898: /* write them out */
6899: /* printf ("event handlers = '%s'\r\n", syn_handlers); */
6900:
6901: syn_event_entry_nstx = nstx;
6902:
6903: stcnv_c2m (syn_handlers);
6904: stcpy (tmp3, syn_handlers);
6905:
6906: syn_handlers[0] = '\0';
6907:
6908: goto evthandler;
6909: }
6910:
6911: syn_evt_loop_bottom:
6912: continue;
6913: }
6914:
6915: in_syn_event_loop = FALSE;
6916: evt_sync_enabled = FALSE;
6917:
6918: break;
6919: }
6920:
6921:
6922: case ESTOP:
6923: if ((rtn_dialect () != D_MDS) &&
6924: (rtn_dialect () != D_FREEM)) {
6925: merr_raise (NOSTAND);
6926: goto err;
6927: }
6928:
6929: evt_sync_enabled = FALSE;
6930: break;
6931: #endif
6932:
6933:
6934: default:
6935: merr_raise (CMMND);
6936:
6937: } /* command switch */
6938:
6939: if ((ch = *codptr) == EOL) {
6940: if (merr () != OK) goto err;
6941: if (forsw) goto for_end;
6942:
6943: mcmnd = 0;
6944:
6945: goto next_line;
6946: }
6947:
6948: if (ch == SP) {
6949: if (merr () == OK) goto next0;
6950:
6951: goto err;
6952: }
6953:
6954: if (ch != ',' && merr () == OK) {
6955: merr_raise (SPACER);
6956: }
6957: else if (ierr <= OK) {
6958: if (*++codptr != SP && *codptr != EOL) goto again;
6959:
6960: merr_raise (ARGLIST);
6961: }
6962:
6963: /* else goto err; */
6964:
6965: /* error */
6966: err:
6967:
6968: /* avoid infinite loops resulting from errors in argumentless FOR loops */
6969: if (merr () != OK && merr () != ASYNC && forsw && ftyp == 0) {
6970: argless_forsw_quit = TRUE;
6971: goto for_end;
6972: }
6973:
6974: /*
6975: * ierr == ASYNC means that the previous command was interrupted by
6976: * an async event. It is not a real error, so just go on to the next
6977: * command after resetting ierr = OK.
6978: */
6979: if (merr () == ASYNC) {
6980: merr_clear ();
6981: goto next_cmnd;
6982: }
6983:
6984: if (merr () > OK) {
6985: job_set_status (pid, JSTAT_ERROR);
6986: }
6987:
6988: if (ierr < 0) {
6989:
6990: ierr += CTRLB;
6991:
6992: if (merr () == OK) {
6993: zbflag = TRUE;
6994:
6995: goto zb_entry;
6996: }
6997: }
6998:
6999:
7000: if (merr () > OK ) {
7001:
7002: char er_buf[ERRLEN];
7003:
7004: merr_set_ecode_ierr ();
7005:
7006: stcpy (er_buf, errmes[merr ()]);
7007: stcnv_m2c (er_buf);
7008:
7009:
7010: #if !defined(MSDOS)
7011: logprintf (FM_LOG_DEBUG, "xecline: interpreter error %d [%s]", ierr, er_buf);
7012: #endif
7013:
7014: }
7015:
7016: zerr = ierr;
7017: merr_clear ();
7018:
7019: /* goto restart; */
7020:
7021:
7022: restart:
7023:
7024: if (param) goto restore;
7025:
7026: dosave[0] = EOL;
7027: setpiece = FALSE;
7028: setop = 0;
7029: privflag = FALSE;
7030:
7031: if (merr () == INRPT) goto err;
7032: if (zerr == STORE) symtab (kill_all, "", "");
7033:
7034: if (errfunlvl > 0) {
7035: errfunlvl--;
7036: }
7037: else {
7038:
7039: if (zerr == OK) {
7040: zerror[0] = EOL; /* reset error */
7041: }
7042: else {
7043:
7044: #ifdef DEBUG_STACK
7045: printf ("Storing NESTERR\r\n");
7046: #endif
7047:
7048: nesterr = nstx; /* save stack information at error */
7049:
7050: for (i = 1; i <= nstx; i++) getraddress (callerr[i], i);
7051:
7052: zerror[0] = '<';
7053:
7054: if (etxtflag) {
7055: stcpy (&zerror[1], errmes[zerr]);
7056: }
7057: else {
7058: intstr (&zerror[1], zerr);
7059: }
7060:
7061: stcat (zerror, ">\201");
7062:
7063: if (rou_name[0] != EOL) {
7064: char *j0;
7065: char *j1;
7066: char tmp1[256];
7067:
7068:
7069:
7070: if (nestc[nstx] == XECUTE) {
7071:
7072: if (nestn[nstx]) { /* reload routine */
7073: zload (nestn[nstx]);
7074: merr_clear ();
7075: }
7076:
7077: roucur = nestr[nstx] + rouptr; /* restore roucur */
7078: }
7079:
7080:
7081:
7082: j0 = (rouptr - 1);
7083: j = 0;
7084: tmp1[0] = EOL;
7085: j0++;
7086:
7087: if (roucur < rouend) {
7088:
7089: while (j0 < (roucur - 1)) {
7090:
7091: j1 = j0++;
7092: j++;
7093:
7094: if ((*j0 != TAB) && (*j0 != SP)) {
7095:
7096: j = 0;
7097:
7098: while ((tmp1[j] = (*(j0++))) > SP) {
7099:
7100: if (tmp1[j] == '(') tmp1[j] = EOL;
7101:
7102: j++;
7103: }
7104:
7105: tmp1[j] = EOL;
7106: j = 0;
7107: }
7108:
7109: j0 = j1;
7110: j0 += (UNSIGN (*j1)) + 2;
7111: }
7112: }
7113:
7114: stcat (zerror, tmp1);
7115:
7116: if (j > 0) {
7117: i = stlen (zerror);
7118: zerror[i++] = '+';
7119:
7120: intstr (&zerror[i], j);
7121: }
7122:
7123: stcat (zerror, "^\201");
7124:
7125:
7126:
7127: if (nestc[nstx] == XECUTE) {
7128:
7129: if (nestn[nstx]) { /* reload routine */
7130: zload (rou_name);
7131:
7132: ssvn_job_update ();
7133:
7134: merr_clear ();
7135: }
7136:
7137: stcat (zerror, nestn[nstx]);
7138: }
7139: else
7140: stcat (zerror, rou_name);
7141: }
7142:
7143: if (zerr == UNDEF) zerr = M6;
7144:
7145: /* undefined: report variable name */
7146: if (zerr == UNDEF || zerr == SBSCR || zerr == NAKED || zerr == ZTERR || zerr == DBDGD || zerr == LBLUNDEF || zerr == NOPGM || zerr == M6 || zerr == M7 || zerr == M13) {
7147:
7148: int f; /* include erroneous reference */
7149:
7150: f = stlen (zerror);
7151: zerror[f++] = SP;
7152: zname (&zerror[f], varerr);
7153: } /* end varnam section */
7154: }
7155: }
7156:
7157: roucur = buff + (NO_OF_RBUF * PSIZE0 + 1);
7158: tmp4[0] = EOL;
7159:
7160: while (ierr != (OK - CTRLB)) {
7161:
7162:
7163: /* standard error handling */
7164: if (etrap[0] != EOL && stcmp (ecode, "") != 0) {
7165:
7166: on_frame_entry ();
7167:
7168: /* disable $ZTRAP error handling */
7169: ztrap[nstx][0] = EOL;
7170:
7171: stcpy (tmp4, etrap);
7172: stcat (tmp4, " quit:$quit \"\" quit\201");
7173:
7174: if (etrap_lvl > 1) {
7175: /* we've encountered an error within an error handler.
7176: save off the error code at merr_stack[nstx + 1].ECODE */
7177:
7178: stcpy (merr_stack[nstx + 1].ECODE, ecode);
7179: merr_topstk = nstx + 1;
7180: etrap_lvl++;
7181:
7182: }
7183: else {
7184: merr_topstk = nstx;
7185: etrap_lvl++;
7186: }
7187:
7188: break;
7189:
7190: }
7191:
7192:
7193:
7194: if (ztrap[nstx][0] != EOL && !DSM2err) {
7195:
7196: #ifdef DEBUG_NEWSTACK
7197:
7198: printf ("Dropped into Ztrap [");
7199:
7200: for (loop = 0; loop < 20 && ztrap[nstx][loop] != EOL; loop++) {
7201: printf ("%c", ztrap[nstx][loop]);
7202: }
7203:
7204: printf ("]\r\n");
7205:
7206: #endif
7207:
7208: tmp4[0] = GOTO;
7209: tmp4[1] = SP;
7210: stcpy (&tmp4[2], ztrap[nstx]);
7211: ztrap[nstx][0] = EOL;
7212:
7213: #ifdef DEBUG_NEWSTACK
7214:
7215: printf ("Set tmp4 to [");
7216: for (loop = 0; tmp4[loop] != EOL; loop++) printf ("%c", tmp4[loop]);
7217: printf ("]\r\n");
7218:
7219: #endif
7220:
7221: break;
7222: }
7223:
7224:
7225:
7226: if (nstx == 0) {
7227:
7228: #ifdef DEBUG_NEWSTACK
7229: printf ("Nestx was Zero\r\n");
7230: #endif
7231:
7232: forx = 0;
7233: cmdptr = cmdstack;
7234: namptr = namstck;
7235: level = 0;
7236: errfunlvl = 0;
7237: io = HOME; /* trap to direct mode: USE 0 */
7238:
7239: if (zerr == INRPT && frm_filter) {
7240: tmp4[0] = 'h';
7241: tmp4[1] = EOL;
7242: }
7243:
7244: if (DSM2err && (ztrap[NESTLEVLS + 1][0] != EOL)) { /* DSM V.2 error trapping */
7245:
7246: #ifdef DEBUG_NEWSTACK
7247: printf ("Ztrap 2\r\n");
7248: #endif
7249:
7250: tmp4[0] = GOTO;
7251: tmp4[1] = SP; /* GOTO errorhandling */
7252:
7253: stcpy (&tmp4[2], ztrap[NESTLEVLS + 1]);
7254: ztrap[NESTLEVLS + 1][0] = EOL;
7255:
7256: }
7257:
7258: break;
7259: }
7260:
7261: #ifdef DEBUG_NEWSTACK
7262: printf ("Nestc[nstx] is [%d]\r\n", nestc[nstx]);
7263: #endif
7264:
7265: if (nestc[nstx] == BREAK) break;
7266:
7267: if (merr () > OK) goto err;
7268:
7269: if (nestc[nstx] == FOR) {
7270: if (forx == 0) goto for_quit;
7271: ftyp = fortyp[--forx];
7272: fvar = forvar[forx];
7273: finc = forinc[forx];
7274: flim = forlim[forx];
7275: fi = fori[forx];
7276: }
7277: else {
7278:
7279: if (nestc[nstx] == DO_BLOCK) {
7280: test = nestlt[nstx];
7281: level--;
7282: }
7283: else { /* pop $TEST */
7284: level = nestlt[nstx]; /* pop level */
7285: }
7286:
7287: #ifdef DEBUG_NEWSTACK
7288: printf ("Nestn[nstx] is [%d]\r\n", nestn[nstx]);
7289: #endif
7290:
7291: if (nestn[nstx]) { /* 'reload' routine */
7292: namptr = nestn[nstx];
7293: stcpy (rou_name, namptr);
7294: zload (rou_name);
7295:
7296: ssvn_job_update ();
7297:
7298: dosave[0] = 0;
7299:
7300: namptr--;
7301: }
7302:
7303: #ifdef DEBUG_NEWSTACK
7304: printf ("Execcing the rest...\r\n");
7305: #endif
7306:
7307: roucur = nestr[nstx] + rouptr;
7308:
7309: if (nestnew[nstx]) unnew (); /* un-NEW variables */
7310:
7311: cmdptr = nestp[nstx];
7312:
7313: if (nestc[nstx--] == '$') { /* extrinsic function/variable */
7314: *argptr = EOL;
7315: merr_raise (zerr);
7316: errfunlvl++;
7317:
7318: return 0;
7319: }
7320: estack--;
7321: }
7322: }
7323:
7324: forsw = FALSE;
7325:
7326: /* PRINTING ERROR MESSAGES */
7327: if (tmp4[0] == EOL) {
7328:
7329: if (zerr == BKERR && brkaction[0] != EOL) {
7330: stcpy (code, brkaction);
7331: codptr = code;
7332:
7333: if (libcall == TRUE) {
7334: return zerr;
7335: }
7336: else {
7337: goto next_cmnd;
7338: }
7339: }
7340:
7341: if (libcall == TRUE) return zerr;
7342:
7343: DSW &= ~BIT0; /* enable ECHO */
7344:
7345: /* print here */
7346: {
7347: char *t_rtn;
7348: char *t_nsn = (char *) malloc (STRLEN * sizeof (char));
7349: char *t_cod;
7350: int t_pos;
7351:
7352: NULLPTRCHK(t_nsn,"xecline");
7353:
7354: t_rtn = strtok (zerror, ">");
7355: t_rtn = strtok (NULL, ">");
7356:
7357: if (t_rtn != NULL && t_rtn[1] == '%') {
7358: strcpy (t_nsn, "SYSTEM");
7359: }
7360: else {
7361: strcpy (t_nsn, nsname);
7362: }
7363:
7364: if (deferred_ierr > OK) {
7365: t_cod = deferrable_code;
7366: t_pos = deferrable_codptr - code + 3;
7367: }
7368: else {
7369: t_cod = code;
7370: t_pos = codptr - code + 3;
7371: }
7372:
7373: if (t_rtn != NULL) {
7374: merr_dump (zerr, t_rtn, t_nsn, t_cod, t_pos);
7375: }
7376: else {
7377: merr_dump (zerr, "<UNKNOWN>", t_nsn, t_cod, t_pos);
7378: }
7379:
7380:
7381: free (t_nsn);
7382:
7383: }
7384:
7385:
7386: }
7387: else {
7388: stcpy (code, tmp4);
7389:
7390: codptr = code;
7391: tmp4[0] = EOL;
7392:
7393: goto next_cmnd;
7394: }
7395:
7396: restore:
7397:
7398: io = HOME;
7399: codptr = code;
7400:
7401: if (param > 0) {
7402:
7403: j = 0;
7404: ch = 0;
7405: paramx++;
7406: param--;
7407:
7408: for (;;) {
7409: if (m_argv[++j][0] == '-') {
7410: i = 0;
7411:
7412: while ((m_argv[j][++i] != 0) && (m_argv[j][i] != 'x'));
7413:
7414: if (m_argv[j][i] != 'x') continue;
7415:
7416: j++;
7417:
7418: if (++ch < paramx) continue;
7419:
7420: strcpy (code, m_argv[j]);
7421: break;
7422: }
7423: else {
7424: if (++ch < paramx) continue;
7425:
7426: strcpy (code, "d ");
7427: strcpy (&code[2], m_argv[j]);
7428: break;
7429: }
7430: }
7431: code[strlen (code)] = EOL;
7432: codptr = code;
7433: goto next_cmnd;
7434:
7435: }
7436:
7437: if (usermode == 0) { /* application mode: direct mode implies HALT */
7438: code[0] = 'H';
7439: code[1] = EOL;
7440: codptr = code;
7441:
7442: goto next_cmnd;
7443: }
7444:
7445: if (libcall == TRUE) { /* library mode: don't go to direct mode, just return */
7446: return merr ();
7447: }
7448:
7449:
7450: do {
7451:
7452: if (frm_filter == FALSE && promflag) {
7453: stcpy (code, " \201");
7454: stcpy (&code[2], " \201");
7455: promflag = FALSE;
7456: }
7457: else {
7458:
7459: direct_mode:
7460:
7461: if (dbg_enable_watch && dbg_pending_watches) dbg_dump_watchlist ();
7462:
7463: /* DIRECT-MODE PROMPT HERE */
7464: #if defined(HAVE_LIBREADLINE) && !defined(_AIX)
7465: {
7466: char *fmrl_buf;
7467: char fmrl_prompt[256];
7468: HIST_ENTRY **hist_list;
7469: int hist_idx;
7470: HIST_ENTRY *hist_ent;
7471:
7472: rl_attempted_completion_function = command_completion;
7473:
7474: if (quiet_mode == FALSE) {
7475: if (tp_level == 0) {
7476: snprintf (fmrl_prompt, sizeof (fmrl_prompt) - 1, "\r\n%s.%s> ", shm_env, nsname);
7477: }
7478: else {
7479: snprintf (fmrl_prompt, sizeof (fmrl_prompt) - 1 , "\r\nTL%d:%s.%s> ", tp_level, shm_env, nsname);
7480: }
7481: }
7482: set_io (UNIX);
7483:
7484: job_set_status (pid, JSTAT_DIRECTMODE);
7485:
7486: #if defined(__NetBSD__)
7487: printf ("\r\n");
7488: #endif
7489:
7490: /* readline() does its own malloc() */
7491: fmrl_buf = readline (fmrl_prompt);
7492:
7493: if (!fmrl_buf) {
7494: set_io (UNIX);
7495: printf ("\n");
7496: set_io (MUMPS);
7497:
7498: goto halt;
7499: }
7500:
7501:
7502: if (strlen (fmrl_buf) > 0) {
7503: add_history (fmrl_buf);
7504: }
7505:
7506: if (fmrl_buf[0] == '?') {
7507:
7508: char kb[20];
7509: char db[STRLEN];
7510:
7511: snprintf (kb, sizeof (kb) - 1, "%%SYSHLP\201");
7512: snprintf (db, STRLEN - 1, "\201");
7513:
7514: symtab (kill_sym, kb, db);
7515:
7516: /* Invoke Online Help */
7517:
7518: set_io (MUMPS);
7519: stcpy (code, "DO ^%ZHELP\201");
7520:
7521: if (strlen (fmrl_buf) > 1) {
7522: snprintf (db, STRLEN - 1, "%s\201", &fmrl_buf[1]);
7523: symtab (set_sym, kb, db);
7524: }
7525:
7526: }
7527: else if (strcmp (fmrl_buf, "rbuf") == 0) {
7528: rbuf_dump ();
7529: }
7530: else if (strcmp (fmrl_buf, "jobtab") == 0) {
7531: job_dump ();
7532: }
7533: else if (strcmp (fmrl_buf, "locktab") == 0) {
7534: locktab_dump ();
7535: code[0] = '\201';
7536: codptr = code;
7537: }
7538: else if (strcmp (fmrl_buf, "shmstat") == 0) {
7539: shm_dump ();
7540: }
7541: else if (strcmp (fmrl_buf, "shmpages") == 0) {
7542: shm_dump_pages ();
7543: }
7544: else if (strcmp (fmrl_buf, "glstat") == 0) {
7545: gbl_dump_stat ();
7546: }
7547: else if (strcmp (fmrl_buf, "events") == 0) {
7548:
7549: char stat_desc[30];
7550: char *evclass_name;
7551:
7552: printf ("\n%-20s %-15s %s\n", "Event Class", "Processing Mode", "ABLOCK Count");
7553: printf ("%-20s %-15s %s\n", "-----------", "---------------", "------------");
7554:
7555: for (i = 0; i < EVT_MAX; i++) {
7556:
7557: evclass_name = evt_class_name_c (i);
7558:
7559: switch (evt_status[i]) {
7560: case EVT_S_DISABLED:
7561: strcpy (stat_desc, "Disabled");
7562: break;
7563: case EVT_S_ASYNC:
7564: strcpy (stat_desc, "Asynchronous");
7565: break;
7566: case EVT_S_SYNC:
7567: strcpy (stat_desc, "Synchronous");
7568: }
7569:
7570: printf ("%-20s %-15s %d\n", evclass_name, stat_desc, evt_blocks[i]);
7571:
7572: }
7573:
7574:
7575: }
7576: else if (strcmp (fmrl_buf, "wh") == 0) {
7577: write_history (history_file);
7578: }
7579: else if (strcmp (fmrl_buf, "trantab") == 0) {
7580: tp_tdump();
7581: }
7582: else if (isdigit(fmrl_buf[0]) || (fmrl_buf[0] == '(') || (fmrl_buf[0] == '-') || (fmrl_buf[0] == '\'') || (fmrl_buf[0] == '+') || (fmrl_buf[0] == '$') || (fmrl_buf[0] == '^')) {
7583:
7584: snprintf (code, STRLEN - 1, "W %s", fmrl_buf);
7585: stcnv_c2m (code);
7586:
7587: set_io (MUMPS);
7588:
7589: }
7590: #if !defined(__APPLE__)
7591: else if (strcmp (fmrl_buf, "history") == 0) {
7592:
7593: /* History List */
7594:
7595: hist_list = history_list ();
7596: if (hist_list) {
7597:
7598: for (i = 0; hist_list[i]; i++) {
7599: printf("%d: %s\n", i + history_base, hist_list[i]->line);
7600: }
7601:
7602: }
7603:
7604: stcpy (code, " \201");
7605:
7606: set_io (MUMPS);
7607:
7608: }
7609: #endif
7610: else if (strncmp (fmrl_buf, "rcl", 3) == 0) {
7611:
7612: /* Recall History Item */
7613:
7614:
7615:
7616: if (!isdigit (fmrl_buf[4])) {
7617: fprintf (stderr, "invalid history index '%s'\n", &fmrl_buf[4]);
7618:
7619: set_io (MUMPS);
7620: stcpy (code, " \201");
7621:
7622: break;
7623: }
7624:
7625: hist_idx = atoi (&fmrl_buf[4]);
7626:
7627: if ((hist_idx > history_length) || (hist_idx < 1)) {
7628: fprintf (stderr, "history entry %d out of range (valid entries are 1-%d)\n", hist_idx, history_length);
7629:
7630: set_io (MUMPS);
7631: stcpy (code, " \201");
7632:
7633: break;
7634: }
7635:
7636: hist_ent = history_get (hist_idx);
7637:
7638: printf ("%s\n", hist_ent->line);
7639:
7640: strncpy (code, hist_ent->line, 255);
7641: stcnv_c2m (code);
7642:
7643: set_io (MUMPS);
7644:
7645: }
7646: else {
7647:
7648: /* Pass to M Interpreter */
7649:
7650: set_io (MUMPS);
7651:
7652: strncpy (code, fmrl_buf, 255);
7653: stcnv_c2m (code);
7654:
7655: }
7656:
7657: /* free the buffer malloc()'d by readline() */
7658: if (fmrl_buf) free (fmrl_buf);
7659: }
7660: #else
7661:
7662: {
7663: char fmrl_prompt[256];
7664:
7665: if (tp_level == 0) {
7666: snprintf (fmrl_prompt, sizeof (fmrl_prompt) - 1, "\r\n%s> \201", nsname);
7667: }
7668: else {
7669: snprintf (fmrl_prompt, sizeof (fmrl_prompt) - 1, "\r\nTL%d:%s> \201", tp_level, nsname);
7670: }
7671:
7672: write_m (fmrl_prompt);
7673:
7674: read_m (code, -1L, 0, 255); /* Not necessarily STRLEN? */
7675: }
7676:
7677: promflag = TRUE;
7678: #endif
7679:
7680: if (merr () > OK) goto err;
7681:
7682: if (code[0] == EOL && zbflag && nestc[nstx] == BREAK) {
7683:
7684: debug_mode = TRUE;
7685: merr_raise (OK - CTRLB);
7686:
7687: goto zgo;
7688: } /* single step */
7689: }
7690: }
7691: while (code[0] == EOL);
7692:
7693: if (promflag) write_m ("\r\n\201");
7694:
7695: /* automatic ZI in direct mode: insert an entry with TAB */
7696: i = (-1);
7697: j = 0;
7698: merr_clear ();
7699:
7700: while (code[++i] != EOL) {
7701: if (code[i] == '"') toggle (j);
7702:
7703: if (code[i] == TAB && j == 0) {
7704: dosave[0] = EOL;
7705:
7706: zi (code, rouins);
7707: if (merr ()) goto err;
7708: goto restore;
7709: }
7710: }
7711:
7712: code[++i] = EOL;
7713: code[++i] = EOL;
7714:
7715: roucur = buff + (NO_OF_RBUF * PSIZE0 + 1);
7716:
7717: goto next_cmnd;
7718:
7719: skip_line:
7720:
7721: if (forsw) goto for_end;
7722: goto next_line;
7723:
7724: } /*end of xecline() */
7725:
7726: void on_frame_entry(void)
7727: {
7728: return;
7729: }
7730:
7731: void rbuf_dump(void)
7732: {
7733: register int i;
7734: char rnam[256];
7735: char rpth[256];
7736: char ldtime[80];
7737: char flgs[80];
7738: time_t ag;
7739: struct tm tld;
7740:
7741:
7742: printf ("ROUTINE BUFFER CONFIGURATION\r\n");
7743: printf (" ROUTINE BUFFER COUNT: %ld\r\n", NO_OF_RBUF);
7744: printf (" MAX. ROUTINE BUFFER COUNT: %d\r\n", MAXNO_OF_RBUF);
7745: printf (" DEFAULT ROUTINE BUFFER SIZE (EACH): %d BYTES\r\n", DEFPSIZE0 - 1);
7746: printf (" CURRENT ROUTINE BUFFER SIZE (EACH): %ld BYTES\r\n\r\n", PSIZE0 - 1);
7747: printf ("BUFFERS IN USE:\r\n\r\n");
7748:
7749:
7750: for (i = 0; i < NO_OF_RBUF; i++) {
7751:
7752: flgs[0] = '\0';
7753:
7754: if (ages[i] == 0) {
7755: sprintf (rnam, "---------");
7756: sprintf (rpth, "[buffer empty]");
7757: sprintf (ldtime, "n/a");
7758: sprintf (flgs, "n/a");
7759: }
7760: else {
7761: stcpy (rnam, pgms[i]);
7762: stcnv_m2c (rnam);
7763:
7764: stcpy (rpth, path[i]);
7765: stcnv_m2c (rpth);
7766:
7767: ag = ages[i];
7768: tld = *localtime (&ag);
7769:
7770: strftime (ldtime, 80, "%a %Y-%m-%d %H:%M:%S %Z", &tld);
7771: if (rbuf_flags[i].dialect != D_FREEM) {
7772: strcat (flgs, "STANDARD");
7773:
7774: switch (rbuf_flags[i].dialect) {
7775:
7776: case D_M77:
7777: strcat (flgs, " [M 1977]");
7778: break;
7779:
7780: case D_M84:
7781: strcat (flgs, " [M 1984]");
7782: break;
7783:
7784: case D_M90:
7785: strcat (flgs, " [M 1990]");
7786: break;
7787:
7788: case D_M95:
7789: strcat (flgs, " [M 1995]");
7790: break;
7791:
7792: case D_MDS:
7793: strcat (flgs, " [MILLENNIUM DRAFT]");
7794: break;
7795:
7796: case D_M5:
7797: strcat (flgs, " [M5]");
7798: break;
7799: }
7800:
7801: }
7802: else {
7803: strcat (flgs, "FREEM");
7804: }
7805: }
7806:
7807: if (ages[i] != 0) {
7808: printf ("#%d [ROUTINE '%s']\r\n", i, rnam);
7809: printf (" UNIX PATH: %s\r\n", rpth);
7810: printf (" LAST ACCESS: %s\r\n", ldtime);
7811: printf (" DIALECT: %s\r\n", flgs);
7812: }
7813:
7814: }
7815:
7816: }
7817:
7818: short rbuf_slot_from_name(char *rnam)
7819: {
7820: register short i;
7821:
7822: for (i = 0; i < NO_OF_RBUF; i++) {
7823: if (stcmp (rnam, pgms[i]) == 0) {
7824: return i;
7825: }
7826: }
7827:
7828: return -1;
7829: }
7830:
7831: short is_standard(void)
7832: {
7833:
7834: if (rtn_dialect () == D_FREEM) {
7835: return FALSE;
7836: }
7837: else {
7838: return TRUE;
7839: }
7840:
7841: }
7842:
7843: int rtn_dialect(void)
7844: {
7845: short slot;
7846:
7847: slot = rbuf_slot_from_name (rou_name);
7848:
7849: return rbuf_flags[slot].dialect;
7850: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>