File:  [Coherent Logic Development] / freem / src / xecline.c
Revision 1.10: download - view: text, annotated - select for diffs
Thu Mar 27 03:27:35 2025 UTC (5 days, 20 hours ago) by snw
Branches: MAIN
CVS tags: v0-62-3, HEAD
Install init scripts to share/freem/examples/init and fix regression in method dispatch

/*
 *   $Id: xecline.c,v 1.10 2025/03/27 03:27:35 snw Exp $
 *    freem interpreter proper
 *
 *  
 *   Author: Serena Willis <snw@coherent-logic.com>
 *    Copyright (C) 1998 MUG Deutschland
 *    Copyright (C) 2020, 2025 Coherent Logic Development LLC
 *
 *
 *   This file is part of FreeM.
 *
 *   FreeM is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU Affero Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   FreeM is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU Affero Public License for more details.
 *
 *   You should have received a copy of the GNU Affero Public License
 *   along with FreeM.  If not, see <https://www.gnu.org/licenses/>.
 *
 *   $Log: xecline.c,v $
 *   Revision 1.10  2025/03/27 03:27:35  snw
 *   Install init scripts to share/freem/examples/init and fix regression in method dispatch
 *
 *   Revision 1.9  2025/03/24 04:13:12  snw
 *   Replace action macro dat with fra_dat to avoid symbol conflict on OS/2
 *
 *   Revision 1.8  2025/03/24 04:05:36  snw
 *   Replace crlf with frm_crlf to avoid symbol conflict with readline on OS/2
 *
 *   Revision 1.7  2025/03/22 22:52:24  snw
 *   Add STRLEN_GBL macro to manage global string length
 *
 *   Revision 1.6  2025/03/22 21:44:32  snw
 *   Make the startup messages fewer and add environment name to direct-mode prompt
 *
 *   Revision 1.5  2025/03/09 19:50:47  snw
 *   Second phase of REUSE compliance and header reformat
 *
 *
 * SPDX-FileCopyrightText:  (C) 2025 Coherent Logic Development LLC
 * SPDX-License-Identifier: AGPL-3.0-or-later
 **/

#include <stdlib.h>

#include "mpsdef.h"
#include "namespace.h"
#include "transact.h"
#include "merge.h"
#include "sighnd.h"
#include "init.h"
#include "events.h"
#include "mdebug.h"
#include "freem.h"
#include "mref.h"
#include "log.h"
#include "consttbl.h"
#include "shmmgr.h"
#include "locktab.h"
#include "jobtab.h"
#include "config.h"
#include "datatypes.h"
#include "objects.h"
#include "mcommand.h"

#if defined(__linux__)
# include <sched.h>
#endif

#if !defined(MSDOS)
# include "io_socket.h"
#endif

#include "merr.h"

#include <errno.h>
#include <unistd.h>
#include <string.h>

#if !defined(MSDOS)
# include <syslog.h>
#endif

#include <stdio.h>
#include <ctype.h>

#include <time.h>
#include <sys/types.h>
#include <pwd.h>
#if !defined(__OpenBSD__) && !defined(__FreeBSD__)
# include <sys/timeb.h>
#endif
#include <sys/wait.h>
#include <sys/time.h>
#include <time.h>

#ifdef HAVE_LIBREADLINE
#  if defined(HAVE_READLINE_READLINE_H)
#    include <readline/readline.h>
#  elif defined(HAVE_READLINE_H)
#    include <readline.h>
#  else /* !defined(HAVE_READLINE_H) */
extern char *readline ();
#  endif /* !defined(HAVE_READLINE_H) */
/*char *cmdline = NULL;*/
#else /* !defined(HAVE_READLINE_READLINE_H) */
  /* no readline */
#endif /* HAVE_LIBREADLINE */

#ifdef HAVE_READLINE_HISTORY
#  if defined(HAVE_READLINE_HISTORY_H)
#    include <readline/history.h>
#  elif defined(HAVE_HISTORY_H)
#    include <history.h>
#  else /* !defined(HAVE_HISTORY_H) */
extern void add_history ();
extern int write_history ();
extern int read_history ();
#  endif /* defined(HAVE_READLINE_HISTORY_H) */
  /* no history */
#endif /* HAVE_READLINE_HISTORY */

#include "mwapi_window.h"
#include "mwapi_event.h"


void on_frame_entry(void);
void rbuf_dump(void);
short rbuf_slot_from_name(char *);
short is_standard(void);

/*
 * xecline():
 *   typ (where to go on function entry):   1 = restart
 *                                          2 = error
 *
 */
