File:  [Coherent Logic Development] / freem / src / views.c
Revision 1.6: download - view: text, annotated - select for diffs
Sun Mar 9 19:50:47 2025 UTC (3 weeks, 2 days ago) by snw
Branches: MAIN
CVS tags: v0-62-3, v0-62-2, v0-62-1, v0-62-0, HEAD
Second phase of REUSE compliance and header reformat

/*
 *   $Id: views.c,v 1.6 2025/03/09 19:50:47 snw Exp $
 *    implementation of VIEW command and $VIEW intrinsic function
 *
 *  
 *   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: views.c,v $
 *   Revision 1.6  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 "mwapi_window.h"

#define LOCK        'l'
#define ZDEALLOCATE 'D'

/* system services */

#include <signal.h>

#if !defined(__APPLE__) && !defined(__gnu_hurd__) && !defined(EMSCRIPTEN)
# if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__AMIGA)
#  include <termios.h>
#  if !defined(__AMIGA)
#   define TCGETA TIOCGETA
#   define TCSETA TIOCSETA
#  endif
#  define termio termios
# else
#  if !defined(MSDOS)
#    include <termio.h>
#  endif
# endif
#else
# include <termios.h>
#endif


#ifdef __CYGWIN__
#include <errno.h>
#endif /* __CYGWIN__ */
#include <errno.h> /* snw */

#if defined(__NetBSD__) || defined(__OpenBSD__)
#include <sys/ioctl.h>
#endif

#include <fcntl.h>
#include <unistd.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#include "shmmgr.h"

/* 01/18/99 rlf Apparently, tell disappeared with libc-6 */
#if defined(LINUX_GLIBC) || defined(__APPLE__)

long int tell (int fd)
{
    return lseek (fd, 0, SEEK_CUR);
}

#else
long int tell ();
#endif					/* LINUX_GLIBC */


#if defined(MWAPI_GTK)
void destroy(GtkWidget* widget, gpointer data)
{
    gtk_main_quit();
}
#endif


