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