int xecline(int typ)
{
    MACTION ra;
    short new_and_set = FALSE;
    short new_object = FALSE;
    short destructor_run = FALSE;
    short debug_mode = FALSE;
    short libcall = FALSE;
    char *namold;
    long rouoldc;
    unsigned long jobtime;
    char label[256], routine[256];

    char *vn;
    char *an;
    char *tmp;
    char *tmp2;
    char *tmp3;
    
    
    char *deferrable_codptr;
    char deferrable_code[512];

    char *ev_handlers;
    
    char *reeval_codptr;
    char reeval_code[512];
    
    int i;
    int j;
    register int ch;

    int then_ctr = 0;

#if defined(HAVE_MWAPI_MOTIF)    
    int syn_event_entry_nstx = 0;
    int in_syn_event_loop = FALSE;
#endif
    
#   ifdef DEBUG_NEWSTACK
    int loop;
#   endif

    vn = (char *) malloc ((STRLEN + 1) * sizeof (char));
    an = (char *) malloc ((STRLEN + 1) * sizeof (char));
    tmp = (char *) malloc ((STRLEN + 1) * sizeof (char));
    tmp2 = (char *) malloc ((STRLEN + 1) * sizeof (char));
    tmp3 = (char *) malloc ((STRLEN + 1) * sizeof (char));

    NULLPTRCHK(vn,"xecline");
    NULLPTRCHK(an,"xecline");
    NULLPTRCHK(tmp,"xecline");
    NULLPTRCHK(tmp2,"xecline");
    NULLPTRCHK(tmp3,"xecline");

    deferrable_codptr = deferrable_code;

    switch (typ) {

        case 0:
            goto next_line;
        
        case 1:
            goto restart;

        case 2:
            goto err;

        case 3:
            libcall = TRUE;
            goto restart;

    }

next_line:          /* entry point for next command line */

    
    job_set_status (pid, JSTAT_INTERPRETER);
    
    if (then_ctr > 0) {
        test = nestlt[nstx];
        level--;
        then_ctr--;
    }
    
    while ((roucur < rouend) && (ch = (*roucur++)) != TAB && ch != SP); /* skip label */

    if (roucur >= rouend) goto quit0;         /* end of routine implies QUIT */

    while ((ch = *roucur) == TAB || ch == SP) roucur++;

    i = 0;
    if (ch == '.') {               /* get level count */
        
        do {
            i++;
            while ((ch = (*++roucur)) == SP || ch == TAB);
        }
        while (ch == '.');
        
    }

    if (i != level) {

        if (mcmnd == GOTO) {
            merr_raise (M45);
            goto err;
        }

        if (i < level) {
            goto quit0;
        }
        else {
            roucur += stlen (roucur) + 2;
            goto next_line;
        }
    }

    i = stcpy (code, roucur) + 1;    
    code[i] = EOL;
    roucur += i + 1;
    codptr = code;

next_cmnd:          /* continue line entry point */
    if (sigint_in_for) goto for_quit;
    
    if (forsw && (forpost[forx][0] != '\0')) {

        stcpy (reeval_code, code);
        reeval_codptr = codptr;

        strcpy (code, forpost[forx]);
        stcnv_c2m (code);
        codptr = code;

        expr (STRING);
        
        if (merr () > OK) {
            stcpy (code, reeval_code);
            codptr = reeval_codptr;

            goto err;
        }

        if (tvexpr (argptr) == FALSE) {
            stcpy (code, reeval_code);
            codptr = reeval_codptr;
            
            goto for_quit;
        }

        stcpy (code, reeval_code);
        codptr = reeval_codptr;
        
    }
        
    job_set_status (pid, JSTAT_INTERPRETER);

    if (evt_async_enabled == TRUE) {

        switch (pending_signal_type) {

            case SIGWINCH:
                evt_enqueue ("SIGWINCH", EVT_CLS_INTERRUPT, 1);
                break;

            case SIGINT:
                evt_enqueue ("SIGINT", EVT_CLS_INTERRUPT, 0);
                break;

            case SIGFPE:
                evt_enqueue ("SIGFPE", EVT_CLS_INTERRUPT, 0);
                break;

            case SIGQUIT:
                evt_enqueue ("SIGQUIT", EVT_CLS_INTERRUPT, 0);
                break;

        }

        pending_signal_type = -1;
        
        /* process async events */
        ev_handlers = (char *) malloc (STRLEN * sizeof (char));
	NULLPTRCHK(ev_handlers,"xecline");


        /* get a comma-delimited list of applicable handlers (e.g. ^HNDL1,^HNDL2,^HNDL3) */
        ev_handlers[0] = NUL;
        evt_depth = evt_get_handlers (ev_handlers);

        stcnv_c2m (ev_handlers);
        stcpy (tmp3, ev_handlers);
        free (ev_handlers);

        /* only execute event handlers if we have at least one such handler registered in ^$JOB($JOB,"EVENTS") */
        if (evt_depth) {
    
            /* per X11-1998/28, async events are to be disabled during the execution of event handlers */

            /* TODO: this should be done by incrementing the event block counter
               for all event types, or whatever the event extension says to do.

               In any event (rimshot here for the obvious pun), turning off all
               event handlers this way is decidedly non-standard. Or non-what-might-
               become the standard. Whatever. */
            
            evt_async_enabled = FALSE;
            evt_async_initial = TRUE;
            evt_async_restore = TRUE;

            goto evthandler;
    
        }

    }


    if (merr () > OK) goto err;

next0:

    do {
        if ((ch = *codptr) == EOL) {
            if (forsw) goto for_end;

            goto next_line;
        }

        codptr++;
    }
    while (ch == SP);

    /* decode command word */

    if (ch < 'A') {  /* Handle non-alpha first chars */
        
        if (ch == ';') {           /* COMMENT */

            ch = *(codptr++);

            if(ch == '%') {         /* DIRECTIVE */

                int dir_pos = 0;
                int dir_wc = 0;
                char dir_words[20][255];

                while((ch = *(codptr++)) != EOL) {

                    switch (ch) {


                        case SP:
                            
                            dir_words[dir_wc][dir_pos] = NUL;

                            dir_wc++;
                            dir_pos = 0;

                            break;


                        default:

                            dir_words[dir_wc][dir_pos++] = ch;

                    }

                }

                dir_words[dir_wc][dir_pos] = NUL;

                if (strcmp (dir_words[0], "DIALECT") == 0) {
                    short rb_slot;

                    rb_slot = rbuf_slot_from_name (rou_name);
                    
                    if ((strcmp (dir_words[1], "STANDARD") == 0) ||
                        (strcmp (dir_words[1], "MDS") == 0)) {
                        rbuf_flags[rb_slot].standard = TRUE;
                        rbuf_flags[rb_slot].dialect = D_MDS;
                    }
                    else if (strcmp (dir_words[1], "M77") == 0) {
                        rbuf_flags[rb_slot].standard = TRUE;
                        rbuf_flags[rb_slot].dialect = D_M77;
                    }
                    else if (strcmp (dir_words[1], "M84") == 0) {
                        rbuf_flags[rb_slot].standard = TRUE;
                        rbuf_flags[rb_slot].dialect = D_M84;
                    }
                    else if (strcmp (dir_words[1], "M90") == 0) {
                        rbuf_flags[rb_slot].standard = TRUE;
                        rbuf_flags[rb_slot].dialect = D_M90;
                    }
                    else if (strcmp (dir_words[1], "M95") == 0) {
                        rbuf_flags[rb_slot].standard = TRUE;
                        rbuf_flags[rb_slot].dialect = D_M95;
                    }
                    else if (strcmp (dir_words[1], "M5") == 0) {
                        rbuf_flags[rb_slot].standard = TRUE;
                        rbuf_flags[rb_slot].dialect = D_M5;
                    }
                    else if ((strcmp (dir_words[1], "FREEM") == 0) ||
                             (strcmp (dir_words[1], "EXTENDED") == 0)) {
                        rbuf_flags[rb_slot].standard = FALSE;
                        rbuf_flags[rb_slot].dialect = D_FREEM;
                    }
                    else {
                        merr_raise (CMMND);
                        goto err;
                    }
                    goto skip_line;
                }
                else {
                    goto skip_line;
                }

            }

            goto skip_line;
        }

        if ((!is_standard ()) && (ch == '#')) {
            goto skip_line;
        }

        if ((is_standard ()) && (ch == '#')) {
            merr_raise (NOSTAND);
            goto err;
        }

        if (ch == '@') {
            if (!is_standard ()) {
                goto do_xecute;
            }
            else {
                merr_raise (NOSTAND);
                goto err;
            }
        }
        
        if (ch == '!') {           /* UNIXCALL */

            if (restricted_mode) {
                merr_raise (NOSTAND);
                goto err;
            }
            
            /* don't catch child dies signal */
            sig_attach (SIGUSR1, SIG_IGN);

            tmp2[stcpy (tmp2, codptr)] = NUL;

            if (demomode) fputc (d1char, stdout);

            if (tmp2[0] == '!') {
                
		uid_t suid;
		struct passwd *spw;

		suid = geteuid ();
		spw = getpwuid (suid);
		
		set_io (UNIX);

		fprintf (stderr, "Type Ctrl-D to exit from the shell\n");

                if (strlen (spw->pw_shell)) {
		    zsystem = system (spw->pw_shell);
		}
		else {
		    zsystem = system ("/bin/sh");
		}
		
		set_io (MUMPS);
		sig_attach (SIGUSR1, &oncld);   /* restore handler */
		
            }
            else if (tmp2[0] == '<') {           /* call write output to %-array */
                
                FILE *pipdes;
                char key[STRLEN + 1 /*was 256 */ ];
                char data[STRLEN + 1 /*was 256 */ ];
                char data_kill[256];
                data_kill[255] = EOL;
                
                for (i = 0; i < STRLEN + 1; i++) vn[i] = EOL;
                
                snprintf (key, 255, "^$JOB\202%d\202PIPE_GLVN\201", pid);
                ssvn (get_sym, key, vn);

                if (vn[0] == '^') {

                    if (vn[1] == '$') {
                        merr_raise (INVREF);
                        goto err;
                    }
                    else {
                        global (kill_sym, vn, data_kill);
                    }

                }
                else {
                    symtab (kill_sym, vn, data);
                }

                snprintf (key, 255, "^$JOB\202%d\202PIPE_GLVN\201", pid);
                ssvn (get_sym, key, vn);

                data[0] = '0';
                data[1] = EOL;

                if (vn[0] == '^') {

                    if (vn[1] == '$') {
                        merr_raise (INVREF);
                        goto err;
                    }
                    else {
                        global (set_sym, vn, data);
                    }

                }
                else {
                    symtab (set_sym, vn, data);
                }

		set_io (UNIX);
                if ((pipdes = popen (&tmp2[1], "r")) == NULL) {
                    zsystem = 1;
                }
                else {
                    int glvn_len = 0;
                    
                    while (fgets (data, STRLEN, pipdes)) {
                        snprintf (key, 255, "^$JOB\202%d\202PIPE_GLVN\201", pid);
                        ssvn (get_sym, key, vn);

                        glvn_len = stlen (vn);                        
                        stcpy (key, vn);

                        key[glvn_len] = DELIM;

                        if (vn[0] == '^') {
                            
                            if (vn[1] == '$') {
                                merr_raise (INVREF);
                                goto err;
                            }
                            else {
                                global (getinc, vn, &key[glvn_len + 1]);
                            }
                            
                        }
                        else {
                            symtab (getinc, vn, &key[glvn_len + 1]);
                        }
                        
                        i = strlen (data);
                        
                        data[i] = EOL;

                        if (i > 1 && data[i - 1] == LF) data[i - 1] = EOL;

                        if (vn[0] == '^') {
                            
                            if (vn[1] == '$') {
                                merr_raise (INVREF);
                                goto err;
                            }
                            else {
                                global (set_sym, key, data);
                            }
                            
                        }
                        else {
                            symtab (set_sym, key, data);
                        }
                        
                        if (merr () == STORE) break;
                    }

                    pclose (pipdes);
                    
                    zsystem = 0;
                }
		set_io (MUMPS);
            }      
            else if (tmp2[0] == '>') {           /* call read input from %-array */
                FILE *pipdes;
                char key[STRLEN + 1 /*was 256 */ ];
                char data[STRLEN + 1 /*was 256 */ ];
                int i, k, l;
                
                for (i = 0; i < STRLEN + 1; i++) vn[i] = EOL;
                
                snprintf (key, 255, "^$JOB\202%d\202PIPE_GLVN\201", pid);
                ssvn (get_sym, key, vn);

                if (vn[0] == '^') {

                    if (vn[1] == '$') {
                        merr_raise (INVREF);
                        goto err;
                    }
                    else {
                        global (get_sym, vn, data);
                    }

                }
                else {
                    symtab (get_sym, vn, data);
                }

                merr_clear ();
                k = intexpr (data);

		set_io (UNIX);
                if (k < 1 || (pipdes = popen (&tmp2[1], "w")) == NULL) {
                    zsystem = 1;
                }
                else {
                    int glvn_len = 0;
                    
                    for (i = 1; i <= k; i++) {
                        snprintf (key, 255, "^$JOB\202%d\202PIPE_GLVN\201", pid);
                        ssvn (get_sym, key, vn);

                        glvn_len = stlen (vn);                        
                        stcpy (key, vn);

                        key[glvn_len] = DELIM;
                        
                        intstr (&key[glvn_len + 1], i);

                        if (vn[0] == '^') {

                            if (vn[1] == '$') {
                                merr_raise (INVREF);
                                goto err;
                            }
                            else {
                                global (get_sym, key, data);
                            }
                            
                        }
                        else {                        
                            symtab (get_sym, key, data);
                        }

                        l = stlen (data);
                        
                        data[l++] = LF;
                        data[l] = NUL;

                        fputs (data, pipdes);
                    }
                    
                    pclose (pipdes);

                    zsystem = 0;
                    merr_clear ();
                }
		set_io (MUMPS);
		
            }     
            else {
		set_io (UNIX);
                zsystem = system (tmp2);
		set_io (MUMPS);
            }

            if (demomode) fputc (d1char, stdout);

            sig_attach (SIGUSR1, &oncld);   /* restore handler */
	    

            if (merr () == STORE) {
                zsystem = 1;
                goto err;
            }

            goto skip_line;
        }

        merr_raise (CMMND);
        goto err;
    } /* END handling of non-alpha first chars */


    mcmnd = ch | 0140;      /* uppercase to lower case */

    i = 1;

    while ((ch = (*codptr)) != SP && ch != ':' && ch != EOL) {
        tmp3[++i] = ch | 0140;
        codptr++;
    }

    j = i;

    if (j > 1) {
        merr_raise (mcmd_tokenize (&ra, tmp3, deferrable_codptr, deferrable_code, &j));
        MRESCHECK(ra);
    }


    if (*codptr == ':') {               
        /* handle postconditional */
        
        if (mcmnd == FOR) {
            char *savcp = codptr;

            codptr++;
            i = 0;
            while ((forpost[forx + 1][i++] = *(codptr++)) != SP);

            forpost[forx + 1][i - 1] = '\0';
        
            codptr = savcp;
        }
        

        /* postcond after FOR,IF,ELSE not allowed in dialects other than D_FREEM  */ 

        
        if ((rtn_dialect () != D_FREEM) && (mcmnd == FOR || mcmnd == IF || mcmnd == ELSE)) {
            merr_raise (NOSTAND);
            goto err;
        }       

        codptr++;

        expr (STRING);

        if (merr () > OK) goto err;

        ch = *codptr;

        if (ch != SP && ch != EOL) {
            merr_raise (SPACER);
            goto err;
        }

        if (tvexpr (argptr) == FALSE) {           /* skip arguments */

            if ((mcmnd == IF) || (mcmnd == THEN) || (mcmnd == ELSE) || (mcmnd == FOR)) {
                mcmnd = 0;
                goto skip_line;
            }
            
            mcmnd = 0;      /* avoid false LEVEL error */            
            
            for (;;) {
                if (ch == EOL) goto skip_line;               
                if ((ch = *++codptr) == SP) goto next_cmnd;
                if (ch != '"') continue;

                while (*codptr++ != EOL) {
                    if (*codptr != ch) continue;
                    if (*++codptr != ch) break;
                }

                if (--codptr == code) goto err;
            }
        }

    }

    if (*codptr != EOL) {               /* beware argumentless cmnds at end of line */
        codptr++;           /* entry for next argument in list */

again:
        while (*codptr == '@') {           /* handle indirection */
            
            stcpy (tmp, codptr++);  /* save code to restore on nameind */
            expr (ARGIND);

            if (merr () > OK) goto err;

            if (((ch = (*codptr)) != SP && ch != EOL && ch != ',' && ch != ':' && ch != '=') || (ch == '@' && *(codptr + 1) == '(')) {
                stcpy (code, tmp);  /* restore code on nameind */
                codptr = code;

                break;
            }
            else {
                stcpy (argptr + stlen (argptr), codptr);
                stcpy (code, argptr);
                
                codptr = code;
            }
        }
    }

    switch (mcmnd) {

        case MAP:
            merr_raise (cmd_map (&ra));
            MRESCHECK(ra);
            break;
            
        case UNMAP:
            merr_raise (cmd_unmap (&ra));
            MRESCHECK(ra);
            break;
        
        case THEN:
            merr_raise (cmd_then (&ra, &then_ctr));
            MRESCHECK(ra);
            break;
            
        case THROW:
            merr_raise (cmd_throw (&ra));
            MRESCHECK(ra);
            break;
            
	case CONST:            
            merr_raise (cmd_const (&ra));
            MRESCHECK(ra);
	    break;
	    
        case KVALUE:
            merr_raise (cmd_kvalue (&ra));
            MRESCHECK(ra);
            break;

        case KSUBSC:
            merr_raise (cmd_ksubscripts (&ra));
            MRESCHECK(ra);
            break;

        case TSTART:
            merr_raise (cmd_tstart (&ra));
            MRESCHECK(ra);
            break;
            
        case TCOMMIT:
            merr_raise (cmd_tcommit (&ra));
            MRESCHECK(ra);
            break;
            
        case TROLLBACK:
            merr_raise (cmd_trollback (&ra));
            MRESCHECK(ra);
            break;
            
        case SET:

set0:
            if ((ch = (*codptr)) >= 'A') {           /* no set$piece nor multiset */
                short setref = FALSE;
                short stclass = SC_UNCHANGED;
                
                expr (NAME);
                if (merr () > OK) break;               
                stcpy (vn, varnam);

                if (isalpha (vn[0]) && *(codptr + 1) == ':') {
                    char sc_string[255];
                    register int sci;
                    
                    codptr += 2;
                    expr (NAME);

                    stcpy (sc_string, varnam);
                    for (i = 0; i < stlen (sc_string); i++) {
                        sc_string[i] = toupper (sc_string[i]);
                    }

                    stcnv_m2c (sc_string);
                    if (strcmp (sc_string, "PRIVATE") == 0) {
                        stclass = SC_PRIVATE;
                    }
                    else if (strcmp (sc_string, "PUBLIC") == 0) {
                        stclass = SC_PUBLIC;
                    }
                    else {
                        merr_raise (OBJACINVALID);
                        break;
                    }
                }

                if ((*++codptr != '=') || (*(codptr + 1) == '=')) {
                    ch = *codptr;
                    
                    /* double char symbol ** (power) is encoded by ' ' */
                    if (ch == '*' && *(codptr + 1) == ch) {
                        codptr++;
                        ch = ' ';
                    }

                    /* negated boolean operator */
                    else if ((ch == '\'') && (*(codptr + 2) == '=')) ch = SETBIT (*++codptr);

                    if (*++codptr != '=') {

/* SET A++ or SET A-- equivalent to SET A+=1 SET A-=1 currently disabled */
//#ifdef NEVER
                        if ((ch == '+' || ch == '-') && ch == *codptr) {
                            codptr++;
                            setop = ch;
                            argptr[0] = '1';
                            argptr[1] = EOL;
                            
                            goto set2;
                        }
//#endif /* NEVER */

                        merr_raise (ASSIGNER);
                        break;
                    }

                    setop = ch;
                }

                codptr++;

                ch = *codptr;               

                if (ch == '.') {                    
                    setref = TRUE;
                    codptr++;
                    expr (NAME);
                }
                else {                
                    expr (STRING);
                }

                
                if (merr () > OK) break;


set2:

                if (vn[0] == '^') {

                    stcpy (an, argptr);
                    
                    if (setref == TRUE) {
                        merr_raise (INVREF);
                        goto err;
                    }
                    
                    if (vn[1] == '$') {
                        ssvn (set_sym, vn, an);
                    }
                    else {
                        global (set_sym, vn, an);
                    }

                }
                else {
                    stcpy (an, argptr);
                    
                    if (setref == TRUE) {
                        symtab (new_sym, vn, "");
                        symtab (m_alias, vn, varnam);
                        codptr++;
                    }
                    else {
                        if (new_object == FALSE) {
                            symtab (set_sym, vn, an);
                            switch (stclass) {
                                
                                case SC_PUBLIC:
                                    obj_set_field_public (vn);
                                    break;

                                case SC_PRIVATE:
                                    obj_set_field_private (vn);
                                    break;

                            }
                        }
                    }
                }
                
                if (merr () > OK) {
                    stcpy (varerr, vn);
                    break;
                }

                if (((new_and_set == TRUE) || (new_object == TRUE)) && (*codptr != SP) && (*codptr != EOL)) {
                    new_and_set = FALSE;
                    new_object = FALSE;
                    
                    merr_raise (INEWMUL);
                    goto err;
                }

                if (new_and_set == TRUE) new_and_set = FALSE;
                if (new_object == TRUE) new_object = FALSE;
set1:
                if (*codptr != ',') break;

                if (*++codptr == '@') goto again;

                goto set0;
            }

            /****** special SET syntax: multiple SET, set$piece, special variables */
            {
                char multiset, vnset[256];  /* multiset variables */
                long arg3, arg4;    /* 3rd,4th arg in set$piece */

                if ((multiset = (ch == '('))) {
                    vnset[0] = EOL;
                    codptr++;
                }

set:
                if (*codptr == '$' && (*(codptr + 1) | 0140) == 'p') {           /* set$piece */

                    if (multiset) {
                        merr_raise (INVREF);
                        goto err;
                    }
        
                    setpiece = 'p';

                    while (*++codptr != '(') {
                        
                        if (*codptr == EOL) {
                            merr_raise (INVREF);
                            goto err;
                        }
                    
                    }
                    
                    codptr++;
                    
                    expr (NAME);

                    if (merr () > OK) goto err;

                    stcpy (vn, varnam);
                    
                    codptr++;

                    if (*codptr++ != ',') {
                        merr_raise (COMMAER);
                        goto err;
                    }

                    expr (STRING);                    
                    
                    if (merr () > OK) goto err;

                    stcpy (tmp2, argptr);

                    if (*codptr != ')') {
                    
                        codptr++;

                        expr (STRING);

                        if (merr () > OK) goto err;

                        arg3 = intexpr (argptr);

                        if (merr () == MXNUM) {
                            arg3 = 256;
                            merr_clear ();
                        }
                    
                    }
                    else {
                        arg3 = 1;
                    }

                    if (*codptr != ')') {
                    
                        codptr++;

                        expr (STRING);

                        if (merr () > OK) goto err;

                        if (*codptr != ')') {
                            merr_raise (BRAER);
                            goto err;
                        }

                        arg4 = intexpr (argptr);

                        if (merr () == MXNUM) {
                            arg4 = 256;
                            merr_clear ();
                        }
                    
                    }
                    else {
                        arg4 = arg3;
                    }
                } /* set$piece */
                else if (*codptr == '$' && (*(codptr + 1) | 0140) == 'q' && (*(codptr + 2) | 0140) == 's') { /* TODO: verify this works (jpw) was (*codptr == '$q'...*/
                    /*SET $QSUBSCRIPT */

                    if (multiset) {
                        merr_raise (INVREF);
                        goto err;
                    }

                    setpiece = 'q';

                    while (*++codptr != '(') {
                        
                        if (*codptr == EOL) {
                            merr_raise (INVREF);
                            goto err;
                        }

                    }
                    
                    codptr++;

                    expr (NAME);

                    if (merr () > OK) goto err;

                    stcpy (vn, varnam);

                    if (*++codptr == ',') {
                        codptr++;

                        expr (STRING);
                        
                        if (merr () > OK) goto err;

                        stcpy (tmp2, argptr);
                    }

                    if (*codptr != ')') {
                        merr_raise (BRAER);
                        goto err;
                    }
                
                }
                else if (*codptr == '$' &&
                         (*(codptr + 1) | 0140) == 'd' &&
                         (*(codptr + 2) | 0140) == 'i') {

                    short rb_slot;

                    rb_slot = rbuf_slot_from_name (rou_name);
                    
                    while ((*(++codptr)) != '=');

                    codptr++;

                    expr (STRING);

                    stcnv_m2c (argptr);
                    
                    if ((strcmp (argptr, "STANDARD") == 0) ||
                        (strcmp (argptr, "MDS") == 0)) {
                        rbuf_flags[rb_slot].standard = TRUE;
                        rbuf_flags[rb_slot].dialect = D_MDS;
                    }
                    else if (strcmp (argptr, "M77") == 0) {
                        rbuf_flags[rb_slot].standard = TRUE;
                        rbuf_flags[rb_slot].dialect = D_M77;
                    } 
                    else if (strcmp (argptr, "M84") == 0) {
                        rbuf_flags[rb_slot].standard = TRUE;
                        rbuf_flags[rb_slot].dialect = D_M84;
                    } 
                    else if (strcmp (argptr, "M90") == 0) {
                        rbuf_flags[rb_slot].standard = TRUE;
                        rbuf_flags[rb_slot].dialect = D_M90;
                    } 
                    else if (strcmp (argptr, "M95") == 0) {
                        rbuf_flags[rb_slot].standard = TRUE;
                        rbuf_flags[rb_slot].dialect = D_M95;
                    } 
                    else if (strcmp (argptr, "M5") == 0) {
                        rbuf_flags[rb_slot].standard = TRUE;
                        rbuf_flags[rb_slot].dialect = D_M5;
                    }
                    else if ((strcmp (argptr, "FREEM") == 0) ||
                             (strcmp (argptr, "EXTENDED") == 0)) {
                        rbuf_flags[rb_slot].standard = TRUE;
                        rbuf_flags[rb_slot].dialect = D_FREEM;
                    }
                    else {
                        merr_raise (CMMND);
                        goto err;
                    }

                    goto s_end;

                }
                else if (*codptr == '$' && (*(codptr + 1) | 0140) == 'e' && (*(codptr + 2) | 0140) != 't' && (*(codptr + 2) | 0140) != 'c') {

                    /* set $extract */
                    if (multiset) {
                        merr_raise (INVREF);
                        goto err;
                    }

                    setpiece = 'e';
                    
                    while (*++codptr != '(') {
                        
                        if (*codptr == EOL) {
                            merr_raise (INVREF);
                            goto err;
                        }

                    }

                    codptr++;

                    expr (NAME);

                    if (merr () > OK) goto err;

                    stcpy (vn, varnam);

                    codptr++;

                    if (*codptr != ')') {
                        codptr++;

                        expr (STRING);
                        
                        if (merr () > OK) goto err;

                        arg3 = intexpr (argptr);
                        
                        if (merr () == MXNUM) {
                            arg3 = 256;
                            merr_clear ();
                        }
                    }
                    else {
                        arg3 = 1;
                    }

                    if (*codptr != ')') {
                        codptr++;

                        expr (STRING);
                        
                        if (merr () > OK) goto err;

                        if (*codptr != ')') {
                            merr_raise (BRAER);
                            goto err;
                        }

                        arg4 = intexpr (argptr);

                        if (merr () == MXNUM) {
                            arg4 = 256;
                            merr_clear ();
                        }

                    }
                    else {
                        arg4 = arg3;
                    }

                }
                else if (*codptr == '$' && (*(codptr + 1) | 0140) == 'e' && (*(codptr + 2) | 0140) == 'c') {
                    /* set $ecode */

                    if (multiset) {
                        merr_raise (INVREF);
                        goto err;
                    }

                    while ((*(++codptr)) != '=');

                    codptr++;

                    expr (STRING);
                    
                    if (merr () > OK) goto err;

                    switch (argptr[0]) {
                        
                        case ',':
                            
                            switch (argptr[1]) {

                                case ',':
                                    merr_raise (M101);
                                    goto err;                                 
                                
                            }
                            
                            break;

                    }
                    
                    merr_raise (merr_set_ecode (argptr));

#if 0
                    set_io (UNIX);
                    stcnv_m2c (ecode);
                    stcnv_m2c (etrap);
                    printf ("\n\n*** IN SET $ECODE: ecode = '%s' etrap = '%s'\n", ecode, etrap);
                    stcnv_c2m (etrap);
                    stcnv_c2m (ecode);
                    set_io (MUMPS);
#endif

                    if (merr () > OK) goto err;

                    goto s_end;

                }
                else if (*codptr == '$' && (*(codptr + 1) | 0140) == 'e' && (*(codptr + 2) | 0140) == 't') {
                    /* set $etrap */

                    if (multiset) {
                        merr_raise (INVREF);
                        goto err;
                    }

                    while ((*(++codptr)) != '=');

                    codptr++;

                    expr (STRING);

                    if (merr () > OK) goto err;

                    stcpy (etrap, argptr);

#if 0
                    set_io (UNIX);
                    stcnv_m2c (ecode);
                    stcnv_m2c (etrap);
                    printf ("\n\n***IN SET $ETRAP: ecode = '%s' etrap = '%s'\n", ecode, etrap);
                    stcnv_c2m (etrap);
                    stcnv_c2m (ecode);
                    set_io (MUMPS);
#endif

                    goto s_end;

                }
                else if (*codptr == '$' && (*(codptr + 1) | 0140) == 'g' && cset) {           /* set$get */
                    
                    if (multiset) {
                        merr_raise (INVREF);
                        goto err;
                    }

                    setpiece = 'g';

                    while (*++codptr != '(') {
                        
                        if (*codptr == EOL) {
                            merr_raise (INVREF);
                            goto err;
                        }
                    }

                    codptr++;

                    expr (NAME);

                    if (merr () > OK) goto err;

                    stcpy (vn, varnam);

                    if (*++codptr == ',') {
                        codptr++;

                        expr (STRING);

                        if (merr () > OK) goto err;

                        stcpy (tmp2, argptr);
                    }
                    else {
                        tmp2[0] = EOL;
                    }

                    if (*codptr != ')') {
                        merr_raise (BRAER);
                        goto err;
                    }
                }
                else {
                    if (*codptr == '$') {
                        codptr++;

                        expr (NAME);

                        if (merr () > OK) goto err;

                        stcpy (tmp, varnam);

                        varnam[0] = '$';

                        stcpy (&varnam[1], tmp);
                        
                        i = 0;
                        while ((ch = varnam[++i]) != EOL) { 
                            if (ch >= 'A' && ch <= 'Z') {
                                varnam[i] |= 0140;  /*to lowercase */
                            }
                        }
                    }
                    else {
                        expr (NAME);

                        if (merr () > OK) goto err;
                    }

                    stcpy (vn, varnam);
                }

                if (multiset) {
                    vnset[i = stlen (vnset)] = SOH;
                    
                    stcpy (&vnset[++i], vn);

                    if (*++codptr == ',') {
                        codptr++;
                        goto set;
                    }

                    if (*codptr != ')') {
                        merr_raise (COMMAER);
                        goto err;
                    }
                }

                if (*++codptr != '=') {
                    ch = *codptr;

                    if (!cset || *++codptr != '=' || multiset || setpiece || varnam[0] == '$') {
                        merr_raise (ASSIGNER);
                        break;
                    }

                    setop = ch;
                }

                codptr++;

                expr (STRING);

                if (merr () > OK) goto err;

                if (multiset)
multi:
                {
                    i = 0;
                    while (vnset[i] == SOH) i++;

                    j = 0;
                    while ((vn[j] = vnset[i]) != SOH && vnset[i] != EOL) {
                        vnset[i++] = SOH;
                        j++;
                    }

                    vn[j] = EOL;

                    if (j == 0) goto s_end;
                }

                if (setpiece == 'p') {
                    long m, n;

                    if (arg4 < arg3 || arg4 < 1) {
                        setpiece = FALSE;
                        break;
                    }

                    if (arg3 <= 0) arg3 = 1;
                    
                    if (vn[0] == '^') {
                        if (vn[1] == '$') {
                            ssvn (get_sym, vn, tmp3);
                        }
                        else {
                            global (get_sym, vn, tmp3);
                        }
                    }
                    else {
                        symtab (get_sym, vn, tmp3);
                    }


                    if (merr () == UNDEF || merr () == M6 || merr () == M7) {
                        tmp3[0] = EOL;
                        merr_clear ();
                    }
                    else if (merr () != OK) {
                        stcpy (varerr, vn);
                    }

                    ch = 0;
                    m = 0;
                    n = 0;

                    j = stlen (tmp2);

                    while (n < arg3 - 1) {
                        
                        if ((ch = find (&tmp3[m], tmp2)) <= 0) {

                            while (++n < arg3) {
                                if (stcat (tmp3, tmp2) == 0) {
                                    merr_raise (M75);
                                    goto err;
                                }
                            }

                            arg3 = arg4 = stlen (tmp3);

                            goto set10;
                        }

                        n++;
                        m += j + ch - 1;
                    }

                    if (arg3 > 1) {
                        arg3 = m;
                    }
                    else {
                        arg3 = 0;
                    }

                    while (n++ < arg4) {
                        
                        if ((ch = find (&tmp3[m], tmp2)) <= 0) {
                            arg4 = stlen (tmp3);

                            goto set10;
                        }

                        m += j + ch - 1;
                    }

                    arg4 = m - j;

set10:

                    stcpy0 (tmp2, tmp3, (long) arg3);
                    
                    tmp2[arg3] = EOL;

                    if (stcat (tmp2, argptr) == 0) {
                        merr_raise (M75);
                        goto err;
                    }

                    if (stcat (tmp2, &tmp3[arg4]) == 0) {
                        merr_raise (M56); //JPW
                        goto err;
                    }

                    stcpy (argptr, tmp2);
                    
                    setpiece = FALSE;
                }
                else if (setpiece == 'q') {           /* SET$QSUBSCRIPT */
                    
                    setpiece = FALSE;
                    
                    if (vn[0] == '^') {
                        if (vn[1] == '$') {
                            ssvn (get_sym, vn, tmp3);
                        }
                        else {
                            global (get_sym, vn, tmp3);
                        }                        
                    }
                    else {
                        symtab (get_sym, vn, tmp3);
                    }

                    if (merr () == UNDEF || merr () == M6 || merr () == M7) {
                        tmp3[0] = EOL;
                        merr_clear ();
                    }
                    else if (merr () != OK) {
                        stcpy (varerr, vn);
                    }

                    if (merr () == OK) {
                        /* 2nd $QS argument */
                        if ((arg4 = intexpr (tmp2)) < -1) merr_raise (ARGER);
                        if (merr () != OK) break;

                        /* special if source is empty */
                        if (tmp3[0] != EOL || (arg4 != 0)) {
                            /* special: Set env to empty: no |""| */
                            if ((arg4 == -1) && (*argptr == EOL)) {
                                tmp2[0] = EOL;
                            }                        
                            else if ((arg4 != 0) && !znamenumeric (argptr)) {
                                /* put replacement string in tmp2 with     */
                                /* quotes around env or subscript, unless numeric */
                                i = 0;
                                j = -1;
                                tmp2[0] = '"';

                                while ((tmp2[++i] = argptr[++j]) != EOL) {
                                    if (tmp2[i] == '"') tmp2[++i] = '"';

                                    if (i >= (STRLEN - 2)) {
                                        merr_raise (M75);
                                        break;
                                    }
                                }

                                tmp2[i] = '"';
                                tmp2[++i] = EOL;
                            }
                            else {
                                stcpy (tmp2, argptr);
                            }

                            /* source is tmp3, dest is argptr, replacement is tmp2 */
                            {
                                int ch, cpflag, quote, piececounter;
                                
                                piececounter = 0;
                                i = 0;
                                j = 0;
                                quote = FALSE;
                                cpflag = FALSE;
                                
                                /* if source has no env, process right now */
                                if ((arg4 == -1) && (tmp3[tmp3[0] == '^'] != '|') && tmp2[0] != EOL) {
                                    
                                    if (tmp3[0] == '^') {
                                        argptr[j++] = '^';
                                        i = 1;
                                    }
                                    
                                    argptr[j++] = '|';
                                    ch = 0;
                                    
                                    while ((argptr[j] = tmp2[ch++]) != EOL) j++;

                                    argptr[j++] = '|';

                                }
                                else if (arg4 == 0) {   /* '^'+name may be separated by env */                                
                                    if (tmp2[0] == '^') argptr[j++] = '^';
                                    if (tmp3[0] == '^') i++;
                                }

                                while ((ch = tmp3[i++]) != EOL) {
                                    if (ch == '"') quote = !quote;
                                    
                                    if (!quote) {
                                        
                                        if (ch == ',') {
                                            piececounter++;
                                            argptr[j++] = ch;
                                            
                                            continue;
                                        }
                                        
                                        if ((ch == '(' && piececounter == 0)) {
                                            if (!cpflag && (arg4 == 0)) {
                                                i--;
                                            }
                                            else {
                                                piececounter = 1;
                                                argptr[j++] = ch;

                                                continue;
                                            }
                                        }

                                        if (ch == '|') {
                                            if (piececounter == 0) {
                                                piececounter = (-1);
                                            }
                                            else if (piececounter == (-1)) {
                                                piececounter = 0;
                                            }

                                            if (tmp2[0] != EOL || piececounter > 0) argptr[j++] = ch;

                                            continue;
                                        }
                                    }
                                    
                                    if (piececounter == arg4) {
                                        if (cpflag) continue;

                                        cpflag = TRUE;
                                        ch = 0;
                                        
                                        if (arg4 == 0 && tmp2[0] == '^') ch = 1;

                                        while ((argptr[j] = tmp2[ch++]) != EOL) j++;
                                    }
                                    else {
                                        argptr[j++] = ch;
                                    }

                                    if (j >= (STRLEN - 1)) {
                                        merr_raise (M75);
                                        break;
                                    }
                                } /* while ((ch = tmp3[i++]) != EOL) ... */

                                if (piececounter && (piececounter == arg4)) argptr[j++] = ')';

                                if (piececounter < arg4) {
                                    
                                    if (piececounter == 0) {
                                        argptr[j++] = '(';
                                    }
                                    else {
                                        argptr[j - 1] = ',';
                                    }

                                    while (++piececounter < arg4) {
                                        argptr[j++] = '"';
                                        argptr[j++] = '"';
                                        argptr[j++] = ',';

                                        if (j >= STRLEN) {
                                            merr_raise (M75);
                                            break;
                                        }

                                    }
                                }
                                
                                ch = 0;

                                if (argptr[j - 1] != ')') {
                                    while ((argptr[j++] = tmp2[ch++]) != EOL);
                                    argptr[j - 1] = ')';
                                }
                            }

                            argptr[j] = EOL;

                            if (j >= STRLEN) {
                                merr_raise (M75);
                                break;
                            }
                        
                        }
                    }
                    else {
                        break;
                    }
                } /* set$qsubscript */
                else if (setpiece == 'e') {           /* SETtable $EXTRACT *//* parameters ok?? */

                    if (arg3 > arg4 || arg4 < 1) {
                        setpiece = FALSE;
                        break;
                    }

                    if (arg3 <= 0) arg3 = 1;

                    if (arg3 > STRLEN) {
                        merr_raise (M75);
                        goto err;
                    }

                    /* get value of glvn */
                    if (vn[0] == '^') { 
                        if (vn[1] == '$') {
                            ssvn (get_sym, vn, tmp3);
                        }
                        else {
                            global (get_sym, vn, tmp3);
                        }
                    }
                    else {
                        symtab (get_sym, vn, tmp3);
                    }


                    /* if UNDEF assume null string */
                    if (merr () == UNDEF || merr () == M6 || merr () == M7) {
                        tmp3[0] = EOL;
                        merr_clear ();
                    }
                    else if (merr () != OK) {
                        stcpy (varerr, vn);
                    }

                    j = stlen (tmp3);

                    /* pad with SPaces if source string is too short */
                    while (j < arg3) tmp3[j++] = SP;

                    tmp3[j] = EOL;
                    
                    if (stlen (tmp3) > arg4) {
                        stcpy (tmp2, &tmp3[arg4]);
                    }
                    else {
                        tmp2[0] = EOL;
                    }

                    tmp3[arg3 - 1] = EOL;

                    /* compose new value of glvn */
                    if (stcat (tmp3, argptr) == 0) {
                        merr_raise (M75);
                        goto err;
                    }

                    if (stcat (tmp3, tmp2) == 0) {
                        merr_raise (M75);
                        goto err;
                    }

                    stcpy (argptr, tmp3);
                    setpiece = FALSE;
                }
                else if (setpiece == 'g') {           /* SETtable $GET */
                    setpiece = FALSE;
                    ch = (stcmp (tmp2, argptr) == 0) ? killone : set_sym;

                    if (vn[0] == '^') {
                        stcpy (an, argptr);
                        if (vn[1] == '$') {                            
                            ssvn (ch, vn, an);
                        }
                        else {
                            global (ch, vn, an);
                        }
                    }
                    else {
                        stcpy (an, argptr);
                        symtab (ch, vn, an);
                    }

                    if (merr () != OK) stcpy (varerr, vn);
                    break;
                }

                if (vn[0] == '^') {           /* global variables and SSVNs */
                    stcpy (an, argptr);
                    
                    if (vn[1] == '$') {
                        ssvn (set_sym, vn, an);
                    }
                    else {
                        global (set_sym, vn, an);
                    }


                    if (merr () > OK) {
                        stcpy (varerr, vn);
                        goto err;
                    }
                }
                else if (vn[0] != '$') {           /* local variables */
                    stcpy (an, argptr);
                    symtab (set_sym, vn, an);

                    if (merr () > OK) {
                        stcpy (varerr, vn);
                        goto err;
                    }
                }
                else {           /* $-variables */

                    if (vn[1] == 'x') {           /* set $X */
                        j = intexpr (argptr);

                        if (merr () == MXNUM) {
                            j = 256;
                            merr_clear ();
                        }

                        if (j < 0) {
                            merr_raise (M43);
                            goto err;
                        }

                        if (io == HOME) {
                            argptr[0] = ESC;
                            argptr[1] = '[';
                            argptr[2] = EOL;

                            if (ypos[HOME] > 1) {
                                intstr (tmp3, ypos[HOME] + 1);
                                stcat (argptr, tmp3);
                            }

                            if (j > 0) {
                                stcat (argptr, ";\201");
                                intstr (tmp3, j + 1);
                                stcat (argptr, tmp3);
                            }

                            stcat (argptr, "H\201");
                            write_m (argptr);
                        }

                        xpos[io] = j;
                        goto s_end;
                    }
                    else if (vn[1] == 'y') {           /* set $Y */
                        
                        j = intexpr (argptr);
                        
                        if (merr () == MXNUM)  {
                            j = 256;
                            merr_clear ();
                        }

                        if (j < 0) {
                            merr_raise (M43);
                            goto err;
                        }

                        if (io == HOME) {

                            argptr[0] = ESC;
                            argptr[1] = '[';
                            argptr[2] = EOL;

                            if (j > 0) {
                                intstr (tmp3, j + 1);
                                stcat (argptr, tmp3);
                            }

                            if (xpos[HOME] > 0) {
                                stcat (argptr, ";\201");
                                intstr (tmp3, xpos[HOME] + 1);
                                stcat (argptr, tmp3);
                            }

                            stcat (argptr, "H\201");
                            write_m (argptr);
                        }
                        
                        ypos[io] = j;
                        goto s_end;
                    }
                    else if (vn[1] == 't') {           /* set $t */
                        test = tvexpr (argptr);
                        goto s_end;
                    }
                    else if (vn[1] == 'j') {           /* set $job */
                        pid = intexpr (argptr);
                        lock (" \201", -1, 's');
                        goto s_end;
                    }
#if !defined(_SCO_DS)
                    else if (vn[1] == 'h') {           /* set $horolog */
                        long int day;
		        long int sec;
                        struct timespec sh_ts;

                        if (!is_horolog (argptr)) {
                            merr_raise (ZINVHORO);
                            goto err;
                        }
                        
                        sec = 0L;
                        
                        for (i = 0; argptr[i] != EOL; i++) {

                            if (argptr[i] == ',') {
                                sec = intexpr (&argptr[i + 1]);
                                break;
                            }

                        }

                        if (sec < 0 || sec >= 86400L) {
                            merr_raise (ARGER);
                            goto err;
                        }
                        
                        day = intexpr (argptr) - 47117L;

                        if (day < 0 || day > 49710L) {
                            merr_raise (ARGER);
                            goto err;
                        }
                        
                        sec += day * 86400 + FreeM_timezone;
                        day = FreeM_timezone;

                        sh_ts.tv_sec = sec;

#if defined(__linux__)
                        if (clock_settime (CLOCK_REALTIME, &sh_ts) != 0) {
                            merr_raise (PROTECT);
                            goto err;
                        }
#endif
                        
#ifndef LINUX
/* daylight savings time status may have changed */
                        {
                            struct tm *ctdata;
                            long clock;

                            clock = time (0L);
                            ctdata = localtime (&clock);
                            
                            if (day -= (FreeM_timezone = ctdata->tm_tzadj)) {
                                sec -= day;
                                tzoffset += day;
                                stime (&sec);
                            }
                        }
#endif /* LINUX */
                        goto s_end;


                    }
#endif /* _SCO_DS */
                    else if ((vn[1] == 'r') || ((vn[1] == 'z') && (vn[2] == 'r') && vn[3] == EOL)) { /* set $reference */
                        
                        if (argptr[0] == EOL) {
                            zref[0] = EOL;
                            break;
                        }
                        
                        stcpy (tmp4, codptr);
                        stcpy (code, argptr);
                        
                        codptr = code;
                        
                        expr (NAME);
                        stcpy (code, tmp4);
                        
                        codptr = code;

                        if (argptr[0] != '^') merr_raise (INVREF);
                        if (ierr <= OK) nakoffs = stcpy (zref, argptr); /* save reference */ /* SMW - TODO */

                        goto s_end;
                    }
                    else if (vn[1] == 'z') {           /* $Z.. variables *//* if not intrinsic: make it user defined */
                        
                        i = stcpy (&tmp[1], &vn[1]) + 1;
                        
                        if (vn[3] == DELIM) i = 3;  /* set $zf() function keys */

                        tmp[0] = SP;
                        tmp[i] = SP;
                        tmp[++i] = EOL;
                        
                        if (find (zsvn, tmp) == FALSE) {
                            
                            i = 2;
                            while (vn[i] != EOL) {
                                
                                if (vn[i++] == DELIM) {
                                    merr_raise (INVREF);
                                    goto err;
                                }

                            }

                            udfsvn (set_sym, &vn[2], argptr);
                            break;
                        }
                        
                        if ((!stcmp (&vn[2], "l\201")) || (!stcmp (&vn[2], "local\201"))) { /* set $zlocal */
                            
                            if (argptr[0] == EOL) {
                                zloc[0] = EOL;
                                break;
                            }
                            
                            stcpy (tmp4, codptr);
                            stcpy (code, argptr);
                            
                            codptr = code;
                            
                            expr (NAME);
                            stcpy (code, tmp4);
                            
                            codptr = code;
                            
                            if (argptr[0] == '^') merr_raise (INVREF);
                            if (ierr <= OK) stcpy (zloc, argptr);   /* save reference */

                            break;
                        }
                        if ((!stcmp (&vn[2], "t\201")) || (!stcmp (&vn[2], "tr\201")) || (!stcmp (&vn[2], "trap\201"))) {       /* set $ztrap */
                            
                            if (stlen (argptr) > ZTLEN) {
                                merr_raise (M75);
                                goto err;
                            }
                            
                            /* DSM V.2 error trapping */
#ifdef DEBUG_NEWSTACK
                            printf ("Setting Ztrap, DSM2err [%d]\r\n", DSM2err);
#endif


                            if (DSM2err) {
                                stcpy (ztrap[NESTLEVLS + 1], argptr);
                            }
                            else {
                                stcpy (ztrap[nstx], argptr);
                            }

                        }
                        else if (!stcmp (&vn[2], "p\201") || !stcmp (&vn[2], "precision\201")) { /* set $zprecision */

                            short tmp_zprecise;
                            
                            if ((tmp_zprecise = intexpr (argptr)) < 0) {
                                merr_raise (MXNUM);
                                goto err;
                            }

                            if (!fp_mode) {
                                
                                if (merr () == MXNUM) goto err;

                                if (tmp_zprecise > 20000) {
                                    merr_raise (MXNUM);
                                    goto err;
                                }
                                
                            }
#if !defined(_AIX)			    
                            else {
                                
                                if (tmp_zprecise > DBL_DIG) {
                                    merr_raise (MXNUM);
                                    goto err;
                                }

                                sprintf (fp_conversion, "%%.%df\201", tmp_zprecise);
                                
                            }
#endif			    

                            zprecise = tmp_zprecise;
                            

                        }
                        else if (vn[2] == 'f' && vn[3] == DELIM) {       /* set $zf() function keys */
                            
                            i = intexpr (&vn[4]) - 1;
                            
                            if (i < 0 || i > 43) {
                                merr_raise (FUNARG);
                                goto err;
                            }

                            if (stlen (argptr) > FUNLEN) {
                                merr_raise (M75);
                                goto err;
                            }

                            stcpy (zfunkey[i], argptr);

                        }                    
                        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 */
                            
                            short k;

                            i = 0;

                            for (ch = 0; ch <= 255; ch++) {
                                j = argptr - partition;

                                while ((k = partition[j++]) != EOL) {
                                    
                                    if (UNSIGN (k) == ch) {
                                        tmp[i++] = k;
                                        break;
                                    }

                                }

                            }

                            tmp[i] = EOL;
                            
                            switch (vn[3]) {
                            
                                case 'c':
                                    stcpy (zmc, tmp);
                                    break;
                            
                                case 'n':
                                    stcpy (zmn, tmp);
                                    break;

                                case 'p':
                                    stcpy (zmp, tmp);
                                    break;
                                    /*   'a': always union of zml+zmu */

                                case 'l':
                                    stcpy (zml, tmp);
                                    break;
                            
                                case 'u':
                                    stcpy (zmu, tmp);
                                    break;
                                    /*   'e': always 'everything'     */
                            }

                        }
                        else {
                            merr_raise (INVREF);
                            break;
                        }
                    } 
                    else {
                        merr_raise (INVREF);
                        goto err;
                    } /* end of processing for $Z.. intrinsic special variables */
                }           /* svns=$vars */

                if (multiset) goto multi;
            } /* end of scope for special SET syntaxes */

s_end:
            if (*codptr != ',') break;
            if (*++codptr == '@') goto again;

            goto set0;

        case IF:
            merr_raise (cmd_if (&ra));
            MRESCHECK(ra);
            break;


        case OO_USING:
            merr_raise (cmd_using (&ra));
            MRESCHECK(ra);
	    break;
	    
	case OO_WITH:
            merr_raise (cmd_with (&ra));
            MRESCHECK(ra);
            break;
            
        case WRITE:
            merr_raise (cmd_write(&ra, &i));
            MRESCHECK(ra);
            break;

        case READ:
            merr_raise (cmd_read (&ra));
            MRESCHECK(ra);
            break;

        case ELSE:
            merr_raise (cmd_else (&ra));
            MRESCHECK(ra);
            break;

        case ZQUIT:

        {
            int zq_lvlct;

            if (rtn_dialect () != D_FREEM) {
                merr_raise (NOSTAND);
                goto err;
            }
            
            if (*codptr == EOL) {
                zq_lvlct = nstx;
            }
            else {             
                expr (STRING);

                zq_lvlct = intexpr (argptr);

                if (merr () > OK) goto err;

                if (zq_lvlct < 0 || zq_lvlct > nstx) {
                    merr_raise (LVLERR);
                    goto err;
                }
                else if (zq_lvlct != nstx) {
                    repQUIT = nstx - zq_lvlct;
                }
                else {
                    merr_raise (LVLERR);
                    goto err;
                }
            }
                
            break;
        }
            
        case QUIT:

            if (tp_level > 0) {
                merr_raise (M42);
                goto err;
            }
            
#ifdef DEBUG_NEWSTACK
            printf ("At QUIT command, checking stack...\r\n");
#endif



#ifdef DEBUG_NEWSTACK
            printf ("nestc[nstx] is (%d)\r\n", nestc[nstx]);
#endif

            if (*codptr != EOL && *codptr != SP && nestc[nstx] != '$') {
#ifdef DEBUG_NEWSTACK
                printf ("IERR\r\n");
#endif

                merr_raise (ARGER);
                break;
            }



            if (nestc[nstx] == '$') {           /* extrinsic function/variable */


#ifdef DEBUG_NEWSTACK
                printf ("EXTRINSIC\r\n");
#endif
                //printf (" extr_types[%d] = '%d'\r\n", nstx, extr_types[nstx]);
                if (*codptr == EOL || *codptr == SP) {

#ifdef DEBUG_NEWSTACK
                    printf ("CODPTR is [%d]\r\n", *codptr);
#endif

                    if (exfdefault[0] == EOL) {
                        *argptr = EOL;
                        merr_raise (NOVAL);
                    }
                    else { /* there is a default expression... */
                        stcpy (&code[1], exfdefault);
                        expr (STRING);

                        if (ierr != OK - CTRLB && merr () != OK && merr () != INRPT) {

#ifdef DEBUG_NEWSTACK
                            printf ("Break at 1st IERR\r\n");
#endif
                            break;
                        }
                    }
                }
                else {                    
                    
                    expr (STRING);
                    
                    if (ierr != OK - CTRLB && merr () != OK && merr () != INRPT) {

#ifdef DEBUG_NEWSTACK
                        printf ("Break at 2nd IERR\r\n");
#endif

                        break;
                    }

                    if (dt_check (extr_types[nstx], argptr, 0) == FALSE) {
                        extr_types[nstx] = DT_STRING;
                        merr_raise (TYPMISMATCH);
                        break;
                    }

                    
                }

#ifdef DEBUG_NEWSTACK
                printf ("CHECK 01 (Stack POP)\r\n");
#endif



                if (nestn[nstx]) {           /* reload routine */
                    namptr = nestn[nstx];

                    stcpy (rou_name, namptr);
                    zload (rou_name);
                    
                    ssvn_job_update ();

                    dosave[0] = 0;
                    
                    namptr--;
                }

                if (nestnew[nstx]) unnew ();       /* un-NEW variables */
                
                /* restore old pointers */
                level = nestlt[nstx];   /* pop level */
                roucur = nestr[nstx] + rouptr;

                extr_types[nstx] = DT_STRING;
                
                stcpy (codptr = code, cmdptr = nestp[nstx--]);
                estack--;
                
                forsw = (nestc[nstx] == FOR);
                loadsw = TRUE;
                
                return 0;


            }


            if (nestc[nstx] == BREAK) {
                merr_clear ();
                merr_set_break ();
                goto zgo;
            }           /*cont. single step */


quit0:

#ifdef DEBUG_NEWSTACK
            printf ("CHECK 02 (Stack POP)\r\n");
#endif

            if (evt_depth) {
                    
                evt_depth--;
                    
                if (evt_depth == 0 && evt_async_restore == TRUE) {
                    evt_async_enabled = TRUE;
                    evt_async_restore = FALSE;
                }

            }

            if (etrap_lvl) etrap_lvl--;

            if (nstx == 0) goto restore;       /* nothing to quit */

            if (nestc[nstx] == FOR) {
                
                stcpy (code, cmdptr = nestp[nstx--]);

                estack--;
            
                codptr = code;
            
                ftyp = fortyp[--forx];
                fvar = forvar[forx];
                finc = forinc[forx];
                fpost = forpost[forx];
                flim = forlim[forx];
                fi = fori[forx];

                if ((forsw = (nestc[nstx] == FOR))) goto for_end;
            
                goto next_line;
            }

            if (nestn[nstx]) {           /* reload routine */
                namptr = nestn[nstx];

                if ((nestc[nstx] != XECUTE) || loadsw) {
                    
                    stcpy (rou_name, namptr);
                    zload (rou_name);
                
                    ssvn_job_update ();

                    dosave[0] = 0;
                }

                namptr--;
            }

            if (nestnew[nstx]) unnew ();       /* un-NEW variables */

            /* restore old pointers */
            if ((mcmnd = nestc[nstx]) == BREAK) goto restore;       /* cont. single step */

            if (mcmnd == DO_BLOCK) {
                test = nestlt[nstx];
                level--;
            }
            else { /* pop $TEST */
                level = nestlt[nstx];   /* pop level */
            }

            if (nstx) {
                roucur = nestr[nstx] + rouptr;
            }
            else {
                roucur = buff + (NO_OF_RBUF * PSIZE0 + 1);
            }

            stcpy (codptr = code, cmdptr = nestp[nstx--]);
            estack--;
            forsw = (nestc[nstx] == FOR);
            
            loadsw = TRUE;

            if (deferred_ierr > OK) { /* smw - TODO: how to handle deferred_ierr now */
                merr_raise (deferred_ierr);
            }

#if defined(HAVE_MWAPI_MOTIF)            
            if ((in_syn_event_loop == TRUE) && (nstx == syn_event_entry_nstx)) goto syn_evt_loop_bottom;
#endif            
            
            break;

        case FOR:

            if ((ch = *codptr) == EOL) goto skip_line;     /* ignore empty line */

#ifdef DEBUG_NEWSTACK
            printf ("CHECK 03 (Stack PUSH)\r\n");
#endif

            
            if (++nstx > NESTLEVLS) {
                nstx--;                
                merr_raise (STKOV);
            
                break;
            }
            else {
                estack++;
            }

            fvar = forvar[++forx];
            finc = forinc[forx];
            fpost = forpost[forx];
            flim = forlim[forx];
            fi = fori[forx];
            nestc[nstx] = FOR;  /* stack set-up */

#ifdef DEBUG_NEWSTACK
            if (!cmdptr) printf ("CMDPTR is ZERO!\r\n");
#endif

            nestp[nstx] = cmdptr;
            nestn[nstx] = 0;        /* no overring of routine */
            nestr[nstx] = roucur - rouptr;  /* save roucur: only for $V(26) needed */
            ztrap[nstx][0] = EOL;


            forsw = TRUE;
            ftyp = 0;           /* no args is FOREVER */

            if (ch == SP) {
                goto for_go;
            }
            else {           /* find local variable */
                
                if (ch == '^') {
                    merr_raise (GLOBER);
                    break;
                }
                
                if (ch == '$') {
                    merr_raise (INVREF);
                    break;
                }

                if (*(codptr + 1) == '=') {           /* single char local variable */

                    if ((ch < 'A' && ch != '%') || (ch > 'Z' && ch < 'a') || ch > 'z') {
                        merr_raise (INVREF);
                        break;
                    }

                    fvar[0] = ch;
                    fvar[1] = EOL;
                    
                    codptr += 2;
                }
                else {
                    expr (NAME);

                    if (*++codptr != '=') merr_raise (ASSIGNER);
                    if (merr () != OK) break;

                    stcpy (fvar, varnam);

                    codptr++;
                }

                ftyp++;
            }

for_nxt_arg:

            expr (STRING);
            
            if (merr () != OK) break;

            stcpy (tmp, argptr);

            if ((ch = *codptr) != ':') {
                
                if (ch == ',' || ch == SP || ch == EOL) {
                    ftyp = 1;
                    goto for_init;
                }
            
                merr_raise (ARGLIST);
                break;
            }

            numlit (tmp);       /* numeric interpretation */

            codptr++;
            expr (STRING);
            
            if (merr () != OK) break;
            
            numlit (argptr);
            stcpy (finc, argptr);   /* increment */
            
            if ((ch = *codptr) != ':') {
                
                if (ch == ',' || ch == EOL || ch == SP) {
                    ftyp = 2;
                    goto for_init;
                }

                merr_raise (ARGLIST);
                break;

            }

            codptr++;

            expr (STRING);
            if (merr () != OK) break;

            numlit (argptr);
            stcpy (flim, argptr);   /* limit */

            ftyp = 3;

            if ((ch = *codptr) != ',' && ch != SP && ch != EOL) {
                merr_raise (ARGLIST);
                break;
            }

            if ((*finc != '-' && comp (flim, tmp)) || (*finc == '-' && comp (tmp, flim))) {
            
                symtab (set_sym, fvar, tmp);
            
                if (merr () > OK) {
                    stcpy (varerr, vn);
                    break;
                }
            
                goto for_quit;
            }

for_init:

            symtab (set_sym, fvar, tmp);

            if (merr () > OK) {
                stcpy (varerr, fvar);
                break;
            }

            /* optimize frequent special case: */
            /* increment by one and no additional FOR arguments */
            /* if limit value it must be a positive integer */
            if (ftyp > 1 && finc[0] == '1' && finc[1] == EOL) {
                j = TRUE;
                
                if (ftyp == 3) {
                    i = 0;

                    while ((ch = flim[i]) != EOL) {
                        
                        if (ch < '0' || ch > '9') j = FALSE;
                    
                        i++;
                    }

                    fi = i;
                    fori[forx] = i;
                }

                if (j && ((ch = *codptr) == SP || ch == EOL)) {
                    ftyp += 2;                
                    if (ch == SP) codptr++;
                }
            }

for_go:

            fortyp[forx] = ftyp;


#ifdef DEBUG_NEWSTACK
            if (!cmdptr) printf ("CMDPTR is ZERO!\r\n");
#endif

            nestp[nstx] = cmdptr;

            cmdptr += stcpy (cmdptr, codptr) + 1;

            if (ftyp > 3) goto next_cmnd;

            /* skip following for arguments if there are any */

for10:

            if (*codptr == SP) goto next_cmnd;

            i = 0;

            while ((((ch = *codptr) != SP) || i) && ch != EOL) {                
                if (ch == '"') i = !i;                

                codptr++;
            }           /* skip rest of FOR list */

            goto next_cmnd;

for_end:            /* end of line return */

#ifdef DEBUG_NEWSTACK
            printf ("For_end: nstx: %d, Nestp: (%d)\r\n", nstx, nestp[nstx]);
#endif

            stcpy (codptr = code, nestp[nstx]); /* restore old pointers */



            switch (ftyp) {
                
                case 5:     /* frequent special case: increment 1 */
                    symtab (getinc, fvar, tmp);

                    /*  compare fvar-value to flim-value */
                    /* fi: i=0; while (flim[i]>='0') i++; */
                    /* Note: EOL<'-'<'.'<'0' tmp has at least one character */
                    ch = '0';
                    j = 1;

                    while (tmp[j] >= ch) j++;
                    
                    if (j < fi) goto next_cmnd;
                    
                    if (j == fi) {
                        j = 0;
                    
                        while (tmp[j] == flim[j]) {
                            if (tmp[j] == EOL) goto next_cmnd;
                            j++;
                        }
                        
                        if (tmp[j] <= flim[j]) goto next_cmnd;
                    }
                    
                    if (flim[0] != '-' && tmp[0] == '-') goto next_cmnd;

                    stcpy (tmp2, "-1\201"); /* correct last inc */
                    add (tmp, tmp2);
                    symtab (set_sym, fvar, tmp);

                    goto for_quit;
                
                case 4:     /* frequent special case: increment 1 without limit */
                    symtab (getinc, fvar, tmp);
                    
                    
                case 0:     /* argumentless FOR */

                    if(argless_forsw_quit == TRUE) {
                        /* if we have a positive QUIT condition, bail from the FOR loop */
                        argless_forsw_quit = FALSE;
                        goto for_quit;
                    }
                    else {

                        /* otherwise, just keep on truckin' */
                        goto next_cmnd;
                    }

                case 3:     /* FOR with increment and limit test */
                    symtab (get_sym, fvar, tmp);
                    numlit (tmp);
                    stcpy (tmp2, finc); /* add may change forinc */
                    add (tmp, tmp2);

                    if (*finc != '-') {
                        if (comp (flim, tmp)) goto for_quit;
                    }
                    else {
                        if (comp (tmp, flim)) goto for_quit;
                    }

                    symtab (set_sym, fvar, tmp);

                    goto for10;

                case 2:     /* FOR with increment without limit test */
                    symtab (get_sym, fvar, tmp);
                    numlit (tmp);
                    stcpy (tmp2, finc); /* add may change forinc */
                    add (tmp, tmp2);

                    symtab (set_sym, fvar, tmp);
                    goto for10;
            }           /* end switch */

for_quit:

            cmdptr = nestp[nstx];


            if (*codptr++ == ',') goto for_nxt_arg;

            forpost[forx][0] = '\0';

            nstx--;
            estack--;

            forx--;
            ftyp = fortyp[forx];
            fvar = forvar[forx];
            finc = forinc[forx];
            flim = forlim[forx];
            fi = fori[forx];


            if ((forsw = (nestc[nstx] == FOR))) goto for_end;

            if (sigint_in_for) {
                merr_raise (INRPT);
                sigint_in_for = FALSE;
            }
            
            if (merr () > OK) goto err;
            goto next_line;

        case MERGE:

            {
                char lhs[256];
                char rhs[256];

                char k_buf[STRLEN];

                if ((rtn_dialect () != D_M95) &&
                    (rtn_dialect () != D_MDS) &&
                    (rtn_dialect () != D_M5) &&
                    (rtn_dialect () != D_FREEM)) {
                    merr_raise (NOSTAND);
                    goto err;
                }
                
                expr (NAME);
                if (merr () > OK) break;

                key_to_name (lhs, varnam, 255);
                stcnv_c2m (lhs);

                if (*++codptr != '=') {
                    merr_raise (ASSIGNER);
                    break;
                }

                codptr++;

                expr (NAME);
                if (merr () > OK) break;

                codptr++;

                key_to_name (rhs, varnam, 255);
                stcnv_c2m (rhs);

                stcpy (k_buf, "%INTMERGELHS\201\201");
                symtab (set_sym, k_buf, lhs);

                stcpy (k_buf, "%INTMERGERHS\201\201");
                symtab (set_sym, k_buf, rhs);
                
                stcpy (&tmp3[1], "SYSWMERGE \201");
                goto private;

                break;

            }

        
        case RLOAD:
            if ((rtn_dialect () != D_MDS) &&
                (rtn_dialect () != D_FREEM)) {
                merr_raise (NOSTAND);
                goto err;
            }
            stcpy (&tmp3[1], "zrload \201");
            goto private;


        case RSAVE:
            if ((rtn_dialect () != D_MDS) &&
                (rtn_dialect () != D_FREEM)) {
                merr_raise (NOSTAND);
                goto err;
            }

            stcpy (&tmp3[1], "zrsave \201");
            goto private;


        case XECUTE:
            

do_xecute:            
            expr (STRING);

            if (merr () > OK) break;
            
            stcpy (tmp, argptr);

            if (*codptr == ':') {           /* argument postcond */                
                codptr++;
                expr (STRING);
                
                if (merr () > OK) break;
                if (tvexpr (argptr) == FALSE) break;
            }
            
            if (++nstx > NESTLEVLS) {
                nstx--;
                merr_raise (STKOV);
            
                break;
            }
            else {
                estack++;
            }


#ifdef DEBUG_NEWSTACK
            if (!cmdptr) printf ("CMDPTR is ZERO!\r\n");
#endif

            nestc[nstx] = XECUTE;            
            nestp[nstx] = cmdptr;   /* command stack address */
            nestr[nstx] = roucur - rouptr;  /* save roucur */
            nestlt[nstx] = level;
            
            level = 0;      /* save level */
            nestnew[nstx] = 0;
            ztrap[nstx][0] = EOL;

            while ((*(namptr++)) != EOL);

            stcpy ((nestn[nstx] = namptr), rou_name);   /* save routine name */

            forsw = FALSE;
            loadsw = FALSE;
            cmdptr += stcpy (cmdptr, codptr) + 1;

            stcpy (code, tmp);

            roucur = buff + (NO_OF_RBUF * PSIZE0 + 1);
            codptr = code;

            goto next_cmnd;

        
        case DO:

            if (evt_async_initial == TRUE) {
                evt_async_initial = FALSE;
            }
            else {
                evt_depth++;
            }

            rouoldc = roucur - rouptr;
            namold = 0;

        case GOTO:

do_goto:

            offset = 0;
            label[0] = routine[0] = EOL;
            dofram0 = 0;

            if (((ch = *codptr) != '+') && (ch != '^')) {           /* parse label */  
                          
                if (ch == SP || ch == EOL) {           /* no args: blockstructured DO */

                    if (mcmnd != DO) {
                        merr_raise (ARGLIST);
                        break;                    
                    }

                    /* direct mode: DO +1 */


                    if (nstx == 0 && roucur >= rouend) {
                        roucu0 = rouptr;
                        goto off1;
                    }

                    mcmnd = DO_BLOCK;
                    roucu0 = roucur;    /* continue with next line */
                    forsw = FALSE;
                
                    goto off2;
                }

                expr (LABEL);
                
                if (merr () > OK) goto err;

                stcpy (label, varnam);

                ch = *++codptr;
            }

            if (ch == '+') {           /* parse offset */
                
                codptr++;
                expr (OFFSET);

                if (merr () > OK) goto err;
                
                offset = intexpr (argptr);
                dosave[0] = EOL;
                
                /* unless argument is numeric, expr returns wrong codptr */
                if ((ch = *codptr) != SP && (ch != EOL) && (ch != ',') && (ch != '^')) ch = *++codptr;
            
            }

            if (ch == '^') {           /* parse routine */
                codptr++;
                expr (LABEL);

                if (merr () > OK) goto err;
                
                stcpy (routine, varnam);
                
                dosave[0] = EOL;
                ch = *++codptr;
                loadsw = TRUE;
            }

            if (ch == '(' && mcmnd == DO) {           /* parse parameter */

                if (offset) {
                    merr_raise (ARGLIST);
                    goto err;
                }

                if (*++codptr == ')') {
                    ch = *++codptr;
                }
                else {
                    dofram0 = dofrmptr;
                    i = 0;
                    
                    for (;;) {
                        setpiece = TRUE;    /* to avoid error on closing bracket */
                    
                        if (*codptr == '.' && (*(codptr + 1) < '0' || *(codptr + 1) > '9')) {
                            codptr++;
                            
                            expr (NAME);
                            codptr++;
                            
                            *dofrmptr++ = DELIM;    /* to indicate call by name */
                            dofrmptr += stcpy (dofrmptr, varnam) + 1;
                        }
                        else {
                            expr (STRING);
                            dofrmptr += stcpy (dofrmptr, argptr) + 1;
                        }
                    
                        setpiece = FALSE;
                        i++;
                        
                        if (merr () > OK) {
                            dofrmptr = dofram0;
                            goto err;
                        }
                    
                        ch = *codptr++;
                        if (ch == ',') continue;
                    
                        if (ch != ')') {
                            merr_raise (COMMAER);
                            dofrmptr = dofram0;
                    
                            goto err;
                        }
                    
                        ch = *codptr;
                        break;
                    }
                }
            }

            if (ch == ':') {           /* parse postcond */
                
                codptr++;
                expr (STRING);
                
                if (merr () > OK) {
                    if (dofram0) dofrmptr = dofram0; /* reset frame pointer */
                    goto err;
                }

                if (tvexpr (argptr) == FALSE) {
                    if (*codptr != ',') mcmnd = 0;  /* avoid false LEVEL Error */
                    if (dofram0) dofrmptr = dofram0; /* reset frame pointer */
                
                    break;
                }
            }

            if (mcmnd == GOTO) {           /* GOTO: clear FORs from stack */
                
#ifdef DEBUG_NEWSTACK
                printf ("CHECK 05 Multi-POP on FOR\r\n");
#endif



                while (nestc[nstx] == FOR) {
                
#ifdef DEBUG_NEWSTACK
                    printf ("POP");
#endif

                    cmdptr = nestp[nstx--];
                    estack--;

                    forx--;
                    ftyp = fortyp[forx];
                    fvar = forvar[forx];
                    finc = forinc[forx];
                    flim = forlim[forx];
                    fi = fori[forx];
                }

#ifdef DEBUG_NEWSTACK
                printf ("\r\n");
#endif


                loadsw = TRUE;
            }

job_entry:     /* entry called from successful JOB */

            if (routine[0] != EOL) {

#ifdef DEBUG_NEWSTACK
                printf ("CHECK 06\r\n");
#endif

                if (mcmnd == DO) {

                    while ((*(namptr++)) != EOL);
                    
                    namold = namptr;
                    stcpy (namptr, rou_name);

                    ssvn_job_update ();

                }

                    /* if (GOTO label^rou) under a (DO label)   */
                    /* save away old routine to restore on quit */


                
                else if (nstx > 0) {

#ifdef DEBUG_NEWSTACK
                    printf ("CHECK 06, stack is greater than 0\r\n");
#endif

                    while (nestc[nstx] == FOR) {
#ifdef DEBUG_NEWSTACK
                        printf ("POP");
#endif

                        nstx--;
                        estack--;
                        forx--;
                        ftyp = fortyp[forx];
                        fvar = forvar[forx];
                        finc = forinc[forx];
                        flim = forlim[forx];
                        fi = fori[forx];
                    }

                    if (nestn[nstx] == 0) {                        
                        while ((*(namptr++)) != EOL);

                        stcpy ((nestn[nstx] = namptr), rou_name);
                    }
                }

                zload (routine);                
                if (merr () > OK) goto err;       /* load file */

                ssvn_job_update ();
            
            } /* if (routine[0] != EOL) */
            {
                char *reg, *reg1;

                reg1 = rouptr;
                reg = reg1;

                if (label[0] != EOL) {
                
                    if (forsw && mcmnd == DO && stcmp (label, dosave) == 0) {
                        roucu0 = xdosave;
                        goto off1;
                    }

                    while (reg < rouend) {
                        reg++;
                        j = 0;
                    
                        while (*reg == label[j]) {
                            reg++;
                            j++;
                        }

                        if (label[j] == EOL) {
                            
                            if (*reg == TAB || *reg == SP) goto off;
                            
                            /* call of procedure without specifying a parameter list */
                            if (*reg == '(') {                                
                                if (dofram0 == 0) dofram0 = dofrmptr;                            
                                goto off;
                            }

                        }

                        reg = (reg1 = reg1 + UNSIGN (*reg1) + 2);
                    }
                    {
                        merr_raise (M13);
                        stcpy (varerr, label);  /* to be included in error message */
                        
                        if (dofram0) dofrmptr = dofram0; /* reset frame pointer */
                        
                        zload (rou_name);
                        ssvn_job_update ();                        
                        goto err;
                    }
                }
off:
                if (label[0] == EOL && offset > 0) offset--;
                while (offset-- > 0) reg1 = reg1 + (UNSIGN (*reg1) + 2);
                
                if (forsw) {
                    xdosave = reg1;
                    stcpy (dosave, label);
                }

                roucu0 = reg1;
            }

            if (roucu0 >= rouend) {
                merr_raise (M13);
                stcpy (varerr, label);  /* to be included in error message */

                if (dofram0) dofrmptr = dofram0; /* reset frame pointer */
                
                zload (rou_name);
                ssvn_job_update ();
                goto err;
            }

off1:
            if (routine[0] != EOL) stcpy (rou_name, routine);

            ssvn_job_update ();            

            roucu0++;
            forsw = FALSE;

            if (mcmnd != DO) {           /* i.e. GOTO or JOB */
                roucur = roucu0;
                goto off3;
            }

off2:

#ifdef DEBUG_NEWSTACK
            printf ("CHECK 07 (Stack PUSH)\r\n");
#endif



            if (++nstx > NESTLEVLS) {
                nstx--;
                merr_raise (STKOV);
            
                goto err;
            }
            else {
                on_frame_entry ();
                estack++;
            }

            nestc[nstx] = mcmnd;

#ifdef DEBUG_NEWSTACK
            if (!cmdptr) printf ("CMDPTR is ZERO!\r\n");
#endif

            nestp[nstx] = cmdptr;
            nestn[nstx] = namold;
            nestr[nstx] = rouoldc;
            nestnew[nstx] = 0;

            if (mcmnd != DO_BLOCK) {
                nestlt[nstx] = level;
                level = 0;
            }
            else { /* push level ; clr level */
                nestlt[nstx] = test;
                level++;
            }           /* push $TEST ; inc level */

            ztrap[nstx][0] = EOL;


            cmdptr += stcpy (cmdptr, codptr) + 1;
            roucur = roucu0;

            /* processing for private Z-Command: */
            if (privflag) {



#ifdef DEBUG_NEWPTR
                printf ("Xecline 01 (using NEWPTR): ");
                printf ("[nstx] is [%d], [nestnew] is [%d]", nstx, nestnew[nstx]);
                printf ("- Initialized to newptr\r\n");
#endif /* Debug */

                nestnew[nstx] = newptr;


                stcpy (vn, zargdefname);

                /*was:      vn[0] = '%';   vn[1] = EOL; */

                symtab (new_sym, vn, "");
                /*djw change 'input variable for Z command' to get value of $V(202) */
                /*was:      vn[0] = '%';   vn[1] = EOL; */

                stcpy (vn, zargdefname);
                symtab (set_sym, vn, tmp2);

                privflag = FALSE;
            }

off3:

            if (dofram0) {
                char *reg, *reg1;

                reg = roucu0;
                reg1 = dofram0;
            
                while ((ch = (*reg++)) != '(') {
                    if (ch == SP || ch == TAB || ch == EOL) break;
                }

                if (ch != '(') {
                    merr_raise (TOOPARA);
                    dofrmptr = dofram0;
            
                    goto err;
                }
            
                j = 0;

                while ((ch = (*reg++)) != EOL) {
            
                    if ((ch == ',' && j) || ch == ')') {
                        varnam[j] = EOL;



#ifdef DEBUG_NEWPTR
                        printf ("Xecline 02: ");
                        printf ("[nstx] is [%d], [nestnew] is [%d]\r\n", nstx, nestnew[nstx]);
#endif

                        if (nestnew[nstx] == 0) nestnew[nstx] = newptr;
            


                        if (reg1 < dofrmptr) {

                            if (*reg1 == DELIM) {   /* call by reference */
                            
                                if (stcmp (reg1 + 1, varnam)) {   /* are they different?? */
                                    symtab (new_sym, varnam, "");
                                    symtab (m_alias, varnam, reg1 + 1);
                                }

                            }
                            else {
                                symtab (new_sym, varnam, "");   /* call by value */
                                symtab (set_sym, varnam, reg1);
                            }

                            reg1 += stlen (reg1) + 1;
                        }
                        else {
                            symtab (new_sym, varnam, "");
                        }

                        if (ch == ')') break;
                
                        j = 0;
                        continue;
                    }

                    if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9' && j) || (ch == '%' && j == 0)) {
                        varnam[j++] = ch;
                        continue;
                    }

                    merr_raise (ARGLIST);
                    dofrmptr = dofram0; /* reset frame pointer */
                    
                    goto err;
                }

                if (reg1 < dofrmptr) {
                    merr_raise (TOOPARA);
                    dofrmptr = dofram0;

                    goto err;
                }

                dofrmptr = dofram0;
            }

            goto next_line;

        /* ZJOB *//* same as JOB, but without timeout */
        /* not recommended; just for backward compatibility */
        case ZJOB:
            if (is_standard ()) {
                merr_raise (NOSTAND);
                goto err;
            }

        case JOB:

            if (rtn_dialect () == D_M77) {
                merr_raise (NOSTAND);
                goto err;
            }
            
            if (*codptr == SP || *codptr == EOL) {
                merr_raise (M13);
                varerr[0] = EOL;    /* to be included in error message */

                break;
            }

            loadsw = TRUE;
            offset = 0;
            frm_timeout = (-1L);
            label[0] = routine[0] = EOL;

            if (((ch = *codptr) != '+') && (ch != '^')) {           /* parse label */
                expr (LABEL);
                if (merr () > OK) goto err;

                stcpy (label, varnam);

                ch = *++codptr;
            }

            if (ch == '+') {           /* parse offset */
                codptr++;

                expr (OFFSET);
                if (merr () > OK) goto err;

                offset = intexpr (argptr);
                
                /* unless argument is numeric, expr returns wrong codptr */
                if ((ch = *codptr) != SP && (ch != EOL) && (ch != ',') && (ch != '^')) ch = *++codptr;
            
            }

            if (ch == '^') {           /* parse routine */
                codptr++;
                
                expr (LABEL);
                if (merr () > OK) goto err;

                stcpy (routine, varnam);

                dosave[0] = EOL;
                ch = *++codptr;
            }

            dofram0 = NULL;
            if (ch == '(') {           /* parse parameter */
                
                if (offset) {
                    merr_raise (ARGLIST);
                    goto err;
                }
                
                codptr++;
                dofram0 = dofrmptr;
                
                i = 0;
                for (;;) {
                    setpiece = TRUE;    /* to avoid error on closing bracket */
                    
                    if (*codptr == '.' && (*(codptr + 1) < '0' || *(codptr + 1) > '9')) {
                        codptr++;
                        
                        expr (NAME);
                        
                        codptr++;
                        
                        *dofrmptr++ = DELIM;    /* to indicate call by name */
                        dofrmptr += stcpy (dofrmptr, varnam) + 1;
                    }
                    else {
                        expr (STRING);
                        dofrmptr += stcpy (dofrmptr, argptr) + 1;
                    }

                    setpiece = FALSE;
                    i++;
                    
                    if (merr () > OK) {
                        dofrmptr = dofram0;
                        goto err;
                    }

                    ch = *codptr++;
                    if (ch == ',') continue;

                    if (ch != ')') {
                        merr_raise (COMMAER);
                        dofrmptr = dofram0;

                        goto err;
                    }

                    ch = *codptr;
                    break;
                }
            }

            if (ch == ':' && *(codptr + 1) == ch) {
                codptr++;       /* timeout,no jobparams */                
            }
            else if (ch == ':' && *(codptr + 1) == '(') { /* parse any 'job parameters', but ignore them otherwise */
                codptr++;
                setpiece = TRUE;    /* to avoid bracket error at end of jobparameters */

                for (;;) {
                    if (*++codptr != ':') expr (STRING);
                    if (*codptr == ':') continue;
                    if (*codptr++ != ')') merr_raise (ARGER);

                    break;
                }

                setpiece = FALSE;
                ch = (*codptr);
            }

            if (ch == ':') {           /* timeout */
                codptr++;
                expr (STRING);

                if ((frm_timeout = intexpr (argptr)) < 0L) frm_timeout = 0L;
                if (merr () > OK) goto err;

                test = TRUE;
            }

            if (mcmnd == ZJOB) frm_timeout = 0L;       /* ZJOB-command has timeout 0 */

            close_all_globals ();   /* close all globals */
            j = getpid ();      /* job number of father process */

            if (lonelyflag) {           /* single user */
                if (frm_timeout < 0L) {
                    merr_raise (PROTECT); /* error without timeout */
                }
                else {
                    test = FALSE;   /* timeout always fails */
                }
                
                break;
            }

            while ((i = fork ()) == -1) {
            
                if (frm_timeout == 0L) {
                    test = FALSE;
                    break;
                }
                
                if (frm_timeout > 0L) frm_timeout--;
                
                sleep (1);

            }

            if (mcmnd == ZJOB && zjobflag) {
                
                if (i == 0) {           /* we are in child process */
                    intstr (zb, j); /* $JOB of father job */
                    
                    father = j;
                    pid = getpid ();    /* this is our new job number */

                    jobtime = time (0L);;


                    nstx = 0;       /* clear stack */
                    estack = 0;

                    forx = 0;
                    forsw = FALSE;
                    level = 0;
                    cmdptr = cmdstack;  /*  -  command stack pointer */
                    namptr = namstck;   /*  -  routine name stack pointer */
                    usermode = 0;   /* application mode */
                    merr_clear ();

                    lock (" \201", -1, 'j');    /* tell lock about JOB */
                    goto job_entry;
                }

                /* ignore signal while here */
                sig_attach (SIGUSR1, SIG_IGN);

                while (wait (&zsystem) != i);

                sig_attach (SIGUSR1, &oncld);   /* restore handler */

                merr_clear ();      /* there might be a INRPT from other job */
    
                set_io (MUMPS);
                break;
            }

            if (i == 0) {           /* we are in child process */
                
                intstr (zb, j); /* $JOB of father job */
                father = j;

                pid = getpid ();    /* $J = process ID */
                usermode = 0;       /* no programmer mode */
                DSW |= BIT0;        /* disable echo */
                zbreakon = DISABLE; /* disable CTRL/B */
                breakon = DISABLE;  /* disable CTRL/C */
                hardcopy = DISABLE; /* disable hardcopy function */
                
                fclose (stdin); /* close normal input */
                
                jour_flag = 0;  /* no protocol */
                

                nstx = 0;       /* clear stack */
                estack = 0;

                forx = 0;
                forsw = FALSE;
                level = 0;
                
                cmdptr = cmdstack;  /*  -  command stack pointer */
                namptr = namstck;   /*  -  routine name stack pointer */
                
                /* init random number */
                if ((nrandom = time (0L) * getpid ()) < 0) nrandom = (-nrandom);
                
                merr_clear ();
                lock (" \201", -1, 'j');    /* tell lock about JOB */

                goto job_entry;
            }

            intstr (zb, i);     /* $JOB of the process just started */
            break;

        case KILL:
            
            /* argumentless: KILL all local variables */
            if (((ch = *codptr) == SP) || ch == EOL) {
                symtab (kill_all, "", "");
                break;
            }

            if (ch != '(') {
                char destc[255];
                register int cd;

                destc[0] = '\0';
                
                expr (NAME);
            
                /* aviod a disaster if someone types KILL ^PATDAT[TEST] ! */
                if (((ch = *++codptr) != SP) && ch != EOL && ch != ',') merr_raise (INVREF);
                if (merr () > OK) goto err;
            
                if (varnam[0] == '^') {
                    if (varnam[1] != '$') {
                        global (kill_sym, varnam, tmp);
                    }
                    else {
                        ssvn (kill_sym, varnam, tmp);
                    }
                    break;
                }

                symtab (kill_sym, varnam, tmp);
               
                if (destructor_ct) {

                    for (cd = 0; cd < destructor_ct; cd++) {
                        if (strlen (destructors[cd]) > 0) {
                            strcat (destc, destructors[cd]);
                            strcat (destc, ",");
                        }
                    }

                    destructor_ct = 0;                    
                    destc[strlen(destc) - 1] = '\201';

                    stcpy (&tmp3[1], destc);
                    destructor_run = TRUE;
                    
                    goto private;
                }
                
                
                break;
            }

            /* exclusive kill */
            tmp[0] = SP;
            tmp[1] = EOL;

            for (;;) {

                codptr++;
                expr (NAME);
                
                if (merr () > OK) goto err;
                
                if (varnam[0] == '^') {
                    merr_raise (GLOBER);
                    goto err;
                }
                
                i = 0;
                while (varnam[i] != EOL) {

                    if (varnam[i] == DELIM) {
                        merr_raise (SBSCR);
                        goto err;
                    }

                    i++;
                }

                if (stcat (tmp, varnam) == 0) {
                    merr_raise (M75);
                    goto err;
                }

                if (stcat (tmp, " \201") == 0) {
                    merr_raise (M75);
                    goto err;
                }

                if ((ch = *++codptr) == ')') {
                    codptr++;
                    break;
                }

                if (ch != ',') {
                    merr_raise (COMMAER);
                    goto err;
                }
            }

            symtab (killexcl, tmp, "");
            break;

        case NEWCMD:
            if ((rtn_dialect () == D_M77) ||
                (rtn_dialect () == D_M84)) {
                merr_raise (NOSTAND);
                goto err;
            }
        /*case ZNEW:*/            
            
            /* argumentless: NEW all local variables */
            if (((ch = *codptr) == SP) || ch == EOL) {
                ch = nstx;

                while (nestc[ch] == FOR) ch--;       /* FOR does not define a NEW level */
                
#ifdef DEBUG_NEWPTR
                printf ("Xecline 03: (TODO - NEW ALL) ");
                printf ("[ch] is %d, [nestnew] is %d\r\n", ch, nestnew[ch]);
#endif

                if (nestnew[ch] == 0) nestnew[ch] = newptr;
                
                symtab (new_all, "", "");
                break;
            }

            if (ch != '(') {
                expr (NAME);
                
                if (merr () > OK) goto err;

                codptr++;
                
                if (varnam[0] == '^') {
                    merr_raise (GLOBER);
                    goto err;
                }

                if (varnam[0] == '$') {
                    i = 0;
                
                    while ((ch = varnam[++i]) != EOL) if (ch >= 'A' && ch <= 'Z') varnam[i] = ch + 32;

                    /* set $reference */    
                    if ((stcmp (&varnam[1], "r\201")) && (stcmp (&varnam[1], "reference\201")) && (stcmp (&varnam[1], "zr\201")) && (stcmp (&varnam[1], "zreference\201")) &&
                        (stcmp (&varnam[1], "t\201")) && (stcmp (&varnam[1], "test\201")) && (stcmp (&varnam[1], "j\201")) && (stcmp (&varnam[1], "job\201")) &&
                        (stcmp (&varnam[1], "zi\201")) && (stcmp (&varnam[1], "zinrpt\201")) && (stcmp (&varnam[1], "et\201")) && (stcmp (&varnam[1], "etrap\201")) &&
                        (stcmp (&varnam[1], "es\201")) && (stcmp (&varnam[1], "estack\201"))) {
                            merr_raise (INVREF);
                            goto err;
                    }
                }

                /* new and set, new object */
                if (*codptr == '=') {

                    if ((rtn_dialect () != D_FREEM)) {
                        merr_raise (NOSTAND);
                        goto err;
                    }
                    
                    codptr++;
                    stcpy (vn, varnam);

                    if (*codptr != '$') {
                        /* this is a new-and-set */
                        expr (STRING);
                        new_and_set = TRUE;
                    }
                    else {
                        if ((*codptr == '$') &&
                            (*(codptr + 1) == '#') &&
                            (*(codptr + 2) == '^')) {

                            char class[255];
                            char constructor[255];
                            char objvar[255];
                            char datres[5];
                            int dat_res;
                            
                            stcpy (objvar, vn);

                            symtab (fra_dat, objvar, datres);
                            dat_res = atoi (datres);

                            if (dat_res > 0) {
                                merr_raise (OBJCONFLICT);
                                goto err;
                            }
                            
                            stcnv_m2c (objvar);
                            
                            codptr += 2;                            
                
                            /* this is probably an object instantiation */
                            expr (NAME);
                            if (merr () > OK) goto err;

                            stcpy (class, varnam);
                            stcnv_m2c (class);                                                       
                            new_object = TRUE;
                            codptr++;
                            
                            obj_get_constructor (constructor, class, objvar);

                            for (dat_res = 0; dat_res < strlen (class); dat_res++) {
                                if (class[dat_res] == '\202') {
                                    class[dat_res] = '\0';
                                    break;
                                }
                            }
                            
                            obj_create_symbols (objvar, class);

                            if (merr () > OK) goto err;

                            snprintf (&tmp3[1], 255, "%s\201", &constructor[1]);
                            goto private;

                        }
                        else {
                            if (*codptr == '$') {
                                expr (STRING);
                                new_and_set = TRUE;
                            }
                            else {
                                merr_raise (ILLFUN);
                                goto err;
                            }
                        }                        
                    }
                        
                    
                    goto set2;
                }

post_new:
                
                ch = nstx;
                
                while (nestc[ch] == FOR) ch--;       /* FOR does not define a NEW level */

#ifdef DEBUG_NEWPTR
                printf ("Xecline 04 (DANGER): ");
                printf ("[ch] is %d, [nestnew] is %d\r\n", ch, nestnew[ch]);
#endif

                if (nestnew[ch] == 0) nestnew[ch] = newptr;
                
                symtab (new_sym, varnam, "");
                break;
            }

            /* exclusive new */
            tmp[0] = SP;
            tmp[1] = EOL;
            
            for (;;) {
                codptr++;
                expr (NAME);

                if (merr () > OK) goto err;

                if (varnam[0] == '^') {
                    merr_raise (GLOBER);
                    goto err;
                }

                if (varnam[0] == '$') {
                    merr_raise (INVREF);
                    goto err;
                }

                i = 0;
                while (varnam[i] != EOL) {

                    if (varnam[i] == DELIM) {
                        merr_raise (SBSCR);
                        goto err;
                    }

                    i++;
                }

                if (stcat (tmp, varnam) == 0) {
                    merr_raise (M75);
                    goto err;
                }

                if (stcat (tmp, " \201") == 0) {
                    merr_raise (M75);
                    goto err;
                }

                if ((ch = *++codptr) == ')') {
                    codptr++;
                    break;
                }

                if (ch != ',') {
                    merr_raise (COMMAER);
                    goto err;
                }
            }

            ch = nstx;
            while (nestc[ch] == FOR) ch--;           /* FOR does not define a NEW level */