void view_com (void)
{
    /* process VIEW command */

    char tmp[256];
    char tmp2[256];
    int arg1;
    register long int i;
    register long int j;
    register long int ch;

    if (*codptr == SP || *codptr == EOL) {	/* no argument form of VIEW */
        merr_raise (ARGER);
        return;
    }
    
    expr (STRING);
    
    arg1 = intexpr (argptr);
    
    if (merr () > OK) return;
    
    if (*codptr == ':') {
        
        codptr++;
	
        expr (STRING);
	
        if (merr () > OK) return;
	
        switch (arg1) {			
            
            
            /* VIEW 52: G0 input translation table */
            case 52:
                
                stcpy0 (G0I[io], argptr, 256L);
		
                for (i = 0; i < 256; i++) {
                    
                    if (G0I[io][i] == EOL) {
                        
                        while (i < 256) {
                            G0I[io][i] = (char) i;
                            i++;
                        } 
                        
                        break;					
                    }
                    
                }
                
                break;
                
                
                /* VIEW 53: G0 output translation table */
            case 53:
                
                stcpy0 (G0O[io], argptr, 256L);
		
                for (i = 0; i < 256; i++) {
                    
                    if (G0O[io][i] == EOL) {
                        
                        while (i < 256) {
                            G0O[io][i] = (char) i;
                            i++;
                        } 
                        
                        break;
                    }
                    
                }
                
                break;
                
                
                /* VIEW 54: G1 input translation table */
            case 54:
                
                stcpy0 (G1I[io], argptr, 256L);
                
                for (i = 0; i < 256; i++) {
                    
                    if (G1I[io][i] == EOL) {
                        
                        while (i < 256) {
                            G1I[io][i] = (char) i;
                            i++;
                        }
                        
                        break;
                        
                    }
                    
                }
                
                break;
                
                
                /* VIEW 55: G1 output translation table */
            case 55:
                
                stcpy0 (G1O[io], argptr, 256L);
		
                for (i = 0; i < 256; i++) {
                    
                    if (G1O[io][i] == EOL) {
                        
                        while (i < 256) {
                            G1O[io][i] = (char) i;
                            i++;
                        } 
                        
                        break;
                        
                    }
                    
                }
                
                break;
                
                
                /* VIEW 62: random: seed number */
            case 62:
                
                i = intexpr (argptr);
		
                if (merr () == MXNUM) return;
                
                if (i < 0) {
                    merr_raise (ARGER);
                }
                else {
                    nrandom = i;
                }
                
                break;
                
                
                /* VIEW 63: random: parameter a */
            case 63:
                
                i = intexpr (argptr);
                
                if (merr () == MXNUM) return;
                
                if (i <= 0) {
                    merr_raise (ARGER);
                }
                else {
                    ran_a = i;
                }
                
                break;
                
                
                /* VIEW 64: random: parameter b */
            case 64:
                
                i = intexpr (argptr);
		
                if (merr () == MXNUM) return;
                
                if (i < 0) {
                    merr_raise (ARGER);
                }
                else {
                    ran_b = i;
                }
                
                break;
                
                
                /* VIEW 65: random: parameter c */
            case 65:
                
                i = intexpr (argptr);
		
                if (merr () == MXNUM) return;
		
                if (i <= 0) {
                    merr_raise (ARGER);
                }
                else {
                    ran_c = i;
                }
		
                break;
		
                
                /* VIEW 66: SIGTERM handling flag */
            case 66:
                
                killerflag = tvexpr (argptr);
		
                break;
                
                
                /* VIEW 67: SIGHUP handling flag */
            case 67:
                
                huperflag = tvexpr (argptr);
		
                break;
		
                
                /* ... reserved ... */
                
                /* VIEW 70: ZSORT/ZSYNTAX flag */
            case 70:
                
                s_fun_flag = tvexpr (argptr);
		
                break;
		
                
                /* VIEW 71: ZNEXT/ZNAME flag */
            case 71:
                
                n_fun_flag = tvexpr (argptr);
		
                break;
		
                
                /* VIEW 72: ZPREVIOUS/ZPIECE flag */
            case 72:
                
                p_fun_flag = tvexpr (argptr);
		
                break;
		
                
                /* VIEW 73: ZDATA/ZDATE flag */
            case 73:
                
                d_fun_flag = tvexpr (argptr);
		
                break;
                
                
                /* VIEW 79: old ZJOB vs. new ZJOB flag */
            case 79:
                
                zjobflag = tvexpr (argptr);
		
                break;
                
                
                /* VIEW 80: 7 vs. 8 bit flag */
            case 80:
                
                eightbit = tvexpr (argptr);
		
                break;
                
                
                /* VIEW 81: PF1 flag */
            case 81:
                
                PF1flag = tvexpr (argptr);
		
                break;
                
                
                /* VIEW 82: not used */
                /* VIEW 83: text in $ZE flag */
            case 83:
                
                etxtflag = tvexpr (argptr);
		
                break;
		
                
                /* VIEW 84: not used */
                /* VIEW 85: not used */
                /* VIEW 86: not used */
                
            case 87:			/* VIEW 87: date type definition */
                
                i = intexpr (argptr);
		
                if (i < 0 || i >= NO_DATETYPE) {
                    merr_raise (ARGER);
                    return;
                }
                
                if (*codptr != ':') {
                    datetype = i;
                    break;
                }
                
                if (i == 0) {
                    merr_raise (ARGER);
                    return;
                }
                
                codptr++;
		
                expr (STRING);
		
                j = intexpr (argptr);
		
                if (*codptr != ':') {
                    merr_raise (ARGER);
                    return;
                }
                
                codptr++;
		
                expr (STRING);
		
                if (j > 0 && j < 15 && stlen (argptr) > MONTH_LEN) {
                    merr_raise (M75);
                }
                else if (j > 0 && j < 13) {
                    stcpy (month[i][j - 1], argptr);
                }
                else if (j == 13) {
                    stcpy (dat1char[i], argptr);
                }
                else if (j == 14) {
                    stcpy (dat2char[i], argptr);
                }
                else if (j == 15) {
                    dat3char[i] = (*argptr);
                }
                else if (j == 16) {
					
                    if ((j = intexpr (argptr)) < 0 || j > 2) {
                        merr_raise (ARGER);
                        return;
                    }

                    dat4flag[i] = j;

                } 
                else if (j == 17) {
                    dat5flag[i] = tvexpr (argptr);
                }
                else if (j == 18) {
                    if ((j = intexpr (argptr) + 672411L) <= 0L) {
                        merr_raise (ARGER);
                        return;
                    }
                    datGRbeg[i] = j;
                } 
                else {
                    merr_raise (ARGER);
                }

                if (merr () > OK) return;

                break;


            case 88:			/* VIEW 88: time type definition */
				
                i = intexpr (argptr);
				
                if (i < 0 || i >= NO_TIMETYPE) {
                    merr_raise (ARGER);
                    return;
                }
				
                if (*codptr != ':') {
                    timetype = i;
                    break;
                }
				
                codptr++;
				
                expr (STRING);
				
                j = intexpr (argptr);
				
                if (*codptr != ':') {
                    merr_raise (ARGER);
                    return;
                }
				
                codptr++;
				
                expr (STRING);
				
                if (j == 1) {
                    tim1char[i] = (*argptr);
                }
                else if (j == 2) {
                    tim2char[i] = (*argptr);
                }
                else if (j == 3) {
                    tim3char[i] = (*argptr);
                }
                else if (j == 4) {
                    tim4flag[i] = tvexpr (argptr);
                }
                else if (j == 5) {
                    tim5flag[i] = tvexpr (argptr);
                }
                else {
                    merr_raise (ARGER);
                }
				
                if (merr () > OK) return;
				
                break;


            case 91:			/* VIEW 91: missing QUIT expr default expression */
				
                stcpy (exfdefault, argptr);
				
                break;


            case 92:			/* VIEW 92: EUR2DEM: type mismatch error */
				
                typemmflag = tvexpr (argptr);
				
                break;


            case 93:			/* VIEW 93: zkey production rule definition */

                i = intexpr (argptr);
				
                if (i < 1 || i > NO_V93) {
                    merr_raise (ARGER);
                    return;
                }
				
                if (*codptr != ':') {
                    v93 = i;
                    break;
                }
				
                codptr++;
				
                expr (STRING);
				
                stcpy (v93a[i - 1], argptr);
				
                break;


            case 96:			/* VIEW 96: global prefix */
				
                if (stlen (argptr) > MONTH_LEN)  {
                    merr_raise (M75);
                }
                else {
                    stcpy (glo_prefix, argptr);
                }
				
                break;


            case 97:			/* VIEW 97: global postfix */

                if (stlen (argptr) > MONTH_LEN) {
                    merr_raise (M75);
                }
                else {
                    stcpy (glo_ext, argptr);
                }
				
                break;


            case 98:			/* VIEW 98: routine extension */

                if (stlen (argptr) > MONTH_LEN) {
                    merr_raise (M75);
                }
                else {
                    stcpy (rou_ext, argptr);
                }

                break;


            case 101:			/* VIEW 101: set ierr */

                merr_raise (intexpr (argptr));

                break;

            case 102:			/* VIEW 102 set deferred_ierr */

                deferred_ierr = intexpr (argptr);

                break;

                                
            case 103:                       /* MERGE to ^$WINDOW complete. Parameter is empty (for all windows) or string for window name in subscript 1 */
#if defined(MWAPI_GTK)                            
                mwapi_on_merge_complete (argptr);
#endif                            
                break;


	
#if !defined(__APPLE__) && !defined(__gnu_hurd__) && !defined(__AMIGA) && !defined(EMSCRIPTEN) && !defined(MSDOS)

            case 113:			/* VIEW 113: set termio infos */
            {
					
                struct termio tpara;

                i = intexpr (argptr);
					
                if (i < 1 || i > MAXDEV) {
                    merr_raise (NODEVICE);
                }
                else if (devopen[i] == 0) {
                    merr_raise (NOPEN);
                }
                else if (*codptr != ':') {
                    merr_raise (ARGER);
                }
                else {
						
                    codptr++;
						
                    expr (STRING);

                    j = intexpr (argptr);

                }

                if (merr () > OK) return;

                ioctl (fileno (opnfile[i]), TCGETA, &tpara);
					
                j = 0;
					
                tpara.c_iflag = intexpr (argptr);
					
                while ((ch = argptr[j]) != EOL) {

                    j++;
						
                    if (ch == ':') break;

                }

                tpara.c_oflag = intexpr (&argptr[j]);
					
                while ((ch = argptr[j]) != EOL) {
						
                    j++;
						
                    if (ch == ':') break;

                }

                tpara.c_cflag = intexpr (&argptr[j]);
					
                while ((ch = argptr[j]) != EOL) {
					
                    j++;
					
                    if (ch == ':') break;

                }

                tpara.c_lflag = intexpr (&argptr[j]);
					
                ioctl (fileno (opnfile[i]), TCSETA, &tpara);
					
                return;

            }

#endif /* __APPLE__ */				


            /* VIEW 133: remember ZLOAD directory on ZSAVE */
            case 133:
				
                zsavestrategy = tvexpr (argptr);

                return;
			

            default:

                merr_raise (ARGER);
                return;

        }				/* end switch one parameter VIEWs */
    } 
    else {				/* no parameters VIEWs */
		
        switch (arg1) {

			
            /* VIEW 21: close all globals */
            case 21:
				
                close_all_globals ();
				
                return;



                /* VIEW 29: symtab copy */
            case 29:			/* get space if needed */

                if (apartition == NULL) apartition = calloc ((unsigned) (PSIZE + 1), 1);
				
                for (i = 0; i <= PSIZE; i++) apartition[i] = partition[i];
				
                asymlen = symlen;
				
                for (i = 0; i < 128; i++) aalphptr[i] = alphptr[i];
				
                return;

        }

        merr_raise (ARGER);
        return;

    }

    return;
}					/* end view_com() */

/*
 * f = number of arguments
 * a = the arguments
 */
void view_fun (int f, char *a)				/* process VIEW function */
{
    int i;

    if (standard) {
        merr_raise (NOSTAND);
        return;
    }					/* non_standard */

    if (f == 1) {

        f = intexpr (a);
		
        switch (f) {

            /* $V(21) returns size of last global */
            case 21:

                if (oldfil[inuse][0] != NUL) {
				
                    lseek (olddes[inuse], 0L, 2);
                    lintstr (a, (long) tell (olddes[inuse]));
				
                } 
                else {
                    *a = EOL;
                }

                break;


                /* $V(22): number of v22_aliases */
            case 22:

                i = 0;
                f = 0;
		
                while (f < v22ptr) {
                    i++;
                    f += UNSIGN (v22ali[f]) + 1;
                }

                intstr (a, i);
				
                break;


                /* $V(23): contents of 'input buffer' */
            case 23:

                stcpy (a, ug_buf[io]);
                break;
			

                /* $V(24)/$V(25) number of screen lines */
            case 24:
            case 25:
					
                intstr (a, N_LINES);
                break;


                /* $V(26): DO-FOR-XEC stack pointer */
            case 26:
				
                intstr (a, nstx);
                break;
			

                /* $V(27): DO-FOR-XEC stack pointer (copy on error) */
            case 27:
				
                intstr (a, nesterr);
                break;
			

                /* $V(30): number of mumps arguments */
            case 30:
			
                intstr (a, m_argc);
                break;
			

                /* $V(31): environment variables */
            case 31:
				
                f = 0;
				
                while (m_envp[f] && m_envp[f][0] != NUL) f++;

                intstr (a, f);
                break;                                			
			

                /* $V(52): G0 input translation table */
            case 52:
				
                stcpy0 (a, G0I[io], 257L);
                a[255] = EOL;
                break;
			

                /* $V(53): G0 output translation table */
            case 53:
				
                stcpy0 (a, G0O[io], 257L);
                a[255] = EOL;
				
                break;
			

                /* $V(54): G1 input translation table */
            case 54:
				
                stcpy0 (a, G1I[io], 257L);
                a[255] = EOL;
				
                break;
			

                /* $V(55): G1 output translation table */
            case 55:
				
                stcpy0 (a, G1O[io], 257L);
                a[255] = EOL;
				
                break;
			

                /* $V(60): partial pattern match flag */
            case 60:
				
                intstr (a, pattrnflag);
                break;
			

                /* $V(61): partial pattern supplement character */
            case 61:
				
                a[0] = pattrnchar;
                a[1] = EOL;
				
                break;
			

                /* $V(62): random: seed number */
            case 62:
				
                lintstr (a, nrandom);
                break;


                /* $V(63): random: parameter a */
            case 63:
				
                lintstr (a, ran_a);
                break;


                /* $V(64): random: parameter b */
            case 64:
				
                lintstr (a, ran_b);
                break;


                /* $V(65): random: parameter c */
            case 65:
				
                lintstr (a, ran_c);
                break;


                /* $V(66): SIGTERM handling flag */
            case 66:
				
                intstr (a, killerflag);
                break;


                /* $V(67): SIGHUP handling flag */
            case 67:
				
                intstr (a, huperflag);
                break;


                /* ... reserved ... */


                /* $V(70): ZSORT/ZSYNTAX flag */
            case 70:
				
                intstr (a, s_fun_flag);
                break;


                /* $V(71): ZNEXT/ZNAME flag */
            case 71:
				
                intstr (a, n_fun_flag);
                break;


                /* $V(72): ZPREVIOUS/ZPIECE flag */
            case 72:
				
                intstr (a, p_fun_flag);
                break;


                /* $V(73): ZDATA/ZDATE flag */
            case 73:
				
                intstr (a, d_fun_flag);
                break;


                /* ... reserved ... */


                /* $V(79): old ZJOB vs. new ZJOB flag */
            case 79:
				
                intstr (a, zjobflag);
                break;


                /* $V(80): 7 vs. 8 bit flag */
            case 80:
				
                intstr (a, eightbit);
                break;


                /* $V(81): PF1 flag */
            case 81:
				
                intstr (a, PF1flag);
                break;
			

                /* $V(82): order counter */
            case 82:
				
                intstr (a, ordercounter);
                break;
			

                /* $V(83): text in $ZE flag */
            case 83:
				
                intstr (a, etxtflag);
                break;
				

                /* $V(84): path of current routine */
            case 84:			/* look whether we know where the routine came from */
				
                for (i = 0; i < NO_OF_RBUF; i++) {
					
                    int j;

                    if (pgms[i][0] == 0) {
                        *a = EOL;
                        return;
                    }			/* buffer empty */
					
                    j = 0;
					
                    while (rou_name[j] == pgms[i][j]) {
						
                        if (rou_name[j++] == EOL) {

                            stcpy (a, path[i]);
                            i = stlen (a);
							
                            if (i > 0) a[i - 1] = EOL;

                            return;

                        }

                    }

                }

                *a = EOL;
				
                break;			/* not found */
			

                /* $V(85): path of last global     */
            case 85:
				
                if (oldfil[inuse][0]) {
                    stcpy (a, oldfil[inuse]);
                }
                else {
                    *a = EOL;
                }
				
                i = 0;
				
                while (a[i] != EOL) {
					
                    if (a[i] == '^') {
					
                        if (i > 0) {
                            i--;
                        }
						
                        a[i] = EOL;
						
                        break;

                    }

                    i++;

                }

                break;
			

                /* $V(86): path of current device  */
            case 86:
				
                stcpy (a, act_oucpath[io]);
                break;
			

                /* $V(87): date type definitions */
            case 87:
				
                intstr (a, datetype);
                break;
			

                /* $V(88): date type definitions */
            case 88:
				
                intstr (a, timetype);
                break;
						

                /* $V(91): missig QUIT expr default expression */
            case 91:
				
                stcpy (a, exfdefault);
                break;
			

                /* $V(92): type mismatch error */
            case 92:
				
                intstr (a, typemmflag);
                break;
			

                /* $V(93): zkey production default rule definition */
            case 93:
				
                lintstr (a, v93);
                break;
			

                /* $V(98): routine extention */
            case 98:
				
                stcpy (a, rou_ext);
                break;		       			

                /* $V(100): exit status of last kill */
            case 100:
				
                intstr (a, v100);
                break;						

                /* $V(114): Number of rows in terminal */
            case 114:
				
                intstr (a, n_lines);
                break;
			

                /* $V(115): Number of columns in terminal */
            case 115:
				
                intstr (a, n_columns);
                break;
			

                /* $V(133): remember ZLOAD directory on ZSAVE */
            case 133:
				
                intstr (a, zsavestrategy);
                break;


            default:
				
                merr_raise (ARGER);
                return;

        }

        return;
    }

    if (f == 2) {
		
        char tmp[256];

        stcpy (tmp, argstck[arg + 1]);
		
        i = intexpr (argstck[arg + 1]);
        f = intexpr (a);
		
        if (merr () == MXNUM) return;

        if (f == 16) {

            if (i <= OK || i >= MAXERR) {
                merr_raise (ARGER);
                return;
            } 
            else {
                stcpy (a, errmes[i]);
            }

        } 
        else if (f == 22) {		/* return v22_alias entry */

            if (i) {			/* give one of the names which are aliases */
			
                f = 0;
			
                while (f < v22ptr) {

                    i--;
					
                    if (i == 0) {					
                        stcpy (a, &v22ali[f + 1]);
                        return;
                    }

                    f += UNSIGN (v22ali[f]) + 1;

                }

                a[0] = EOL;
				
                return;			/* that number had no entry in the table */
			
            }
			
            if (tstglvn (tmp) == FALSE) {
                merr_raise (INVREF);
                return;
            }
			
            if (v22ptr) {		/* there are aliases */
				
                int k, j;

                i = 0;
				
                while (i < v22ptr) {

                    k = i + UNSIGN (v22ali[i]) + 1;
                    j = 0;		/* is current reference an alias ??? */
					
                    while (v22ali[++i] == tmp[j]) {

                        if (v22ali[i] == EOL) break;
						
                        j++;

                    }

                    /* yes, it is, return it */
                    if (v22ali[i] == EOL && tmp[j] == EOL) {
                        stcpy (a, &v22ali[i + 1]);
                        return;
                    }

                    i = k;

                }

            }

            a[0] = EOL;			/* entry was not in the table */
			
            return;

        } 
        else if (f == 24) {		/* return screen line */

            if (i < -N_LINES || i > N_LINES || i == 0) {
                *a = EOL;
            }
            else if (i < 0) {
				
                stcpy0 (a, (*screen).screena[(unsigned int) (*screen).sclines[-i - 1]], (long) N_COLUMNS);			
                a[80] = EOL;

                return;

            } 
            else {
				
                stcpy0 (a, (*screen).screenx[(unsigned int) (*screen).sclines[i - 1]], (long) N_COLUMNS);
                a[80] = EOL;
				
                return;

            }
        } 
        else if (f == 25) {		/* return screen line with attribute */

            i--;
			
            if (i < 0 || i >= N_LINES) {
                *a = EOL;
            }
            else {
                v25 (a, i);
            }

            return;

        } 
        else if (f == 26) {		/* $V(26) returns DO-FOR-XEC stack pointer */
			
            if (i < 1 || i > nstx) {
                merr_raise (ARGER);
                return;
            }

            getraddress (a, i);
			
            return;

        }		/* $V(27) returns DO-FOR-XEC stack pointer(error state) */
        else if (f == 27) {

            if (i < 1 || i > nesterr) {
                merr_raise (ARGER);
                return;
            }
			
            stcpy (a, callerr[i]);
			
            return;

        } 
        else if (f == 30) {		/* $V(30): arguments of mumps */

            if (i < 1 || i > m_argc) {
                merr_raise (ARGER);
                return;
            }
		
            strcpy (a, m_argv[i - 1]);
            a[strlen (a)] = EOL;
		
            return;

            /* guard against very long environment name=value entries */
        } 
        else if (f == 31) { /* $V(31): environment variables */
			
            f = 0;
			
            while (m_envp[f] && m_envp[f++][0] != NUL) {
				
                if (f != i) continue;

                if ((f = strlen (m_envp[i - 1])) > STRLEN) {
                    merr_raise (M75);
                    return; 
                }

                strcpy (a, m_envp[i - 1]);
                a[f] = EOL;		
				
                return;

            }

            merr_raise (ARGER);
            return;

        } 
        else if (f == 93) { /* $V(93): zkey production rule definition */
			
            if (i <= 0 || i > NO_V93) {
                merr_raise (ARGER);
            }
            else {
                strcpy (a, v93a[i - 1]);
            }
			
            return;

        } 
#if !defined(__APPLE__) && !defined(__gnu_hurd__) && !defined(__AMIGA) && !defined(EMSCRIPTEN) && !defined(MSDOS)
        else if (f == 113) {		/* $V(113): get termio infos */
			
            struct termio tpara;

            if (i < 1 || i > MAXDEV) {
                merr_raise (NODEVICE);
                return;
            }

            if (devopen[i] == 0) {
                merr_raise (NOPEN);
                return;
            }

            ioctl (fileno (opnfile[i]), TCGETA, &tpara);
			
            intstr (a, tpara.c_iflag);
            i = stlen (a);
            a[i++] = ':';
			
            intstr (&a[i], tpara.c_oflag);
            i = stlen (a);
            a[i++] = ':';
			
            intstr (&a[i], tpara.c_cflag);
            i = stlen (a);
            a[i++] = ':';
			
            intstr (&a[i], tpara.c_lflag);
			
            return;

        } 
#endif		
        else {
            merr_raise (ARGER);
            return;
        }

    } 
    else if (f == 3) {

        char tmp[256];

        stcpy (tmp, argstck[arg + 2]);
        i = intexpr (argstck[arg + 1]);
        f = intexpr (a);
		
        if (merr () == MXNUM) return;

        if (f == 87) {			/* $V(87): date type definitions */
			
            if (i < 0 || i >= NO_DATETYPE) {
                merr_raise (ARGER);
                return;
            }

            f = intexpr (tmp);
			
            if (f > 0 && f < 13) {
                stcpy (a, month[i][f - 1]);
                return;
            }

            switch (f) {
				

                case 13:
					
                {
                    stcpy (a, dat1char[i]);
                    return;
                }


                case 14:

                {
                    stcpy (a, dat2char[i]);
                    return;
                }
					

                case 15:

                {
                    a[0] = dat3char[i];
                    a[1] = EOL;

                    return;
                }
				

                case 16:

                {
                    a[0] = dat4flag[i] + '0';
                    a[1] = EOL;
					
                    return;
                }
				

                case 17:

                {
                    a[0] = dat5flag[i] + '0';
                    a[1] = EOL;

                    return;
                }
				

                case 18:

                {
                    lintstr (a, datGRbeg[i] - 672411L);
                    return;
                }


            }
        } 
        else if (f == 88) {		/* $V(88): time type definitions */
			
            if (i < 0 || i >= NO_TIMETYPE) {
                merr_raise (ARGER);
                return;
            }

            f = intexpr (tmp);
			
            switch (f) {
                case 1:

                {
                    a[0] = tim1char[i];
                    a[1] = EOL;

                    return;
                }
				

                case 2:
				
                {
                    a[0] = tim2char[i];
                    a[1] = EOL;

                    return;
                }
				

                case 3:
				
                {
                    a[0] = tim3char[i];
                    a[1] = EOL;

                    return;
                }
				

                case 4:
				
                {
                    a[0] = tim4flag[i] + '0';
                    a[1] = EOL;

                    return;
                }
				

                case 5:
				
                {
                    a[0] = tim5flag[i] + '0';
                    a[1] = EOL;

                    return;
                }


            }

        }

        merr_raise (ARGER);
        return;

    } 
    else {
        merr_raise (FUNARG);
        return;
    }

    return;
}					/* end view_fun() */