#ifdef DEBUG_NEWPTR
            printf ("Xecline 05 (TODO): ");
            printf ("[ch] is %d, [nestnew] is %d\r\n", ch, nestnew[ch]);
#endif

            if (nestnew[ch] == 0) nestnew[ch] = newptr;
            
            symtab (newexcl, tmp, "");
            break;

        case LOCK:

            /* argumentless: UNLOCK */
            if ((ch = *codptr) == SP || ch == EOL) {
                locktab_unlock_all ();
                break;
            }

            if (ch == '+' || ch == '-') {

                if ((rtn_dialect () == D_M77) ||
                    (rtn_dialect () == D_M84)) {
                    merr_raise (NOSTAND);
                    goto err;
                }
                
                tmp[0] = ch;
                ch = (*++codptr);
            }
            else {
                tmp[0] = SP;
            }

            if (ch != '(') {
                expr (NAME);
            
                if (merr () > OK) goto err;

                stcpy (&tmp[1], varnam);
                stcat (tmp, "\001\201");
            }
            else {           /* multiple lock */
                tmp[1] = EOL;

                for (;;) {
                    codptr++;
                    expr (NAME);
                
                    if (merr () > OK) goto err;

                    stcat (tmp, varnam);
                    stcat (tmp, "\001\201");
                    
                    if ((ch = *++codptr) == ')') break;
                    
                    if (ch != ',') {
                        merr_raise (COMMAER);
                        goto err;
                    }
                }

            }

            frm_timeout = (-1L);        /* no timeout */
            
            if (*++codptr == ':') {
                codptr++;
                expr (STRING);
            
                frm_timeout = intexpr (argptr);
            
                if (merr () > OK) goto err;
                if (frm_timeout < 0L) frm_timeout = 0L;
            }

            lock (tmp, frm_timeout, LOCK);
            break;

        case USE:

            if (*codptr == SP || *codptr == EOL) {
                merr_raise (ARGER);
                goto err;
            }

            expr (STRING);
            j = intexpr (argptr);

            if (j > MAXSEQ && j < MAXDEV) {
                io = j;
                goto use_socket;
            }

            if (j < 0 || j > MAXDEV) {
                merr_raise (NODEVICE);
            }
            else if (j != HOME && devopen[j] == 0) {
                merr_raise (NOPEN);
            }

            if (merr () > OK) goto err;

            io = j;

            if (io == HOME && *codptr == ':' && *(codptr + 1) == '(') {

use0:          /* entry point for processing of device parameters */

                codptr += 2;
                j = 1;
                setpiece = TRUE;    /* so a surplus closing bracket will not be an error */
                
                while (*codptr != ')') {

                    if (*codptr == ':') {
                        codptr++;
                        j++;
                    
                        continue;
                    }
                    
                    expr (STRING);
                    
                    if (merr () > OK) {
                        setpiece = FALSE;
                        goto err;
                    }

                    switch (j) {

                        case 1:
                            i = intexpr (argptr);

                            if (i < 0) i = 0;
                            if (i > 255) i = 255;
                            
                            RightMargin = i;                            
                            break;
                        
                        case 3:
                            i = intexpr (argptr);
                            
                            if (i < 0) i = 0;
                            if (i > 255) i = 255;

                            InFieldLen = i;
                            break;
                        
                        case 5:
                            DSW = intexpr (argptr);
                            break;
                        
                        case 7:
                            i = intexpr (argptr);
                            ypos[HOME] = i / 256;
                            xpos[HOME] = i % 256;
                            
                            if (DSW & BIT7) {
                                
                                i = io;
                                io = HOME;
                                argptr[0] = ESC;
                                argptr[1] = '[';
                                argptr[2] = EOL;

                                if (ypos[HOME]) {
                                    intstr (&argptr[2], ypos[HOME] + 1);
                                }

                                if (xpos[HOME]) {
                                    tmp3[0] = ';';
                                    
                                    intstr (&tmp3[1], xpos[HOME] + 1);
                                    stcat (argptr, tmp3);
                                }

                                stcat (argptr, "H\201");
                                write_m (argptr);
                                
                                io = i;
                            }
                            break;
                        
                        case 9:
                            i = 0;
                            j = 0;

                            while ((ch = argptr[i++]) != EOL) LineTerm[j++] = ch;
                            
                            LineTerm[j] = EOL;
                            break;
                        
                        case 10:
                            BrkKey = (*argptr);
                            
                            /* make new break active */
                            set_io (UNIX);
                            set_io (MUMPS);
                    }
                }
                
                setpiece = FALSE;
                codptr++;
                
                break;
            }
            else if (*codptr == ':') {
                codptr++;
                
                if (io == HOME) {           /* old syntax: enable/disable echo */
                    expr (STRING);
                
                    if (merr () > OK) goto err;
                    
                    if (tvexpr (argptr)) {
                        DSW &= ~BIT0;
                    }
                    else {
                        DSW |= BIT0;
                    }

                }
                else {

                    if (*codptr == '(') {
                        codptr++;
                        setpiece = TRUE;
                    }

                    j = 1;
                    
                    while (*codptr != ')') {

                        if (*codptr == ':') {
                            codptr++;
                            j++;
                            
                            continue;
                        }
                        else if (setpiece == FALSE) {
                            merr_raise (SPACER);
                            goto err;
                        }

                        expr (STRING);
                    
                        if (merr () > OK) {
                            setpiece = FALSE;
                            goto err;
                        }
                    
                        switch (j) {
                            
                            case 1:
                                fseek (opnfile[io], (long) intexpr (argptr), 0);
                                break;

                            case 2:
                                frm_crlf[io] = tvexpr (argptr);
                                break;
                            
                            case 3:
                                fm_nodelay[io] = tvexpr (argptr);
                                break;
                        }
                    
                        if (setpiece == FALSE) break;
                    }
                    
                    if (setpiece) {
                        codptr++;
                        setpiece = FALSE;
                    }

                    break;
                }
            }
            break;