void m_tolower (char *str)
{
    int ch;

    while ((ch = *str) != EOL) {
		
        ch = *str;
		
        if (ch <= 'Z' && ch >= 'A') {
            ch += 32;
            *str = ch;
        }

        str++;

    }

    return;

}					/* end tolower() */


/*
 * size = desired size for 'partition'
 */
short int newpsize (long size)
{
    char *newpart = NULL;
    char *anewpart = NULL;
    long dif, j;

    if (size == PSIZE) return 0;			/* nothing changes */
    if (size <= (PSIZE - symlen + 512)) return 0;			/* cannot decrease it now */
    if (apartition && size <= (PSIZE - asymlen + 512)) return 0;			/* cannot decrease it now */

    if (writing_mb) {
        newpart = shm_alloc ((size_t) (size+1));
    }
    else {
        newpart = calloc ((unsigned) (size + 1), 1);
    }
        
    if (newpart == NULL) return 1;			/* could not allocate stuff */
	
    if (apartition) {

        anewpart = calloc ((unsigned) (size + 1), 1);
		
        if (anewpart == NULL) {
            free (newpart);
            return 1;
        }	
        /* no more space */

    }

    dif = argptr - partition + 256;
	
    if (dif > PSIZE) dif = PSIZE;
	
    stcpy0 (newpart, partition, dif);	/* intermediate results */
    dif = size - PSIZE;
    stcpy0 (&newpart[symlen + dif], &partition[symlen], PSIZE - symlen);
	
    if (apartition) stcpy0 (&anewpart[asymlen + dif], &apartition[asymlen], PSIZE - asymlen);
	
    for (j = '%'; j <= 'z'; j++) {	/* update alphpointers */
		
        if (alphptr[j])	alphptr[j] += dif;
        if (aalphptr[j]) aalphptr[j] += dif;

    }

    PSIZE = size;
    symlen += dif;
    asymlen += dif;

    if (writing_mb) {
        shm_free (partition);
    }
    else {
        free (partition);			/* free previously allocated space */
    }
    
    if (apartition) free (apartition);		/* free previously allocated space */
	
    dif = newpart - partition;
    partition = newpart;
	
    if (apartition) apartition = anewpart;
	
    s = &partition[symlen] - 256;	/* pointer to symlen_offset        */
    argptr += dif;			/* pointer to beg of tmp-storage   */
	
    for (j = 0; j <= PARDEPTH; j++) {

        if (argstck[j])	argstck[j] += dif;

    }

    return 0;

}					/* end newpsize() */

/* change size of svn_table to 'size' */
short int newusize (long size)
{
	
    char   *newsvn;
    long    dif, j;

    if (size <= (UDFSVSIZ - svnlen)) return 0;			/* cannot decrease it now */
    if (size == UDFSVSIZ) return 0;			/* nothing changes */

    newsvn = calloc ((unsigned) (size + 1), 1);

    if (newsvn == NULL) return 1;			/* could not allocate stuff */
	
    stcpy0 (newsvn, svntable, svnlen);	/* intermediate results */
    dif = size - UDFSVSIZ;
    stcpy0 (&newsvn[svnlen + dif], &svntable[svnlen], UDFSVSIZ - svnlen);
	
    for (j = '%'; j <= 'z'; j++) {	/* update svn_alphpointers */
        if (svnaptr[j]) svnaptr[j] += dif;
    }

    UDFSVSIZ = size;
    svnlen += dif;
	
    free (svntable);			/* free previously allocated space */
	
    svntable = newsvn;

    return 0;

}					/* end newusize() */

/*
 * allocate 'nbrbuf' routine buffers
 * of 'size' bytes
 */
short int newrsize (long size, long nbrbuf)
{

    char *newrbuf;
    int i;
    long dif;
    unsigned long total;

    if (size <= (rouend - rouptr + 1)) return 0;			/* making it smaller would be a mistake */

    if (nbrbuf > MAXNO_OF_RBUF)	nbrbuf = MAXNO_OF_RBUF;

    total = (unsigned) nbrbuf *(unsigned) size;

    /* some overflow ??? */
    if ((total / (unsigned) size) != (unsigned) nbrbuf) {
        merr_raise (ARGER);
        return 1;
    }

    newrbuf = calloc (total, 1);	/* routine buffer pool             */
	
    while (newrbuf == NULL) {		/* could not allocate stuff...     */
		
        if (--nbrbuf < 2) return 1;			/* ...so try with less buffers     */
		
        total = (unsigned) nbrbuf *(unsigned) size;

        newrbuf = calloc (total, 1);

    }

    /* clear all routine buffers but one */
    for (i = 0; i < MAXNO_OF_RBUF; i++) {	/* empty routine buffers */
        pgms[i][0] = 0;
        ages[i] = 0L;
    }

    /* transfer to new buffer */
    stcpy0 (newrbuf, rouptr, (long) (rouend - rouptr + 1));
	
    dif = newrbuf - rouptr;
    rouend += dif;
    ends[0] = rouend;
	
    stcpy (pgms[0], rou_name);
	
    rouins += dif;
	
    if (roucur == (buff + (NO_OF_RBUF * PSIZE0 + 1))) {
        roucur = newrbuf + (nbrbuf * size + 1);
    }
    else {
        roucur += dif;
    }
	
    rouptr = newrbuf;

    free (buff);			/* free previously allocated space */

    buff = newrbuf;
    NO_OF_RBUF = nbrbuf;
    PSIZE0 = size;
	
    return 0;

}					/* end newrsize() */