use_socket:
            {
                char use_parm[256];
                int upct = 0;                

                if (*codptr == ':') {
                    codptr++;
                }
                else {
                    while ((ch = *(codptr++)) != SP && ch != EOL);
                    codptr--;
                    break;
                }

                if (*codptr != '/') {
                    merr_raise (ARGLIST);
                    goto err;
                }

                codptr++;

                while ((ch = *codptr++) != SP && ch != EOL && isalpha (ch)) {
                    use_parm[upct++] = ch;
                }

                use_parm[upct] = NUL;

                for (upct = 0; upct < strlen (use_parm); upct++) {
                    use_parm[upct] = toupper (use_parm[upct]);
                }

                if (strcmp (use_parm, "CONNECT") == 0) {

                    msck_connect (io);

                    if (merr () > OK) goto err;

                }
                else if (strcmp (use_parm, "BIND") == 0) {
                    write_m("BIND\r\n\201");
                }
                else {
                    merr_raise (ARGLIST);
                    goto err;
                }

                break;

            }

        case OPEN:

            {                
                short k;

                if (*codptr == SP || *codptr == EOL) {
                    merr_raise (FILERR);
                    goto err;
                }

                expr (STRING);
                k = intexpr (argptr);
                
                if (merr () > OK) goto err;

                
                if (k < 0 || k > MAXDEV) {
                    merr_raise (NODEVICE);
                    goto err;
                }

                if (k > MAXSEQ) goto open_socket;

                if (restricted_mode) {
                    merr_raise (NOSTAND);
                    goto err;
                }

                /* need to evaluate the following 6 lines carefully - smw 2023-10-15 */
                if (k != HOME) {
                    frm_crlf[k] = FALSE;
                    fm_nodelay[k] = FALSE;
                    xpos[k] = 0;
                    ypos[k] = 0;
                }
                
                /* OPEN implies a previous CLOSE on same channel */
                if ((k != HOME) && devopen[k]) {
                    
                    fclose (opnfile[k]);
                    devopen[k] = 0;
                
                    if (io == k) io = HOME;
                }

                /* process device parameters on HOME at USE command. */
                if (k == HOME && *codptr == ':' && *(codptr + 1) == '(') goto use0;
                
                if (*codptr != ':') {

                    if (k == HOME) break;
                    
                    if (dev[k][0] == EOL) {
                        merr_raise (FILERR);
                        merr_set_iochan_err (k, FILERR, "file not found");
                        goto err;
                    }

                    goto open10;
                }

                codptr++;
                
                if (k == HOME) {

                    if (*codptr != ':') {           /* turn echo on/off */
                        
                        expr (STRING);
                        
                        if (merr () > OK) goto err;

                        if (tvexpr (argptr)) {
                            DSW &= ~BIT0;
                        }
                        else {
                            DSW |= BIT0;
                        }
                    }

                    if (*codptr == ':') {           /* dummy timeout on HOME */
                        codptr++;

                        if (*codptr != SP && *codptr != EOL) {
                            expr (STRING);
                    
                            if (merr () > OK) goto err;
                        
                            test = TRUE;
                            break;
                        }
                        else {
                            merr_raise (INVEXPR);
                            goto err;
                        }
                    }
                }
                else {
                    int op_pos;

                    expr (STRING);

                    if (merr () > OK) goto err;
                    
                    stcpy (dev[k], argptr);
                    frm_timeout = (-1L);
                    
                    if (*codptr == ':') {
                        
                        codptr++;

                        expr (STRING);                        
                        frm_timeout = intexpr (argptr);
                        
                        if (merr () > OK) goto err;
                        if (frm_timeout < 0L) frm_timeout = 0L;
                    }

open10:

                    j = stcpy (tmp, dev[k]);
                    i = dev[k][j - 1];
                    
                    while (--j >= 0) {
                        if (dev[k][j] == '/') break;
                    }

                    stcpy (tmp2, dev[k]);
                    
                    if (j <= 0) {
                        tmp2[stlen (tmp2)] = NUL;
                        tmp[1] = 'r';
                        i = '+';
                    }                  
                    else { /* default is read+write */
                        tmp2[j] = NUL;

                        j = stcpy (&tmp[1], &tmp[j + 1]);
                        
                        tmp[0] = SP;
                        tmp[j + 1] = SP;
                        tmp[j + 2] = EOL;
                        
                        j = 0;
                        
                        while ((ch = tmp[++j]) != EOL) if (ch >= 'A' && ch <= 'Z') tmp[j] = ch + 32;
                        
                        if (find (" r w a r+ w+ a+ read write append read+ write+ append+ \201", tmp) == FALSE) {
                            tmp[1] = 'r';
                            i = '+';
                        
                            tmp2[strlen (tmp2)] = '/';
                        }
                    }

                    tmp[0] = tmp[1];
                    tmp[1] = NUL;   /* NUL not EOL !!! */
                    
                    if (i == '+') {
                        tmp[1] = i;
                        tmp[2] = NUL;
                    }

                    op_pos = 0;

                open20:
                    
                    if (oucpath[op_pos] != EOL) {

                        j = stlen (dev[k]);
                        
                        while (--j >= 0) if (dev[k][j] == '/') break;                        
                        while (--j >= 0) if (dev[k][j] == '/') break;
                        
                        if (j < 0) {

                            strcpy (tmp3, tmp2);
                            stcpy (tmp2, &oucpath[op_pos]);
                            
                            j = 0;
                            while (tmp2[j] != ':' && tmp2[j] != EOL) j++;

                            tmp2[j] = EOL;
                            
                            stcpy (act_oucpath[k], tmp2);
                            op_pos += j;
                            
                            if (j) tmp2[j++] = '/';

                            strcpy (&tmp2[j], tmp3);
                        }
                    }

                    /* r  = READ only access;
                    * w  = WRITE new file;
                    * a  = WRITE append;
                    * r+ = READ/WRITE access;
                    * w+ = WRITE new file;
                    * a+ = WRITE append;
                    */
                    j = tmp[0];
                    sq_modes[k] = j;

                    if (j == 'r' && tmp[1] == '+') {
                        sq_modes[k] = '+';
                    }
                    
                    if (j == 'r' && frm_timeout < 0L) {

                        errno = 0;
                        
                        while ((opnfile[k] = fopen (tmp2, tmp)) == NULL) {
                            
                            if (errno == EINTR) {
                                errno = 0;
                                continue;
                            }       /* interrupt */
                            
                            if (errno == EMFILE || errno == ENFILE) {
                                close_all_globals ();
                                continue;
                            }

                            if (dev[k][0] != '/' && oucpath[op_pos++] != EOL) {
                                strcpy (tmp2, tmp3);
                                goto open20;
                            }

                            act_oucpath[k][0] = EOL;
                            merr_raise ((errno == ENOENT ? FILERR : PROTECT));

                            switch (merr ()) {
                                
                                case FILERR:
                                    merr_set_iochan_err (k, FILERR, "file not found");
                                    break;

                                case PROTECT:
                                    merr_set_iochan_err (k, PROTECT, "file protection violation");
                                    break;

                            }
                            
                            goto err;
                        }
                        
                        ssvn_job_add_device (k, tmp2);                         
                        
                        devopen[k] = ((i == '+') ? i : j);
                        break;
                    }

                    if (j == 'r' || j == 'w' || j == 'a') {
                        
                        if (frm_timeout >= 0L) {
                            
                            test = TRUE;
                            
                            if (setjmp (sjbuf)) {
                                test = FALSE;
                                goto endopn;
                            }
                            
                            sig_attach (SIGALRM, &ontimo);
                            alarm ((unsigned) (frm_timeout < 3 ? 3 : frm_timeout));
                        }

                        for (;;) {
                            errno = 0;

                            if ((opnfile[k] = fopen (tmp2, tmp)) != NULL) break;
                            if (merr () == INRPT) goto err;
                            if (errno == EINTR) continue;   /* interrupt */
                            
                            if (errno == EMFILE || errno == ENFILE) {
                                close_all_globals ();
                                continue;
                            }

                            if (frm_timeout < 0L) {

                                if (dev[k][0] != '/' && oucpath[op_pos++] != EOL) {
                                    strcpy (tmp2, tmp3);
                                    goto open20;
                                }

                                if (errno == ENOENT) continue;

                                act_oucpath[k][0] = EOL;
                                merr_raise (PROTECT);

                                merr_set_iochan_err (k, PROTECT, "file protection violation");
                                
                                goto err;
                            }

                            if (frm_timeout == 0L) {
                                test = FALSE;
                                goto endopn;
                            }

                            sleep (1);
                            frm_timeout--;
                        }

                        devopen[k] = ((i == '+') ? i : j);
                        endopn:;
                        
                        alarm (0);  /* reset alarm request */
                    }
                    else {
                        merr_raise (ARGLIST);
                        merr_set_iochan_err (k, ARGLIST, "invalid argument");
                        goto err;
                    }
                }


open_socket:
                if (*codptr != ':') {
                    if (j == 'w') {
                        merr_raise (FILEXWR);
                        merr_set_iochan_err (k, FILEXWR, "cannot open existing file for WRITE");
                    }
                    else {
                        merr_raise (ARGLIST);
                        merr_set_iochan_err (k, ARGLIST, "invalid argument");
                    }
                    goto err;
                }

                codptr++;
                expr (STRING);

                if (merr () > OK) goto err;


                stcpy (vn, argptr);
                stcnv_m2c (vn);

                msck_open (k, vn);

                if (merr () > OK) goto err;
                
                ssvn_job_add_device (k, vn);
                
                break; 
            }
            break;

          



        case CLOSE:

            /* no arguments: close all exept HOME */
            if (*codptr == SP || *codptr == EOL) {

                if (rtn_dialect () != D_FREEM) {
                    merr_raise (NOSTAND);
                    break;
                }

                j = 1;
                
                while (j <= MAXDEV) {
                    
                    if (j < FIRSTSCK) {
                        if (jour_flag && (j == 2)) {
                            j++;
                            continue;
                        }
                
                        if (devopen[j]) fclose (opnfile[j]);

                        ssvn_job_remove_device (j);
                        
                        devopen[j++] = 0;
                    }
                    else {
                        msck_close (j++);
                    }

                }

                io = HOME;
                break;
            }

            expr (STRING);
            j = intexpr (argptr);

            if (merr () > OK) break;

            if (j >= FIRSTSCK && j < MAXDEV) {
                msck_close (j);
                ssvn_job_remove_device (j);
                break;
            }

            /*ignore close on illgal units */
            if ((j >= 0 && j <= MAXDEV && j != HOME) && (jour_flag == 0 || (j != 2))) {           /*ignore close on protocol channel */
                
                if (devopen[j]) fclose (opnfile[j]);
                
                devopen[j] = 0;
                
                ssvn_job_remove_device (j);
                
                if (io == j) io = HOME;

            }

            /* parse any 'device parameters', but ignore them otherwise */
            if (*codptr == ':') {
                if (*++codptr != '(') {
                    expr (STRING);
                }
                else {
                    setpiece = TRUE;    /* to avoid bracket error at end of deviceparameters */
                    for (;;)
                    {
                    if (*++codptr != ':')
                    expr (STRING);
                    if (*codptr == ':')
                    continue;
                    if (*codptr++ != ')')
                    merr_raise (ARGER);
                    break;
                    }
                    setpiece = FALSE;
                }
            }

            break;

        case ZHALT:     /* ZHALT */
            
            if (is_standard ()) {
                merr_raise (NOSTAND);
                goto err;
            }
            
        case HA:            /* HALT or HANG */


            /* no arguments: HALT */
            if (*codptr == SP || *codptr == EOL || mcmnd == ZHALT) {

                if (mcmnd == ZHALT && *codptr != SP && *codptr != EOL) {
                    expr (STRING);
                    i = intexpr (argptr);
                
                    if (merr () > OK) break;
                }
                else {
                    halt:i = 0;
                }

                cleanup ();
                
                if (father) {           /* advertise death to parent *//* make sure father is waiting !!! */
                    if ((time (0L) - jobtime) < 120) sleep (2);
                    
                    kill (father, SIGUSR1);
                }

                exit (i);       /* terminate mumps */
            };
            /* with arguments: HANG */


        case HANG:          /* HANG */

            {
                unsigned long int waitsec;
                int millisec;
                
#ifdef USE_GETTIMEOFDAY
                struct timeval timebuffer;
#else
                struct timeb timebuffer;
#endif

                expr (STRING);
                numlit (argptr);

                if (merr () > OK) break;

#if !defined(__linux__)                
                if (argptr[0] == '-') break;      /* negative values without effect */
                if (argptr[0] == '0') break;      /* zero without effect */
#else
                /* on linux, return scheduler timeslice to kernel scheduler for hang 0 and hang with negative values
                   for compatibility with Reference Standard M, only when process is using a realtime scheduling policy */
                if ((argptr[0] == '-') || (argptr[0] == '0')) {                    
                    int policy;

                    policy = sched_getscheduler (0);
                    if ((policy == -1) || ((policy != SCHED_FIFO) && (policy != SCHED_RR))) break;

                    sched_yield ();
                }
#endif
                
                waitsec = 0;
                millisec = 0;
                i = 0;
                
                for (;;) {       /* get integer and fractional part */ 
                    
                    if ((ch = argptr[i++]) == EOL) break;
                    
                    if (ch == '.') {
                        millisec = (argptr[i++] - '0') * 100;
                    
                        if ((ch = argptr[i++]) != EOL) {
                            millisec += (ch - '0') * 10;
        
                            if ((ch = argptr[i]) != EOL) {
                                millisec += (ch - '0');
                            }
                        }
                    
                        break;
                    }

                    waitsec = waitsec * 10 + ch - '0';
                }

                if ((i = waitsec) > 2) i -= 2;

#ifdef USE_GETTIMEOFDAY
                gettimeofday (&timebuffer, NULL);   /* get current time */

                waitsec += timebuffer.tv_sec;   /* calculate target time */
                millisec += timebuffer.tv_usec;
#else
                ftime (&timebuffer);    /* get current time */
                
                waitsec += timebuffer.time; /* calculate target time */
                millisec += timebuffer.millitm;
#endif

                if (millisec >= 1000) {
                    waitsec++;
                    millisec -= 1000;
                }

                /* do the bulk of the waiting with sleep() */
                while (i > 0) {
                    j = time (0L);
                    sleep ((unsigned) (i > 32767 ? 32767 : i)); /* sleep max. 2**15-1 sec */
                    i -= time (0L) - j; /* subtract actual sleeping time */

                    if (merr () == INRPT) goto err;

                    if (evt_async_enabled && (merr () == ASYNC)) goto err;
                }

                /* do the remainder of the waiting watching the clock */
                for (;;) {
                
#ifdef USE_GETTIMEOFDAY
                
                    gettimeofday (&timebuffer, NULL);
                
                    if (timebuffer.tv_sec > waitsec) break;
                    if (timebuffer.tv_sec == waitsec && timebuffer.tv_usec >= millisec) break;
#else
                    ftime (&timebuffer);

                    if (timebuffer.time > waitsec) break;
                    if (timebuffer.time == waitsec && timebuffer.millitm >= millisec) break;
#endif
                    if (merr () == INRPT) goto err;
                    
                }
            }
            break;


        case HALT:          /* HALT */

            if (*codptr == SP || *codptr == EOL) goto halt;
            
            merr_raise (ARGLIST);
            break;


        case BREAK:

            
            if (*codptr == SP || *codptr == EOL) {
                
                if (breakon == FALSE) break;      /* ignore BREAK */
                
                if (usermode == 0) {
                    merr_raise (BKERR);
                    goto err;
                }
                
                zbflag = TRUE;
                merr_raise (OK - CTRLB);
                zb_entry:loadsw = TRUE;
                
#ifdef DEBUG_NEWSTACK
                printf ("CHECK 08 (Stack PUSH)\r\n");
#endif
                


                if (++nstx > NESTLEVLS) {
                    nstx--;
                    merr_raise (STKOV);
                
                    goto err;
                }
                else {
                    estack++;
                }

                nestc[nstx] = BREAK;

#ifdef DEBUG_NEWSTACK

                if (!cmdptr) printf ("CMDPTR is ZERO!\r\n");

#endif

                nestp[nstx] = cmdptr;   /* command stack address */
                nestn[nstx] = 0;    /*!!! save name */
                nestr[nstx] = roucur - rouptr;  /* save roucur */
                nestnew[nstx] = 0;
                ztrap[nstx][0] = EOL;
                nestlt[nstx] = level;
                level = 0;      /* save level */
                /* save BREAK information   */
                brkstk[nstx] = (((ECHOON ? 1 : 0) << 1) | test) << 3 | io;

                io = HOME;
                forsw = FALSE;
                cmdptr += stcpy (cmdptr, codptr) + 1;
                zerr = BKERR;
                goto restart;
            }

            if (is_standard ()) {
                merr_raise (NOSTAND);
                goto err;
            }
            
            expr (STRING);
            if (merr () > OK) break;

            switch (intexpr (argptr)) {
                
                case 2:
                    DSM2err = TRUE;
                    break;      /* enable DSM V 2 error processing */
                
                case -2:
                    DSM2err = FALSE;
                    break;      /* enable normal error processing  */
                
                case 0:
                    breakon = FALSE;
                    break;      /* disable CTRL/C */
                
                default:
                    breakon = TRUE;
                    break;      /* enable CTRL/C  */
            }
            break;

        case VIEW:

            view_com ();

            if (repQUIT) {           /* VIEW 26: repeated QUIT action */
                
                while (repQUIT-- > 0) {

#ifdef DEBUG_NEWSTACK
                    printf ("CHECK 09 (Stack POP)\r\n");
#endif

                    if (nestc[nstx] == BREAK) {
//                        printf ("nestc[nstx] was BREAK\r\n");
                        if (repQUIT) continue;
                        merr_raise (OK - CTRLB);
                        
                        goto zgo;   /*cont. single step */
                    }
//                    else {
//                        printf ("nestc[nstx] was _not_ BREAK\r\n");
//                    }

                    if (nestc[nstx] == FOR) {

                        stcpy (code, cmdptr = nestp[nstx--]);
                        estack--;
                        
                        codptr = code;
                        ftyp = fortyp[--forx];
                        fvar = forvar[forx];
                        finc = forinc[forx];
                        flim = forlim[forx];
                        fi = fori[forx];
                        
                        if (repQUIT) continue;
                        if ((forsw = (nestc[nstx] == FOR))) goto for_end;

                        goto next_line;
                    }

                    if (nestn[nstx]) {       /* reload routine */
                        namptr = nestn[nstx];
                        
                        if ((nestc[nstx] != XECUTE) || loadsw) {
                            stcpy (rou_name, namptr);
                            zload (rou_name);

                            ssvn_job_update ();
                            
                            dosave[0] = 0;
                        }

                        namptr--;
                    }

                    if (nestnew[nstx]) unnew ();   /* un-NEW variables */
                    
                    /* restore old pointers */
                    if ((mcmnd = nestc[nstx]) == BREAK) {
                        if (repQUIT) continue;
                        
                        goto restore;
                    }       /*cont. single step */
                    
                    if (mcmnd == DO_BLOCK) {
                        test = nestlt[nstx];
                        level--;
                    }                
                    else { /* pop $TEST */
                        level = nestlt[nstx];   /* pop level */
                    }

                    roucur = nestr[nstx] + rouptr;
                    stcpy (codptr = code, cmdptr = nestp[nstx--]);
                    estack--;
                    forsw = (nestc[nstx] == FOR);


                    loadsw = TRUE;

                    if (mcmnd == '$') {
                        if (repQUIT) return 0;
                        merr_raise (NOVAL);
                    }
                }
                repQUIT = 0;
            }
            break;

        /* Z-COMMANDS */
        case ZGO:

            /* ZGO with arguments: same as GOTO but with BREAK on */
            if (*codptr != EOL && *codptr != SP) {
                mcmnd = GOTO;
                zbflag = TRUE;
                merr_raise (OK - CTRLB);
                
                goto do_goto;
            }

            /* argumentless ZGO resume execution after BREAK */

            if (nestc[nstx] != BREAK) {
                merr_raise (LVLERR);
                break;
            }



            merr_clear ();      /* stop BREAKing */