void zreplace (char *a, char *b, char *c)
{
    long int ch, f, l, m, n;
    char d[256];

    if (b[0] == EOL) return;				/* 2nd argument was empty */
	
    l = stlen (c);			/* length of 3rd argument */
    n = 0;
    f = 0;
	
    for (;;) {

        m = 0;
		
        while ((ch = a[f + m]) == b[m] && ch != EOL) m++;

        if (b[m] == EOL) {
			
            if (n + l > STRLEN) {
                merr_raise (M75);
                return;
            }

            stcpy0 (&d[n], c, l);
			
            n += l;
            f += m;

        } 
        else {

            m = 1;
			
            if (n + 1 > STRLEN) {
                merr_raise (M75);
                return;
            }

            d[n++] = a[f++];

        }

        if (a[f] == EOL) break;

    }

    d[n] = EOL;
    stcpy (a, d);
	
    return;

}					/* end zreplace() */

short int tstglvn (char *a)				/* tests whether 'a' is a proper unsubscripted glvn */
{
    int i, ch;

    i = 0;

    if (a[0] == '^') {
		
        while (((ch = a[++i]) >= 'A' && ch <= 'Z') ||
               (ch >= 'a' && ch <= 'z') ||
               (ch >= '0' && ch <= '9') ||
               ((ch == '%' && i == 1) ||
                (standard == 0 &&
                 (((ch == '.' || ch == '/') && i == 1) ||
                  (((ch == '/' && a[i - 1] != '/') ||
                    (ch == '%' && a[i - 1] == '/')) &&
                   (a[1] == '.' || a[1] == '/'))))));
		
        return a[i] == EOL;

    }
	
    if ((ch = a[i++]) != '%' && (ch < 'A' || ch > 'Z') && (ch < 'a' || ch > 'z')) return FALSE;
	
    while ((ch = a[i++]) != EOL) {
	
        if ((ch < '0' || ch > '9') && (ch < 'A' || ch > 'Z') &&	(ch < 'a' || ch > 'z')) {
            return FALSE;
        }
	
    }
	
    return TRUE;

}					/* end tstnam() */

void zname (char *a, char *b)
{
    int i, j, f, n;

    i = 0;
    j = 0;
    f = FALSE;				/* we are in name section (vs.subscr.) */
    n = FALSE;				/* part is numeric (vs.alphabetic) */
	
    while ((a[i] = b[j++]) != EOL) {

        if (a[i] == '"') a[++i] = '"';
		
        if (a[i] == DELIM) {

            if (f) {

                if (n == FALSE) a[i++] = '"';

                if (i >= (STRLEN-2)/*was 253*/) {
                    a[i] = EOL;
                    merr_raise (M75);
				
                    return;
                }

                a[i] = ',';
				
                if ((n = znamenumeric (&b[j])) == FALSE) a[++i] = '"';

            } 
            else {
				
                a[i] = '(';
                f = TRUE;
			
                if ((n = znamenumeric (&b[j])) == FALSE) a[++i] = '"';

            }

        }

        if (++i >= STRLEN) {

            a[STRLEN] = EOL;
			
            if (b[j] != EOL) {
                merr_raise (M75);
                return;
            }

        }

    }
	
    if (f) {

        if (i > (STRLEN-2) /* was 253 */) {
            merr_raise (M75);
            return;
        }

        if (n == FALSE) a[i++] = '"';

        a[i++] = ')';
        a[i] = EOL;

    }

    return;

}					/* end zname() */