zgo:

#ifdef DEBUG_NEWSTACK
            printf ("Zgoing: (Stack POP)\r\n");
#endif



            if (nestn[nstx]) {           /* reload routine */
                stcpy (rou_name, (namptr = nestn[nstx]));
                zload (rou_name);

                ssvn_job_update ();

                if (merr () > OK) break;
            }

            level = nestlt[nstx];
            roucur = nestr[nstx] + rouptr;
            io = brkstk[nstx];
            
            if (io & 020) {
                DSW &= ~BIT0;
            }
            else {
                DSW |= BIT0;        /* restore echo state */
            }

            test = (io & 010) >> 3; /* restore $TEST */

            /* restore $IO; default to HOME if channel not OPEN */
            if ((io &= 07) != HOME && devopen[io] == 0) io = HOME;
            
            stcpy (codptr = code, cmdptr = nestp[nstx--]);
            estack--;
            
            forsw = (nestc[nstx] == FOR);


            loadsw = TRUE;
            zbflag = FALSE;
            
            goto next0;


        case ZBREAK:

            if (*codptr == SP || *codptr == EOL) {
                merr_raise (ARGLIST);
                break;
            }

            expr (STRING);
            if (merr () > OK) break;

            zbreakon = tvexpr (argptr);
            if (hardcopy == DISABLE) set_zbreak (zbreakon ? STX : -1);   /* enable/disable CTRL/B */

            zbflag = FALSE;
            break;



    
        case ZLOAD:

            if (*codptr == EOL || *codptr == SP) {
                stcpy (varnam, rou_name);
            }
            else {
                expr (NAME);
            
                if (merr () > OK) break;
            
                codptr++;
            }

            dosave[0] = EOL;

            if (varnam[0] == EOL) {
                varerr[0] = EOL;
                merr_raise (NOPGM);
                break;
            }           /*error */

            loadsw = TRUE;

            /* a ZLOAD on the active routine always loads from disk */
            if (stcmp (varnam, rou_name) == 0) {                
                for (i = 0; i < NO_OF_RBUF; i++) {
            
                    if (rouptr == (buff + (i * PSIZE0))) {
                        pgms[i][0] = EOL;
            
                        break;
                    }
                }
            }

            zload (varnam);

            if (merr () > OK) break;          /* load file */

            stcpy (rou_name, varnam);
            ssvn_job_update ();

            break;

        case ZSAVE:

            if (*codptr == EOL || *codptr == SP) {

                if (rou_name[0] == EOL) {
                    varerr[0] = EOL;
                    merr_raise (NOPGM);

                    break;
                }           /*error */

                stcpy (varnam, rou_name);
            }
            else {
                expr (NAME);

                if (varnam[0] == '^') merr_raise (GLOBER);
                if (varnam[0] == '$') merr_raise (INVREF);
                if (merr () > OK) break;
                
                stcpy (rou_name, varnam);
                ssvn_job_update ();

                codptr++;
            }

            zsave (varnam);
            break;


        case ZREMOVE:

            {
                char *beg, *end;

                dosave[0] = EOL;

                if (*codptr == SP || *codptr == EOL) {           /* no args is ZREMOVE  all */
                    loadsw = TRUE;

                    for (i = 0; i < NO_OF_RBUF; i++) {

                        if (rouptr == buff + (i * PSIZE0)) {
                            pgms[i][0] = EOL;
                            break;
                        }

                    }

                    rouptr = buff + (i * PSIZE0);
                    rouend = rouins = rouptr;
                    roucur = buff + (NO_OF_RBUF * PSIZE0 + 1);
                    
                    *(rouptr) = EOL;
                    *(rouptr + 1) = EOL;
                    *(rouptr + 2) = EOL;
                    
                    argptr = partition;
                    rou_name[0] = EOL;

                    ssvn_job_update ();
                    
                    break;
                }
                if (*codptr == ':') {
                    beg = rouptr;
                }
                else if (*codptr == '*') {
                    beg = rouptr;
                
                    while ((end = (beg + UNSIGN (*beg) + 2)) < rouins) beg = end;
                
                    codptr++;
                }
                else {
                    lineref (&beg);
                    if (merr () > OK) break;
                }

                if ((end = beg) == 0) {
                    merr_raise (M13);
                    break;
                }

                if (*codptr == ':') {           /* same as above */
                    codptr++;
                
                    if (*codptr == '*') {
                        end = rouins;
                        codptr++;
                    }
                    else if (*codptr == ',' || *codptr == SP || *codptr == EOL) {
                        end = rouend;
                    }
                    else {
                        lineref (&end);
                        
                        if (end == 0) merr_raise (M13);
                        if (merr () > OK) break;
                
                        end = end + UNSIGN (*end) + 2;
                    }
                }
                else {
                    end = end + UNSIGN (*end) + 2;
                }

                if (beg < rouend) {           /* else there's nothing to zremove */

                    if (end >= rouend) {
                        end = rouend = beg;
                    }
                    else {
                        rouins = beg;

                        while (end <= rouend) *beg++ = (*end++);
                        
                        i = beg - end;
                        rouend += i;
                        
                        if (roucur > end) roucur += i;
                    }
                    
                    *end = EOL;
                    *(end + 1) = EOL;
                    
                    for (i = 0; i < NO_OF_RBUF; i++) {
                        if (rouptr == (buff + (i * PSIZE0))) {
                            ends[i] = rouend;
                            break;
                        }
                    }

                }
                break;
            }

        case ZINSERT:

            {
                char *beg;

                if (*codptr == EOL || *codptr == SP) {
                    merr_raise (ARGLIST);
                    break;
                }           /*error */
                
                dosave[0] = EOL;

                /* parse stringlit */
                expr (STRING);
                
                if (merr () > OK) break;
                
                if (*codptr != ':') {
                    zi (argptr, rouins);
                    break;
                }

                stcpy (tmp, argptr);
                codptr++;
                lineref (&beg);
                
                if (merr () > OK) break;      /* parse label */
                
                if (beg) {
                    beg = beg + UNSIGN (*beg) + 2;
                }
                else {
                    beg = rouptr;
                }
                
                if (beg > rouend + 1) {
                    merr_raise (M13);
                    break;
                }

                /* insert stuff */
                zi (tmp, beg);
                break;
            }


        /* PRINT is convenient -
        * but non-standard ZPRINT should be used instead */
        case 'p':

            if (is_standard ()) {
                merr_raise (NOSTAND);
                break;
            }


        case ZPRINT:
            
            {
                char *beg, *end;

                if (*codptr == SP || *codptr == EOL) {           /* no args is ZPRINT all */
                    beg = rouptr;
                    end = rouend;
                }
                else {
                    if (*codptr == ':') {
                        beg = rouptr;   /* from begin */
                    }
                    else if (*codptr == '*') {           /* from 'linepointer' */
                        beg = rouptr;
                        
                        while ((end = (beg + UNSIGN (*beg) + 2)) < rouins) beg = end;
                        codptr++;
                    }
                    else {
                        lineref (&beg);                        
                        if (merr () > OK) break;
                    }           /* line reference */
                    
                    if (beg == 0) {
                        beg = rouptr;
                        rouins = beg;
                        
                        if (*codptr != ':') break;
                    }

                    if (*codptr == ':') {
                        codptr++;   /* to end */
                    
                        if (*codptr == SP || *codptr == ',' || *codptr == EOL)
                            end = rouend;
                        else {
                            if (*codptr == '*') {
                                end = rouins;
                                codptr++;
                            }               
                            else {  /* to 'linepointer' */
                                lineref (&end);
                    
                                if (merr () > OK) break;  /* line reference */
                                end = end + UNSIGN (*end) + 2;
                            }
                        }
                    }
                    else {
                        end = beg + 1;
                    }
                }
                if (rouend < end) end = rouend - 1;

                for (; beg < end; beg += UNSIGN (*beg) + 2) {
                    
                    if (frm_crlf[io]) {
                        write_m ("\012\201");
                    }
                    else {
                        write_m ("\012\015\201");
                    }
                    
                    if ((*(beg + 1)) == EOL) break;
                    
                    write_m (beg + 1);
                    if (merr () > OK) break;
                }
                
                rouins = beg;
            }

            if (frm_crlf[io]) {
                write_m ("\012\201");
            }
            else {
                write_m ("\012\015\201");
            }

            break;

        case WATCH:
            {
                char op;


                if (((ch = *codptr) == SP) || ch == EOL) {
                    
                    set_io(UNIX);                        
                    
                    if (dbg_enable_watch) {
                        printf ("Watchpoints disabled.\n"); 
                        dbg_enable_watch = 0;
                    }
                    else {
                        printf ("Watchpoints enabled.\n");
                        dbg_enable_watch = 1;
                    }
                    
                    break;        

                }

                if ((ch = *codptr) == '(') {
                    merr_raise (ARGLIST);
                    goto err;
                }

                for (;;) {

                    switch (ch) {
                        
                        case '?':
                        case '+':
                        case '-':
                            op = ch;
                            codptr++;
                            break;

                        default: 
                            merr_raise (ARGLIST);
                            goto err;
                    }

                    expr (NAME);                            /* try to interpret an mname */
                    
                    if (merr () > OK) goto err;

                    stcpy (vn, varnam);

                    switch (op) {
                        
                        case '+':
                            dbg_add_watch (vn);
                            break;

                        case '-':
                            dbg_remove_watch (vn);
                            break;

                        case '?':
                            dbg_dump_watch (vn);
                            break;

                    }                

                    if (merr () > OK) goto err;

                    if ((ch = *(codptr + 1)) == EOL) {
                        codptr++;
                        break;
                    }
                    else if ((ch = *(codptr + 1)) == ',') {
                        codptr += 2;
                        ch = *codptr;
                    }
                    else {
                        merr_raise (ARGLIST);
                        goto err;
                    }
                } 
                

                break;
            }


        case ASSERT_TKN:
            {
                expr (STRING);

                if (merr () > OK) goto err;

                if (tvexpr (argptr) == 0) {
                    merr_raise (ASSERT);
                    goto err;
                }

                break;
            }

        case ZWRITE:


zwrite:
            {
                short k;
                char w_tmp[512];
                char zwmode;


                if (io != HOME && devopen[io] == 'r') {
                    merr_raise (NOWRITE);
                    goto err;
                }

                tmp3[0] = SP;
                tmp3[1] = EOL;
                
                if ((ch = (*codptr)) == '(') {    /* exclusive zwrite */

                    for (;;) {
                        
                        codptr++;
                        expr (NAME);
                        
                        if (merr () > OK) goto err;
                        if (varnam[0] == '^') {
                            merr_raise (GLOBER);
                            goto err;
                        }

                        i = 0;

                        while (varnam[i] != EOL) {
                            
                            if (varnam[i] == DELIM) {
                                merr_raise (SBSCR);
                                goto err;
                            }

                            i++;
                        }

                        if (stcat (tmp3, varnam) == 0) {
                            merr_raise (M75);
                            goto err;
                        }

                        if (stcat (tmp3, " \201") == 0) {
                            merr_raise (M75);
                            goto err;
                        }

                        if ((ch = *++codptr) == ')') {
                            codptr++;
                            break;
                        }

                        if (ch != ',') {
                            merr_raise (COMMAER);
                            goto err;
                        }
                    }
                }
                else {
                    if (ch != SP && ch != EOL) goto zwritep;
                }

                /* no arguments: write local symbol table. */
                stcpy (tmp, " $\201");

                for (;;) {
                    ordercnt = 1L;
                    
                    symtab (bigquery, &tmp[1], tmp2);
                    
                    if (*tmp2 == EOL || merr () == INRPT) break;
                    w_tmp[0] = '=';

                    /* subscripts: internal format different from external one */
                    k = 0;
                    i = 1;
                    j = 0;
                    
                    while ((ch = tmp2[k++]) != EOL) {
                        
                        if (ch == '"') {
                            
                            if (j && tmp2[k] == ch) {
                                k++;
                            }
                            else {
                                toggle (j);
                                continue;
                            }

                        }
                        
                        if (j == 0) {
                    
                            if (ch == '(' || ch == ',') {
                                tmp[i++] = DELIM;
                                
                                continue;
                            }
                    
                            if (ch == ')') break;
                        }
                    
                        tmp[i++] = ch;
                    }
                    
                    tmp[i] = EOL;
                    if (kill_ok (tmp3, tmp) == 0) continue;

                    write_m (tmp2);
                    symtab (get_sym, &tmp[1], &w_tmp[1]);
                    write_m (w_tmp);
                    write_m ("\012\015\201");
                }
                
                break;

zwritep:

                expr (NAME);

                //if (varnam[0] == '^') merr_raise (GLOBER);
                if (merr () > OK) goto err;
                
                codptr++;

                if (varnam[0] == '$') {
                
                    if ((varnam[1] | 0140) == 'z' && (varnam[2] | 0140) == 'f') {
                        w_tmp[0] = '$';
                        w_tmp[1] = 'Z';
                        w_tmp[2] = 'F';
                        w_tmp[3] = '(';
                
                        for (i = 0; i < 44; i++) {

                            if (zfunkey[i][0] != EOL) {
                                intstr (&w_tmp[4], i + 1);
                                stcat (w_tmp, ")=\201");
                                write_m (w_tmp);
                                write_m (zfunkey[i]);
                                write_m ("\012\015\201");
                            }

                        }

                        break;
                    }
                    else {
                        break;      /* do not zwrite special variables etc. other than $ZF */
                    }
                }
                
                if (varnam[0] != '^') {
                    symtab (fra_dat, varnam, tmp2);
                    zwmode = 'L';
                }
                else {
                    if (varnam[1] == '$') {
                        ssvn (fra_dat, varnam, tmp2);
                        zwmode = '$';
                    }
                    else {
                        global (fra_dat, varnam, tmp2);
                        zwmode = '^';
                    }
                }

                if (tmp2[0] == '0') break;      /* variable not defined */
                
                /* if $D(@varnam)=10 get next entry */
                if (tmp2[1] == '0') {
                    ordercnt = 1L;

                    if (varnam[0] != '^') {
                        symtab (fra_query, varnam, tmp2);
                        zwmode = 'L';
                    }
                    else {
                        if (varnam[1] == '$') {
                            ssvn (fra_query, varnam, tmp2);
                            zwmode = '$';
                        }
                        else {
                            global (fra_query, varnam, tmp2);
                            zwmode = '^';
                        }
                    }
                }
                else {
                    k = 0;
                    i = 0;
                    j = 0;
                
                    while ((ch = varnam[k++]) != EOL) {
                        
                        if (ch == DELIM) {
                            
                            if (j) {
                                tmp2[i++] = '"';
                                tmp2[i++] = ',';
                                tmp2[i++] = '"';

                                continue;
                            }

                            j++;
                
                            tmp2[i++] = '(';
                            tmp2[i++] = '"';
                
                            continue;
                        }
                
                        if ((tmp2[i++] = ch) == '"')
                        tmp2[i++] = ch;
                    }
                
                    if (j) {
                        tmp[i++] = '"';
                        tmp2[i++] = ')';
                    }
                
                    tmp2[i] = EOL;
                }
                
                for (;;) {           /* subscripts: internal format different from external one */
                    k = 0;
                    i = 0;
                    j = 0;

                    while ((ch = tmp2[k++]) != EOL) {

                        if (ch == '"') {
                            if (j && tmp2[k] == ch)
                                k++;
                            else {
                                toggle (j);
                                continue;
                            }
                        }
                        
                        if (j == 0) {
                            
                            if (ch == '(' || ch == ',') {
                                tmp[i++] = DELIM;
                        
                                continue;
                            }
                        
                            if (ch == ')') break;
                        }

                        tmp[i++] = ch;
                    }

                    tmp[i] = EOL;
                    i = 0;
                    
                    while (tmp[i] == varnam[i]) {

                        if (varnam[i] == EOL) break;
                    
                        i++;
                    }

                    if (varnam[i] != EOL) break;
                    if (tmp[i] != EOL && tmp[i] != DELIM) break;
                    
                    tmp3[0] = EOL;

                    switch (zwmode) {

                        case 'L':
                            symtab (fra_dat, tmp, tmp3);
                            symtab (get_sym, tmp, &w_tmp[1]);

                            break;


                        case '$':
                            ssvn (fra_dat, tmp, tmp3);
                            ssvn (get_sym, tmp, &w_tmp[1]);

                            break;


                        case '^':
                            global (fra_dat, tmp, tmp3);
                            global (get_sym, tmp, &w_tmp[1]);

                            break;
                    }

                    if (tmp3[0] != '0' && tmp3[1] != '0') {                        
                        
                        write_m (tmp2);
                        
                        w_tmp[0] = '=';
                        
                        write_m (w_tmp);
                        write_m ("\012\015\201");

                    }
                    
                    ordercnt = 1L;
                    
                    switch (zwmode) {

                        case 'L':
                            symtab (fra_query, tmp, tmp2);

                            break;


                        case '$':
                            ssvn (fra_query, tmp, tmp2);

                            break;


                        case '^':
                            global (fra_query, tmp, tmp2);

                            break;

                    }
                    
                    if (merr () == INRPT) break;
                }

                break;
            }


        case ZTRAP:

            if (*codptr == SP || *codptr == EOL) {
                merr_raise (ZTERR);
                varnam[0] = EOL;
                
                break;
            }

            expr (NAME);
            stcpy (varerr, varnam);

            if (merr ()) break;

            if (*++codptr == ':') {           /* parse postcond */
                codptr++;

                expr (STRING);

                if (merr () > OK) goto err;

                if (tvexpr (argptr) == FALSE) break;
            }

            merr_raise (ZTERR);
            break;


        case ZALLOCATE:

            /* argumentless is not permitted */
            if (*codptr == SP || *codptr == EOL) {
                merr_raise (ARGLIST);
                break;
            }

            expr (NAME);
            
            if (merr () > OK) goto err;
            
            tmp[0] = SP;
            stcpy (&tmp[1], varnam);
            stcat (tmp, "\001\201");

            frm_timeout = (-1L);        /* no timeout */
            
            if (*++codptr == ':') {
                codptr++;
            
                expr (STRING);
            
                frm_timeout = intexpr (argptr);
            
                if (merr () > OK) goto err;
                if (frm_timeout < 0L) frm_timeout = 0L;
            }

            lock (tmp, frm_timeout, ZALLOCATE);
            break;
            

        case ZDEALLOCATE:

            tmp[0] = SP;
            
            if (*codptr == SP || *codptr == EOL) {
                tmp[1] = EOL;
            }
            else {
                expr (NAME);
            
                if (merr () > OK) goto err;
            
                stcpy (&tmp[1], varnam);
            
                codptr++;
            }

            lock (tmp, -1L, ZDEALLOCATE);   /* -1: no timeout */
            break;

            /* user defined Z-COMMAND */


        case PRIVATE:

private:            /* for in-MUMPS defined commands */
            i = 0;
            j = 0;
            ch = 0;

            while ((tmp2[i] = *codptr) != EOL) {
                
                if (tmp2[i] == SP && !j) {
                    tmp2[i] = EOL;
                    break;
                }

                if (tmp2[i] == '"') j = (!j);
                
                if (!j) {
                    
                    if (tmp2[i] == '(') ch++;
                    if (tmp2[i] == ')') ch--;
                
                    if (!ch && tmp2[i] == ',') {       /* next argument: */
                
                        tmp2[i] = EOL;  /* call afterwards again */
                        i = 0;
                
                        while (tmp3[i] != EOL) i++;

                        j = i;
                        ch = 1;
                
                        while (ch < i) tmp3[j++] = tmp3[ch++];
                
                        tmp3[j - 1] = SP;
                        tmp3[j] = EOL;
                
                        codptr++;
                
                        j = 0;
                        ch = 0;
                
                        break;
                    }
                }
                
                i++;
                codptr++;            
            }

            if (j || ch) {
                merr_raise (INVREF);
                goto err;
            }

            stcat (tmp3, codptr);

            if (destructor_run) {
                stcpy (code, "d \201");
                destructor_run = FALSE;
            }
            else {
                if (new_object) {
                    stcpy (code, "d ^\201");
                    new_object = FALSE;
                }
                else {
                    stcpy (code, "d ^%\201");
                }
            }

            stcat (code, &tmp3[1]);

            codptr = code;
            privflag = TRUE;

            goto next_cmnd;

evthandler:            /* for event handlers */
            i = 0;
            j = 0;
            ch = 0;

            while ((tmp2[i] = *codptr) != EOL) {
                
                if (tmp2[i] == SP && !j) {
                    tmp2[i] = EOL;
                    break;
                }

                if (tmp2[i] == '"') j = (!j);
                
                if (!j) {
                    
                    if (tmp2[i] == '(') ch++;
                    if (tmp2[i] == ')') ch--;
                
                    if (!ch && tmp2[i] == ',') {       /* next argument: */
                
                        tmp2[i] = EOL;  /* call afterwards again */
                        i = 0;
                
                        while (tmp3[i] != EOL) i++;

                        j = i;
                        ch = 1;
                
                        while (ch < i) tmp3[j++] = tmp3[ch++];
                
                        tmp3[j - 1] = SP;
                        tmp3[j] = EOL;
                
                        codptr++;
                
                        j = 0;
                        ch = 0;
                
                        break;
                    }
                }
                
                i++;
                codptr++;            
            }

            if (j || ch) {
                merr_raise (INVREF);
                goto err;
            }

            stcpy (code, "d \201");
            stcat (code, tmp3);

            codptr = code;
            privflag = TRUE;

            goto next_cmnd;            

        case ABLOCK:
        case AUNBLOCK:
            {
                short evt_mask[EVT_MAX];
                
                if ((rtn_dialect () != D_MDS) &&
                    (rtn_dialect () != D_FREEM)) {
                    merr_raise (NOSTAND);
                    goto err;
                }

                /* declare and initialize table of events to be blocked/unblocked with this command */

                
                for (i = 0; i < EVT_MAX; i++) evt_mask[i] = 0;


                /* argumentless ABLOCK/AUNBLOCK: block/unblock everything */
                if (((ch = *codptr) == SP) || ch == EOL) {
                    
                    for (i = 0; i < EVT_MAX; i++) evt_mask[i] = 1;

                }
                else if (*codptr == '(') {
                    /* exclusive ABLOCK/AUNBLOCK */

                    short evt_exclusions[EVT_MAX];
                    
                    codptr++;


                    for (i = 0; i < EVT_MAX; i++) evt_exclusions[i] = FALSE;

                    for (;;) {

                        expr (STRING);

                        if (merr () == BRAER) merr_clear ();
                        if (merr () > OK) goto err;

                        codptr++;

                        stcpy (vn, argptr);

                        if (stcmp (vn, "COMM\201") == 0) {
                            evt_exclusions[EVT_CLS_COMM] = TRUE;
                        }
                        else if (stcmp (vn, "HALT\201") == 0) {
                            evt_exclusions[EVT_CLS_HALT] = TRUE;
                        }
                        else if (stcmp (vn, "IPC\201") == 0) {
                            evt_exclusions[EVT_CLS_IPC] = TRUE;
                        }
                        else if (stcmp (vn, "INTERRUPT\201") == 0) {
                            evt_exclusions[EVT_CLS_INTERRUPT] = TRUE;
                        }
                        else if (stcmp (vn, "POWER\201") == 0) {
                            evt_exclusions[EVT_CLS_POWER] = TRUE;
                        }
                        else if (stcmp (vn, "TIMER\201") == 0) {
                            evt_exclusions[EVT_CLS_TIMER] = TRUE;
                        }
                        else if (stcmp (vn, "USER\201") == 0) {
                            evt_exclusions[EVT_CLS_USER] = TRUE;
                        }
                        else if (stcmp (vn, "WAPI\201") == 0) {
                            evt_exclusions[EVT_CLS_WAPI] = TRUE;
                        }
                        else {
                            merr_raise (CMMND);
                            goto err;
                        }

                        if ((ch = *(codptr + 1)) == EOL || ch == SP) {
                            codptr++;
                            break;
                        }                       
                        if ((ch = *(codptr + 1)) == ')') {
                            codptr++;
                            break;
                        }

                    }
                
                    for (i = 0; i < EVT_MAX; i++) {

                        if (evt_exclusions[i] == FALSE) evt_mask[i] = 1;

                    }

                }
                else {
                    /* inclusive ABLOCK/AUNBLOCK */

                    for (;;) {

                        expr (STRING);                            /* try to interpret a string */                        
                        if (merr () > OK) goto err;

                        codptr++;

                        stcpy (vn, argptr);

                        if (stcmp (vn, "COMM\201") == 0) {
                            evt_mask[EVT_CLS_COMM] = 1;
                        }
                        else if (stcmp (vn, "HALT\201") == 0) {
                            evt_mask[EVT_CLS_HALT] = 1;
                        }
                        else if (stcmp (vn, "IPC\201") == 0) {
                            evt_mask[EVT_CLS_IPC] = 1;
                        }
                        else if (stcmp (vn, "INTERRUPT\201") == 0) {
                            evt_mask[EVT_CLS_INTERRUPT] = 1;
                        }
                        else if (stcmp (vn, "POWER\201") == 0) {
                            evt_mask[EVT_CLS_POWER] = 1;
                        }
                        else if (stcmp (vn, "TIMER\201") == 0) {
                            evt_mask[EVT_CLS_TIMER] = 1;
                        }
                        else if (stcmp (vn, "TRIGGER\201") == 0) {
                            evt_mask[EVT_CLS_TRIGGER] = 1;
                        }
                        else if (stcmp (vn, "USER\201") == 0) {
                            evt_mask[EVT_CLS_USER] = 1;
                        }
                        else if (stcmp (vn, "WAPI\201") == 0) {
                            evt_mask[EVT_CLS_WAPI] = 1;
                        }
                        else {
                            merr_raise (CMMND);
                            goto err;
                        }
                    
                        if (merr () > OK) goto err;


                        if ((ch = *(codptr)) == EOL || ch == SP) {                            
                            break;
                        }

                    } 

                }

                for (i = 0; i < EVT_MAX; i++) {                    

                    if (evt_mask[i] > 0) {

                        if (mcmnd == ABLOCK) {
                            evt_ablock (i);
                        }
                        else {
                            evt_aunblock (i);
                        }
                    }

                }
            
                
                break;
            }


        case ASSIGN:
            merr_raise (CMMND);
            break;


        case ASTOP:
        case ASTART:
            {
                short evt_mask[EVT_MAX];
                short new_status;
                
                if ((rtn_dialect () != D_MDS) &&
                    (rtn_dialect () != D_FREEM)) {
                    merr_raise (NOSTAND);
                    goto err;
                }
                
                /* declare and initialize table of events to be enabled with this command */

                if (mcmnd == ASTART) {
                    new_status = EVT_S_ASYNC;
                }
                else {
                    new_status = EVT_S_DISABLED;
                }


                for (i = 0; i < EVT_MAX; i++) evt_mask[i] = EVT_S_NOMODIFY;


                /* argumentless ASTART/ASTOP: enable/disable everything */
                if (((ch = *codptr) == SP) || ch == EOL) {
                    
                    for (i = 0; i < EVT_MAX; i++) evt_mask[i] = new_status;

                }
                else if (*codptr == '(') {
                    /* exclusive ASTART */
                    
                    short evt_exclusions[EVT_MAX];

                    codptr++;

                    for (i = 0; i < EVT_MAX; i++) evt_exclusions[i] = FALSE;

                    for (;;) {

                        expr (STRING);

                        if (merr () == BRAER) merr_clear ();
                        if (merr () > OK) goto err;

                        codptr++;

                        stcpy (vn, argptr);

                        if (stcmp (vn, "COMM\201") == 0) {
                            evt_exclusions[EVT_CLS_COMM] = TRUE;
                        }
                        else if (stcmp (vn, "HALT\201") == 0) {
                            evt_exclusions[EVT_CLS_HALT] = TRUE;
                        }
                        else if (stcmp (vn, "IPC\201") == 0) {
                            evt_exclusions[EVT_CLS_IPC] = TRUE;
                        }
                        else if (stcmp (vn, "INTERRUPT\201") == 0) {
                            evt_exclusions[EVT_CLS_INTERRUPT] = TRUE;
                        }
                        else if (stcmp (vn, "POWER\201") == 0) {
                            evt_exclusions[EVT_CLS_POWER] = TRUE;
                        }
                        else if (stcmp (vn, "TIMER\201") == 0) {
                            evt_exclusions[EVT_CLS_TIMER] = TRUE;
                        }
                        else if (stcmp (vn, "USER\201") == 0) {
                            evt_exclusions[EVT_CLS_USER] = TRUE;
                        }
                        else if (stcmp (vn, "WAPI\201") == 0) {
                            evt_exclusions[EVT_CLS_WAPI] = TRUE;
                        }
                        else if (stcmp (vn, "TRIGGER\201") == 0) {
                            evt_exclusions[EVT_CLS_TRIGGER] = TRUE;
                        }
                        else {
                            merr_raise (CMMND);
                            goto err;
                        }

                        if ((ch = *(codptr + 1)) == EOL || ch == SP) {
                            codptr++;
                            break;
                        }                       
                        if ((ch = *(codptr + 1)) == ')') {
                            codptr++;
                            break;
                        }

                    }
                
                    for (i = 0; i < EVT_MAX; i++) {

                        if (evt_exclusions[i] == FALSE) evt_mask[i] = new_status;

                    }

                }
                else {
                    /* inclusive ASTART */

                    for (;;) {

                        expr (STRING);                            /* try to interpret a string */                        
                        if (merr () > OK) goto err;

                        codptr++;

                        stcpy (vn, argptr);

                        if (stcmp (vn, "COMM\201") == 0) {
                            evt_mask[EVT_CLS_COMM] = new_status;
                        }
                        else if (stcmp (vn, "HALT\201") == 0) {
                            evt_mask[EVT_CLS_HALT] = new_status;
                        }
                        else if (stcmp (vn, "IPC\201") == 0) {
                            evt_mask[EVT_CLS_IPC] = new_status;
                        }
                        else if (stcmp (vn, "INTERRUPT\201") == 0) {
                            evt_mask[EVT_CLS_INTERRUPT] = new_status;
                        }
                        else if (stcmp (vn, "POWER\201") == 0) {
                            evt_mask[EVT_CLS_POWER] = new_status;
                        }
                        else if (stcmp (vn, "TIMER\201") == 0) {
                            evt_mask[EVT_CLS_TIMER] = new_status;
                        }
                        else if (stcmp (vn, "USER\201") == 0) {
                            evt_mask[EVT_CLS_USER] = new_status;
                        }
                        else if (stcmp (vn, "WAPI\201") == 0) {
                            evt_mask[EVT_CLS_WAPI] = new_status;
                        }
                        else if (stcmp (vn, "TRIGGER\201") == 0) {
                            evt_mask[EVT_CLS_TRIGGER] = new_status;
                        }
                        else {
                            merr_raise (CMMND);
                            goto err;
                        }
                    
                        if (merr () > OK) goto err;


                        if ((ch = *(codptr)) == EOL || ch == SP) {                            
                            break;
                        }

                    } 

                }

                for (i = 0; i < EVT_MAX; i++) {                    

                    if (evt_status[i] == EVT_S_SYNC && evt_mask[i] == EVT_S_ASYNC) {
                        
                        /* cannot enable both synchronous and asynchronous 
                           event processing on the same event class at the
                           same time */

                        merr_raise (M102);
                        goto err;

                    }
                    else {

                        if (evt_mask[i] > EVT_S_NOMODIFY) {
                            evt_status[i] = evt_mask[i];
                        }
                        
                    }

                }
            
                if (mcmnd == ASTART)  {
                    evt_async_enabled = TRUE;
                }
                else {                    
                    short disabled_evt_count = 0;

                    for (i = 0; i < EVT_MAX; i++) {
                        if (evt_status[i] == EVT_S_DISABLED) {
                            disabled_evt_count++;
                        }
                    }

                    if (disabled_evt_count == (EVT_MAX - 1)) evt_async_enabled = FALSE;

                }

                break;
            }




        case ETRIGGER:

            merr_raise (CMMND);
            break;
        

#if defined(HAVE_MWAPI_MOTIF)            
        case ESTART:
            if ((rtn_dialect () != D_MDS) &&
                (rtn_dialect () != D_FREEM)) {
                merr_raise (NOSTAND);
                goto err;
            }

            {
                if (in_syn_event_loop == TRUE) break;

                int evt_count;
                char *syn_handlers = (char *) malloc (STRLEN * sizeof (char));
                
                /* stack ^$EVENT */
                char key[100] = "^$EVENT\202\201";
                symtab (new_sym, key, " \201");

                evt_sync_enabled = TRUE;
                in_syn_event_loop = TRUE;
                
                while (evt_sync_enabled) {

                    
                    /* run the next iteration of GTK's event loop */
                    //TODO: replace with libXt event loop
                    //gtk_main_iteration_do (TRUE);

                    /* dequeue any events */
                    evt_count = mwapi_dequeue_events (syn_handlers);

                    if (evt_count) {
                        /* write them out */
                        //printf ("event handlers = '%s'\r\n", syn_handlers);

                        syn_event_entry_nstx = nstx;
                        
                        stcnv_c2m (syn_handlers);
                        stcpy (tmp3, syn_handlers);
                        
                        syn_handlers[0] = '\0';
                        
                        goto evthandler;
                    }

syn_evt_loop_bottom:
                    continue;
                }

                in_syn_event_loop = FALSE;
                evt_sync_enabled = FALSE;

                break;
            }
        
        
        case ESTOP:
            if ((rtn_dialect () != D_MDS) &&
                (rtn_dialect () != D_FREEM)) {
                merr_raise (NOSTAND);
                goto err;
            }

            evt_sync_enabled = FALSE;
            break;