/* boolean function that tests whether str is a canonical numeric */
short int znamenumeric (char *str)
{

    register int ptr = 0;
    register int ch;
    register int point;

    if (str[0] == '-') ptr = 1;

    if (str[ptr] == EOL) return FALSE;
    if (str[ptr] == DELIM) return FALSE;
    if (str[ptr] == '0') return str[1] == EOL || str[1] == DELIM;	/* leading zero */
	
    point = FALSE;
	
    while ((ch = str[ptr++]) != EOL && ch != DELIM) {
		
        if (ch > '9') return FALSE;
		
        if (ch < '0') {

            if (ch != '.') return FALSE;
            if (point) return FALSE;		/* multiple points */
			
            point = TRUE;

        }

    }

    if (point) {
        if ((ch = str[ptr - 2]) == '0')	return FALSE;		/* trailing zero */
        if (ch == '.') return FALSE;		/* trailing point */
    }

    return TRUE;

}					/* end of znamenumeric() */

void procv22 (char *key)				/* process v22 translation */
{
    int     i, j, k1;
    char    tmp1[256];

    if (*key == EOL || *key == 0) return;

    i = 0;
    j = 0;
	
    while (i < v22ptr) {

        k1 = i + UNSIGN (v22ali[i]) + 1;
		
        /* is current reference an alias ??? */
		
        j = 0;
		
        while (v22ali[++i] == key[j]) {

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

        /* yes, it is, so resolve it now! */
        if (v22ali[i] == EOL && (key[j] == EOL || key[j] == DELIM)) {

            stcpy (tmp1, key);
            stcpy (key, &v22ali[i + 1]);
            stcat (key, &tmp1[j]);
			
            i = 0;
			
            continue;			/* try again, it might be a double alias! */

        }

        i = k1;

    }

    return;

}					/* end of procv22() */

void v25 (char *a, int i)
{
    short c, exc, k, l, p;

    k = 0;
    exc = ~((*screen).screena[(unsigned int) (*screen).sclines[i]][0]);
	
    for (l = 0; l < N_COLUMNS; l++) {
		
        p = exc;
        exc = (*screen).screena[(unsigned int) (*screen).sclines[i]][l];
        c = (*screen).screenx[(unsigned int) (*screen).sclines[i]][l];

#ifdef NEVER

        /* this may result in a problem, when in a system */
        /* different G0O/G1O sets are in use !!!          */
        if (((exc == 1 && (p == 0)) || ((exc == 0) && (p == 1))) && (G0O[HOME][c] == G1O[HOME][c])) {
            exc = p;			/* if char looks same in SI/SO, delay SI/SO */
        }

#endif /* NEVER */

        if (exc != p) {			/* set attribute */

#ifdef SCO

            p = p & ~04;		/* suppress SGR(3) */

            if (p & 0200) p = p & 0201;		/* no display */
            if (p & 0100) p = p & 0101;		/* inverse */

#endif /* SCO */

            if ((p & 01) != (exc & 01)) a[k++] = (exc & 01) ? SO : SI;
			
            if ((p & ~01) != (exc & ~01)) {
				
                a[k++] = ESC;
                a[k++] = '[';
			
                for (p = 1; p < 8; p++) {
					
                    if (exc & (1 << p)) {

#ifdef SCO

                        if (p == 1) {
                            a[k++] = '1';
                            a[k++] = ';';
						
                            continue;
                        }

#endif /* SCO */

                        a[k++] = '1' + p;
                        a[k++] = ';';

                    }

                }

                if (a[k - 1] == ';') k--;
			
                a[k++] = 'm';
            }

        }

        a[k++] = c;

    }

    if (exc & 01) a[k++] = SI;

    a[k] = EOL;
	
    return;

}					/* end of v25() */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>