#endif            

            
        default:
            merr_raise (CMMND);
    
    }               /* command switch */

    if ((ch = *codptr) == EOL) {
        if (merr () != OK) goto err;
        if (forsw) goto for_end;        
        
        mcmnd = 0;
        
        goto next_line;
    }

    if (ch == SP) {
        if (merr () == OK) goto next0;

        goto err;
    }

    if (ch != ',' && merr () == OK) { 
        merr_raise (SPACER);
    }
    else if ((ierr <= OK) || (debug_mode == TRUE)) {
        if (debug_mode) goto direct_mode;
        if (*++codptr != SP && *codptr != EOL) goto again;

        merr_raise (ARGLIST);
    }
    
    /* else goto err; */

/* error */
err:

    /* avoid infinite loops resulting from errors in argumentless FOR loops */
    if (merr () != OK && merr () != ASYNC && forsw && ftyp == 0) {
        argless_forsw_quit = TRUE;
        goto for_end;
    }    
    
    /*
     * ierr == ASYNC means that the previous command was interrupted by
     * an async event. It is not a real error, so just go on to the next
     * command after resetting ierr = OK. 
     */
    if (merr () == ASYNC) {
            merr_clear ();
            goto next_cmnd;
    }

    if (merr () > OK) {
        job_set_status (pid, JSTAT_ERROR);
    }
    
    if (ierr < 0) {
        
        ierr += CTRLB;

        if (merr () == OK) {
            zbflag = TRUE;
            
            goto zb_entry;
        }
    }

    if (merr () > OK ) {

        char er_buf[ERRLEN];
        
        merr_set_ecode_ierr ();

        stcpy (er_buf, errmes[merr ()]);
        stcnv_m2c (er_buf);

#if !defined(MSDOS)
        m_log (LOG_ERR, er_buf);
#endif
	
    }

    zerr = ierr;    
    merr_clear ();
    
    /*     goto restart;    */


restart:
    
    if (param) goto restore;

    dosave[0] = EOL;
    setpiece = FALSE;
    setop = 0;
    privflag = FALSE;

    if (merr () == INRPT) goto err;
    if (zerr == STORE) symtab (kill_all, "", "");

    if (errfunlvl > 0) {
        errfunlvl--;
    }
    else {

        if (zerr == OK) {
            zerror[0] = EOL;    /* reset error */
        }
        else {

#ifdef DEBUG_STACK
            printf ("Storing NESTERR\r\n");
#endif

            nesterr = nstx; /* save stack information at error */

            for (i = 1; i <= nstx; i++) getraddress (callerr[i], i);
            
            zerror[0] = '<';

            if (etxtflag) {
                stcpy (&zerror[1], errmes[zerr]);
            }
            else {
                intstr (&zerror[1], zerr);
            }

            stcat (zerror, ">\201");

            if (rou_name[0] != EOL) {
                char *j0;
                char *j1;
                char tmp1[256];


            
                if (nestc[nstx] == XECUTE) {
                    
                    if (nestn[nstx]) {       /* reload routine */
                        zload (nestn[nstx]);
                        merr_clear ();
                    }
                
                    roucur = nestr[nstx] + rouptr;  /* restore roucur */
                }


            
                j0 = (rouptr - 1);
                j = 0;
                tmp1[0] = EOL;
                j0++;
                
                if (roucur < rouend) {
                    
                    while (j0 < (roucur - 1)) {

                        j1 = j0++;
                        j++;

                        if ((*j0 != TAB) && (*j0 != SP)) {
                        
                            j = 0;
                        
                            while ((tmp1[j] = (*(j0++))) > SP) {
                        
                                if (tmp1[j] == '(') tmp1[j] = EOL;
                        
                                j++;
                            }
                        
                            tmp1[j] = EOL;
                            j = 0;
                        }
                        
                        j0 = j1;
                        j0 += (UNSIGN (*j1)) + 2;
                    }
                }

                stcat (zerror, tmp1);

                if (j > 0) {
                    i = stlen (zerror);
                    zerror[i++] = '+';
                    
                    intstr (&zerror[i], j);
                }

                stcat (zerror, "^\201");
            

            
                if (nestc[nstx] == XECUTE) {
                    
                    if (nestn[nstx]) {       /* reload routine */
                        zload (rou_name);

                        ssvn_job_update ();

                        merr_clear ();
                    }
                
                    stcat (zerror, nestn[nstx]);
                }
                else
                    stcat (zerror, rou_name);
            }

            if (zerr == UNDEF) zerr = M6;

            /* undefined: report variable name */
            if (zerr == UNDEF || zerr == SBSCR || zerr == NAKED || zerr == ZTERR || zerr == DBDGD || zerr == LBLUNDEF || zerr == NOPGM || zerr == M6 || zerr == M7 || zerr == M13) { 

                int f;      /* include erroneous reference */

                f = stlen (zerror);
                zerror[f++] = SP;
                zname (&zerror[f], varerr);
            }           /* end varnam section */
        }
    }

    roucur = buff + (NO_OF_RBUF * PSIZE0 + 1);
    tmp4[0] = EOL;

    while (ierr != (OK - CTRLB)) {


        /* standard error handling */
        if (etrap[0] != EOL && stcmp (ecode, "") != 0)  {

            on_frame_entry ();
            
            /* disable $ZTRAP error handling */
            ztrap[nstx][0] = EOL;

            stcpy (tmp4, etrap);
            stcat (tmp4, " quit:$quit \"\" quit\201");

            if (etrap_lvl > 1) {
                /* we've encountered an error within an error handler. 
                   save off the error code at merr_stack[nstx + 1].ECODE */

                stcpy (merr_stack[nstx + 1].ECODE, ecode);
                merr_topstk = nstx + 1;
                etrap_lvl++;

            }
            else {
                merr_topstk = nstx;
                etrap_lvl++;
            }

            break;

        }



        if (ztrap[nstx][0] != EOL && !DSM2err) {           

#ifdef DEBUG_NEWSTACK

            printf ("Dropped into Ztrap [");
            
            for (loop = 0; loop < 20 && ztrap[nstx][loop] != EOL; loop++) {
                printf ("%c", ztrap[nstx][loop]);
            }

            printf ("]\r\n");

#endif

            tmp4[0] = GOTO;
            tmp4[1] = SP;
            stcpy (&tmp4[2], ztrap[nstx]);
            ztrap[nstx][0] = EOL;

#ifdef DEBUG_NEWSTACK

            printf ("Set tmp4 to [");
            for (loop = 0; tmp4[loop] != EOL; loop++) printf ("%c", tmp4[loop]);            
            printf ("]\r\n");

#endif

            break;
        }



        if (nstx == 0) {

#ifdef DEBUG_NEWSTACK
            printf ("Nestx was Zero\r\n");
#endif
        
            forx = 0;
            cmdptr = cmdstack;
            namptr = namstck;
            level = 0;
            errfunlvl = 0;
            io = HOME;      /* trap to direct mode: USE 0 */
            
            if (zerr == INRPT && frm_filter) {
                tmp4[0] = 'h';
                tmp4[1] = EOL;
            }

            if (DSM2err && (ztrap[NESTLEVLS + 1][0] != EOL)) {           /* DSM V.2 error trapping */

#ifdef DEBUG_NEWSTACK
                printf ("Ztrap 2\r\n");
#endif

                tmp4[0] = GOTO;
                tmp4[1] = SP;   /* GOTO errorhandling */
                
                stcpy (&tmp4[2], ztrap[NESTLEVLS + 1]);
                ztrap[NESTLEVLS + 1][0] = EOL;
                
            }

            break;
        }

#ifdef DEBUG_NEWSTACK
        printf ("Nestc[nstx] is [%d]\r\n", nestc[nstx]);
#endif

        if (nestc[nstx] == BREAK) break;

        if (merr () > OK) goto err;
        
        if (nestc[nstx] == FOR) {
            if (forx == 0) goto for_quit;
            ftyp = fortyp[--forx];
            fvar = forvar[forx];
            finc = forinc[forx];
            flim = forlim[forx];
            fi = fori[forx];
        }
        else {

            if (nestc[nstx] == DO_BLOCK) {
                test = nestlt[nstx];
                level--;
            }
            else { /* pop $TEST */
                level = nestlt[nstx];   /* pop level */
            }

#ifdef DEBUG_NEWSTACK
            printf ("Nestn[nstx] is [%d]\r\n", nestn[nstx]);
#endif

            if (nestn[nstx]) {           /* 'reload' routine */
                namptr = nestn[nstx];
                stcpy (rou_name, namptr);
                zload (rou_name);

                ssvn_job_update ();
                
                dosave[0] = 0;
                
                namptr--;
            }

#ifdef DEBUG_NEWSTACK
            printf ("Execcing the rest...\r\n");
#endif

            roucur = nestr[nstx] + rouptr;

            if (nestnew[nstx]) unnew ();       /* un-NEW variables */
            
            cmdptr = nestp[nstx];

            if (nestc[nstx--] == '$') {           /* extrinsic function/variable */
                *argptr = EOL;
                merr_raise (zerr);
                errfunlvl++;
                
                return 0;
            }
            estack--;
        }
    }

    forsw = FALSE;

    /* PRINTING ERROR MESSAGES */
    if (tmp4[0] == EOL) {
        
        if (zerr == BKERR && brkaction[0] != EOL) {
            stcpy (code, brkaction);
            codptr = code;

            if (libcall == TRUE) {
                return zerr;
            } 
            else {
                goto next_cmnd;
            }
        }

        if (libcall == TRUE) return zerr;

        DSW &= ~BIT0;       /* enable ECHO */

        // print here
        {
            char *t_rtn;
            char *t_nsn = (char *) malloc (STRLEN * sizeof (char));
            char *t_cod;
            int t_pos;

	    NULLPTRCHK(t_nsn,"xecline");
	    
            t_rtn = strtok (zerror, ">");
            t_rtn = strtok (NULL, ">");

            if (t_rtn != NULL && t_rtn[1] == '%') {
                strcpy (t_nsn, "SYSTEM");
            }
            else {
                strcpy (t_nsn, nsname);
            }

            if (deferred_ierr > OK) {
                t_cod = deferrable_code;
                t_pos = deferrable_codptr - code + 3;
            }
            else {
                t_cod = code;
                t_pos = codptr - code + 3;
            }

            if (t_rtn != NULL) {
                merr_dump (zerr, t_rtn, t_nsn, t_cod, t_pos);
            }
            else {
                merr_dump (zerr, "<UNKNOWN>", t_nsn, t_cod, t_pos);
            }
            
            
            free (t_nsn);
        }


    }
    else {            
        stcpy (code, tmp4);
        
        codptr = code;
        tmp4[0] = EOL;

        goto next_cmnd;
    }

restore:

    io = HOME;
    codptr = code;

    if (param > 0) {

        j = 0;
        ch = 0;
        paramx++;
        param--;
        
        for (;;) {
            if (m_argv[++j][0] == '-') {
                i = 0;
            
                while ((m_argv[j][++i] != 0) && (m_argv[j][i] != 'x'));
                
                if (m_argv[j][i] != 'x') continue;
            
                j++;
            
                if (++ch < paramx) continue;
            
                strcpy (code, m_argv[j]);
                break;
            }
            else {
                if (++ch < paramx) continue;
            
                strcpy (code, "d ");
                strcpy (&code[2], m_argv[j]);
                break;
            }
        }
        code[strlen (code)] = EOL;
        codptr = code;
        goto next_cmnd;

    }

    if (usermode == 0) {               /* application mode: direct mode implies HALT */
        code[0] = 'H';
        code[1] = EOL;
        codptr = code;

        goto next_cmnd;
    }
    else {
       if (debug_mode) goto direct_mode;
    }

    if (libcall == TRUE) {             /* library mode: don't go to direct mode, just return */
        return merr ();
    }


    do {

        if (frm_filter == FALSE && promflag) {
            stcpy (code, " \201");
            stcpy (&code[2], " \201");                
            promflag = FALSE;
        }
        else {

direct_mode:

            if (dbg_enable_watch && dbg_pending_watches) dbg_dump_watchlist ();

            /* DIRECT-MODE PROMPT HERE */
#if defined(HAVE_LIBREADLINE) && !defined(_AIX)
            {
                char *fmrl_buf;
                char fmrl_prompt[256];
                HIST_ENTRY **hist_list;                
                int hist_idx;
                HIST_ENTRY *hist_ent;

                if (quiet_mode == FALSE) {
                    if (tp_level == 0) {
                        snprintf (fmrl_prompt, 255, "\r\n%s.%s> ", shm_env, nsname);
                    }
                    else {
                        snprintf (fmrl_prompt, 255, "\r\nTL%d:%s.%s> ", tp_level, shm_env, nsname);
                    }
                }
                set_io (UNIX);

                job_set_status (pid, JSTAT_DIRECTMODE);
                
                /* readline() does its own malloc() */
                fmrl_buf = readline (fmrl_prompt);
                
                if (!fmrl_buf) {
                    set_io (UNIX);
                    printf ("\n");
                    set_io (MUMPS);
                    
                    goto halt;
                }
                
                if (strlen (fmrl_buf) > 0) {
                    add_history (fmrl_buf);
                }                    

                if (fmrl_buf[0] == '?') {

                    char kb[20];
                    char db[255];
                    
                    snprintf (kb, 19, "%%SYS.HLP\201");
                    snprintf (db, 19, "\201");

                    symtab (kill_sym, kb, db);
                    
                    /* Invoke Online Help */

                    set_io (MUMPS);
                    stcpy (code, "DO ^%ZHELP\201");
                    
                    if (strlen (fmrl_buf) > 1) {
                        snprintf (db, 254, "%s\201", &fmrl_buf[1]);
                        symtab (set_sym, kb, db);
                    }
                    
                }
                else if (strcmp (fmrl_buf, "step") == 0) {
                    debug_mode = TRUE;
                    goto zgo;
                }
                else if ((strcmp (fmrl_buf, "cont") == 0) || (strcmp (fmrl_buf, "continue") == 0)) {
                    debug_mode = FALSE;
                }
                else if (strcmp (fmrl_buf, "rbuf") == 0) {
                    rbuf_dump ();
                }
                else if (strcmp (fmrl_buf, "jobtab") == 0) {
                    job_dump ();
                }
                else if (strcmp (fmrl_buf, "locktab") == 0) {
                    locktab_dump ();
                    code[0] = '\201';
                    codptr = code;
                }
                else if (strcmp (fmrl_buf, "shmstat") == 0) {
                    shm_dump ();
                }
                else if (strcmp (fmrl_buf, "shmpages") == 0) {
                    shm_dump_pages ();
                }
                else if (strcmp (fmrl_buf, "glstat") == 0) {
                    gbl_dump_stat ();
                }
                else if (strcmp (fmrl_buf, "events") == 0) {

                    char stat_desc[30];
                    char *evclass_name;

                    printf ("\n%-20s %-15s %s\n", "Event Class", "Processing Mode", "ABLOCK Count");
                    printf ("%-20s %-15s %s\n", "-----------", "---------------", "------------");

                    for (i = 0; i < EVT_MAX; i++) {

                        evclass_name = evt_class_name_c (i);

                        switch (evt_status[i]) {
                            case EVT_S_DISABLED:
                                strcpy (stat_desc, "Disabled");
                                break;
                            case EVT_S_ASYNC:
                                strcpy (stat_desc, "Asynchronous");
                                break;
                            case EVT_S_SYNC:
                                strcpy (stat_desc, "Synchronous");
                        }

                        printf ("%-20s %-15s %d\n", evclass_name, stat_desc, evt_blocks[i]);

                    }
                    
                    
                }
                else if (strcmp (fmrl_buf, "wh") == 0) {
                    write_history (history_file);
                }
                else if (strcmp (fmrl_buf, "trantab") == 0) {
                    tp_tdump();
                }
                else if (isdigit(fmrl_buf[0]) || (fmrl_buf[0] == '(') || (fmrl_buf[0] == '-') || (fmrl_buf[0] == '\'') || (fmrl_buf[0] == '+') || (fmrl_buf[0] == '$') || (fmrl_buf[0] == '^')) {

                    snprintf (code, 255, "W %s", fmrl_buf);
                    stcnv_c2m (code);

                    set_io (MUMPS);

                }
#if !defined(__APPLE__)
                else if (strcmp (fmrl_buf, "history") == 0) {

                    /* History List */                                                

                    hist_list = history_list ();
                    if (hist_list) {

                        for (i = 0; hist_list[i]; i++) {
                            printf("%d: %s\n", i + history_base, hist_list[i]->line);
                        }
                        
                    }

                    stcpy (code, " \201");

                    set_io (MUMPS);

                }
#endif                    
                else if (strncmp (fmrl_buf, "rcl", 3) == 0) {

                    /* Recall History Item */
                    
                                            
                    
                    if (!isdigit (fmrl_buf[4])) {
                        fprintf (stderr, "invalid history index '%s'\n", &fmrl_buf[4]);

                        set_io (MUMPS);
                        stcpy (code, " \201");

                        break;
                    }

                    hist_idx = atoi (&fmrl_buf[4]);

                    if ((hist_idx > history_length) || (hist_idx < 1)) {
                        fprintf (stderr, "history entry %d out of range (valid entries are 1-%d)\n", hist_idx, history_length);

                        set_io (MUMPS);
                        stcpy (code, " \201");

                        break;
                    }                        

                    hist_ent = history_get (hist_idx);

                    printf ("%s\n", hist_ent->line);

                    strncpy (code, hist_ent->line, 255);
                    stcnv_c2m (code);

                    set_io (MUMPS);

                }
                else {

                    /* Pass to M Interpreter */

                    set_io (MUMPS);

                    strncpy (code, fmrl_buf, 255);
                    stcnv_c2m (code);

                }

                /* free the buffer malloc()'d by readline() */
                if (fmrl_buf) free (fmrl_buf);                    
            }
#else

            {
                char fmrl_prompt[256];

                if (tp_level == 0) {
                    snprintf (fmrl_prompt, 256, "\r\n%s> \201", nsname);
                }
                else {
                    snprintf (fmrl_prompt, 256, "\r\nTL%d:%s> \201", tp_level, nsname);
                }
                
                write_m (fmrl_prompt);

                read_m (code, -1L, 0, 255); /* Not necessarily STRLEN? */
            }

            promflag = TRUE;
#endif

            if (merr () > OK) goto err;


            //      printf ("zbflag = %d\r\n", zbflag);
            
            if (code[0] == EOL && zbflag && nestc[nstx] == BREAK) {

                //printf ("cont single step\r\n");
                debug_mode = TRUE;
                merr_raise (OK - CTRLB);

                //printf ("ierr now '%d'\r\n", ierr);
                goto zgo;
            }           /* single step */
        }
    } 
    while (code[0] == EOL);

    if (promflag) write_m ("\r\n\201");

    /* automatic ZI in direct mode: insert an entry with TAB */
    i = (-1);
    j = 0;
    merr_clear ();

    while (code[++i] != EOL) {
        if (code[i] == '"') toggle (j);

        if (code[i] == TAB && j == 0) {
            dosave[0] = EOL;

            zi (code, rouins);
            if (merr ()) goto err;
            goto restore;
        }
    }

    code[++i] = EOL;
    code[++i] = EOL;

    roucur = buff + (NO_OF_RBUF * PSIZE0 + 1);

    goto next_cmnd;

skip_line:

    if (forsw) goto for_end;
    goto next_line;

}               /*end of xecline() */

void on_frame_entry(void)
{
    return;
}

void rbuf_dump(void)
{
    register int i;
    char rnam[256];
    char rpth[256];
    char ldtime[80];
    char flgs[80];
    time_t ag;
    struct tm tld;

    
    printf ("ROUTINE BUFFER CONFIGURATION\r\n");
    printf ("    ROUTINE BUFFER COUNT:                 %ld\r\n", NO_OF_RBUF);
    printf ("    MAX. ROUTINE BUFFER COUNT:            %d\r\n", MAXNO_OF_RBUF);
    printf ("    DEFAULT ROUTINE BUFFER SIZE (EACH):   %d BYTES\r\n", DEFPSIZE0 - 1);
    printf ("    CURRENT ROUTINE BUFFER SIZE (EACH):   %ld BYTES\r\n\r\n", PSIZE0 - 1);
    printf ("BUFFERS IN USE:\r\n\r\n");

    
    for (i = 0; i < NO_OF_RBUF; i++) {

        sprintf (flgs, "");
        
        if (ages[i] == 0) {
            sprintf (rnam, "---------");
            sprintf (rpth, "[buffer empty]");
            sprintf (ldtime, "n/a");
            sprintf (flgs, "n/a");
        }
        else {
            stcpy (rnam, pgms[i]);
            stcnv_m2c (rnam);

            stcpy (rpth, path[i]);
            stcnv_m2c (rpth);

            ag = ages[i];
            tld = *localtime (&ag);
            
            strftime (ldtime, 80, "%a %Y-%m-%d %H:%M:%S %Z", &tld);
            if (rbuf_flags[i].dialect != D_FREEM) {
                strcat (flgs, "STANDARD");

                switch (rbuf_flags[i].dialect) {

                    case D_M77:
                        strcat (flgs, " [M 1977]");
                        break;

                    case D_M84:
                        strcat (flgs, " [M 1984]");
                        break;

                    case D_M90:
                        strcat (flgs, " [M 1990]");
                        break;

                    case D_M95:
                        strcat (flgs, " [M 1995]");
                        break;

                    case D_MDS:
                        strcat (flgs, " [MILLENNIUM DRAFT]");
                        break;

                    case D_M5:
                        strcat (flgs, " [M5]");
                        break;
                }
                
            }
            else {
                strcat (flgs, "FREEM");
            }
        }

        if (ages[i] != 0) {
            printf ("#%d [ROUTINE '%s']\r\n", i, rnam);
            printf ("  UNIX PATH:        %s\r\n", rpth);
            printf ("  LAST ACCESS:      %s\r\n", ldtime);
            printf ("  DIALECT:          %s\r\n", flgs);
        }
        
    }
    
}

short rbuf_slot_from_name(char *rnam)
{
    register short i;

    for (i = 0; i < NO_OF_RBUF; i++) {
        if (stcmp (rnam, pgms[i]) == 0) {
            return i;
        }
    }

    return -1;
}

short is_standard(void)
{

    if (rtn_dialect () == D_FREEM) {
        return FALSE;
    }
    else {
        return TRUE;
    }
    
}

int rtn_dialect(void)
{
    short slot;

    slot = rbuf_slot_from_name (rou_name);

    return rbuf_flags[slot].dialect;
}

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>