示例#1
0
void iomt_use(io_desc *iod, mval *pp)
{
	unsigned char	ch, len;
	int		lab_type;
	int4		length, width;
	int4		skips;
	d_mt_struct	*mt_ptr, *out_ptr;
	io_desc		*d_in, *d_out;
	mident		tab;
	int		p_offset;

	error_def(ERR_MTINVLAB);
	error_def(ERR_DEVPARMNEG);
	error_def(ERR_UNIMPLOP);

	p_offset = 0;
	d_in = iod->pair.in;
	d_out = iod->pair.out;
	mt_ptr = (d_mt_struct *)iod->dev_sp;
	out_ptr = (d_mt_struct *)d_out->dev_sp;
	while (*(pp->str.addr + p_offset) != iop_eol)
	{
		switch (ch = *(pp->str.addr + p_offset++))
		{
		case iop_ebcdic:
			mt_ptr->ebcdic = TRUE;
			break;
		case iop_noebcdic:
			mt_ptr->ebcdic = FALSE;
			break;
		case iop_newversion:
			mt_ptr->newversion = TRUE;
			break;
		case iop_label:
			memset(tab.c, 0, sizeof(mident));
			len = *(pp->str.addr + p_offset);
			memcpy(tab.c, (pp->str.addr + p_offset + 1), (len < sizeof(mident) ? len : sizeof(mident)));
			if ((lab_type = namelook(mtlab_index, mtlab_names, tab.c)) < 0)
				rts_error(VARLSTCNT(1) ERR_MTINVLAB);
			mt_ptr->labeled = mtlab_type[lab_type];
			break;
		case iop_nolabel:
			mt_ptr->labeled = FALSE;
			break;
		case iop_rdcheckdata:
			mt_ptr->read_mask |= IO_M_DATACHECK;
			break;
		case iop_nordcheckdata:
			mt_ptr->read_mask &= (~(IO_M_DATACHECK));
			break;
		case iop_wtcheckdata:
			mt_ptr->write_mask |= IO_M_DATACHECK;
			break;
		case iop_nowtcheckdata:
			mt_ptr->write_mask &= (~(IO_M_DATACHECK));
			break;
		case iop_inhretry:
			mt_ptr->write_mask |= IO_M_INHRETRY;
			mt_ptr->read_mask |= IO_M_INHRETRY;
			break;
		case iop_retry:
			mt_ptr->write_mask &= ~IO_M_INHRETRY;
			mt_ptr->read_mask &= ~IO_M_INHRETRY;
			break;
		case iop_inhextgap:
			mt_ptr->write_mask |= IO_M_INHEXTGAP;
			break;
		case iop_extgap:
			mt_ptr->write_mask &= ~IO_M_INHEXTGAP;
			break;
		case iop_length:
			GET_LONG(length, (pp->str.addr + p_offset));
			if (length < 0)
				rts_error(VARLSTCNT(1) ERR_DEVPARMNEG);
			iod->length = length;
			break;
		case iop_width:
			GET_LONG(width, (pp->str.addr + p_offset));
			if (width < 0)
				rts_error(VARLSTCNT(1) ERR_DEVPARMNEG);
			if (width == 0)
			{
				iod->wrap = FALSE;
				iod->width = mt_ptr->record_sz;
			} else  if (width <= mt_ptr->record_sz)
			{
				iomt_flush(iod);
				iod->width = width;
				iod->wrap = TRUE;
			}
			break;
		case iop_wrap:
			out_ptr->wrap = TRUE;
			break;
		case iop_nowrap:
			out_ptr->wrap = FALSE;
			break;
		case iop_skipfile:
			GET_LONG(skips, (pp->str.addr + p_offset));
			iomt_skipfile(iod, skips);
			break;
		case iop_unload:
			assert(FALSE);
			break;
		case iop_rewind:
			iomt_rewind(iod);
			break;
		case iop_erasetape:
			iomt_erase(iod);
			break;
		case iop_space:
			GET_LONG(skips, (pp->str.addr + p_offset));
			iomt_skiprecord(iod, skips);
			break;
		case iop_writeof:
			iomt_eof(iod);
			break;
		case iop_writetm:
			iomt_tm(iod);
			break;
		case iop_writelb:
			memset(&tab, 0, sizeof(mident));
			len = *(pp->str.addr + p_offset);
			memcpy(&tab.c[0], pp->str.addr + p_offset + 1, (len < sizeof(mident) ? len : sizeof(mident)));
			if ((lab_type = namelook(mtwtlab_index, mtwtlab_names, tab.c)) < 0)
				rts_error(VARLSTCNT(1) ERR_MTINVLAB);
			iomt_wtansilab(iod, mtwtlab_type[lab_type]);
			break;
		case iop_next:
			rts_error(VARLSTCNT(1) ERR_UNIMPLOP);
			break;
		case iop_exception:
			iod->error_handler.len = *(pp->str.addr + p_offset);
			iod->error_handler.addr = (char *)(pp->str.addr + p_offset + 1);
			s2pool(&iod->error_handler);
			break;
		case iop_ipchset:
			{
				if ( (iconv_t)0 != iod->input_conv_cd )
				{
					ICONV_CLOSE_CD(iod->input_conv_cd);
				}
				SET_CODE_SET(iod->in_code_set, (char *)(pp->str.addr + p_offset + 1));
				if (DEFAULT_CODE_SET != iod->in_code_set)
					ICONV_OPEN_CD(iod->input_conv_cd, (char *)(pp->str.addr + p_offset + 1), INSIDE_CH_SET);
                        	break;
			}
                case iop_opchset:
			{
				if ( (iconv_t) 0 != iod->output_conv_cd )
				{
					ICONV_CLOSE_CD(iod->output_conv_cd);
				}
				SET_CODE_SET(iod->out_code_set, (char *)(pp->str.addr + p_offset + 1));
				if (DEFAULT_CODE_SET != iod->out_code_set)
					ICONV_OPEN_CD(iod->output_conv_cd, INSIDE_CH_SET, (char *)(pp->str.addr + p_offset + 1));
                        	break;
			}
		default:
			break;
		}
		p_offset += ((IOP_VAR_SIZE == io_params_size[ch]) ?
			(unsigned char)*(pp->str.addr + p_offset) + 1 : io_params_size[ch]);
	}
}
示例#2
0
void	iosocket_use(io_desc *iod, mval *pp)
{
    unsigned char	ch, len;
    int		handled_len, handlea_len, handles_len;
    int4		length, width, new_len;
    d_socket_struct *dsocketptr;
    socket_struct	*socketptr, newsocket;
    char		handlea[MAX_HANDLE_LEN], handles[MAX_HANDLE_LEN], handled[MAX_HANDLE_LEN];
    char            addr[SA_MAXLITLEN], *errptr, sockaddr[SA_MAXLITLEN],
                    temp_addr[SA_MAXLITLEN], ioerror;
    unsigned char	delimiter_buffer[MAX_N_DELIMITER * (MAX_DELIM_LEN + 1)];
    unsigned char	zff_buffer[MAX_ZFF_LEN];
    boolean_t	attach_specified = FALSE,
                detach_specified = FALSE,
                connect_specified = FALSE,
                ioerror_specified = FALSE,
                listen_specified = FALSE,
                socket_specified = FALSE,
                delay_specified = FALSE,
                nodelay_specified = FALSE,
                bfsize_specified = FALSE,
                ibfsize_specified = FALSE,
                moreread_specified = FALSE,
                create_new_socket;
    int4 		index, n_specified, zff_len, delimiter_len, moreread_timeout;
    int		fil_type, nodelay, p_offset = 0;
    uint4		bfsize = DEFAULT_SOCKET_BUFFER_SIZE, ibfsize;
    char		*tab;
    int		save_errno;
    size_t		d_socket_struct_len;
    mstr		lcl_zff;

    assert(iod->state == dev_open);
    assert(iod->type == gtmsocket);
    dsocketptr = (d_socket_struct *)(iod->dev_sp);
    /* ---------------------------------- parse the command line ------------------------------------ */
    n_specified = 0;
    zff_len = -1; /* indicates neither ZFF nor ZNOFF specified */
    delimiter_len = -1; /* indicates neither DELIM nor NODELIM specified */

    /* A read or wait was interrupted for this device. Allow only parmless use in $zinterrupt code for
       and interrupted device.
    */
    if (iop_eol != *(pp->str.addr + p_offset))
    {   /* Parameters were specified */
        if (dsocketptr->mupintr)
        {   /* And if we are in $zinterrupt code this is not allowed */
            if (dollar_zininterrupt)
                rts_error(VARLSTCNT(1) ERR_ZINTRECURSEIO);
            /* We are not in $zinterrupt code and this device was not resumed properly
               so clear its restartability.
            */
            io_find_mvstent(iod, TRUE);
            dsocketptr->mupintr = FALSE;
        }
    } else if (dsocketptr->mupintr && !dollar_zininterrupt)
    {   /* The interrupted read was not properly resumed so clear it now */
        dsocketptr->mupintr = FALSE;
        dsocketptr->sock_save_state.who_saved = sockwhich_invalid;
        io_find_mvstent(iod, TRUE);
    }

    while (iop_eol != (ch = *(pp->str.addr + p_offset++)))
    {
        assert((params)ch < (params)n_iops);
        switch (ch)
        {
        case iop_exception:
            iod->error_handler.len = *(pp->str.addr + p_offset);
            iod->error_handler.addr = (char *)(pp->str.addr + p_offset + 1);
            s2pool(&iod->error_handler);
            break;
        case iop_filter:
            len = *(pp->str.addr + p_offset);
            tab = pp->str.addr + p_offset + 1;
            if ((fil_type = namelook(filter_index, filter_names, tab, len)) < 0)
            {
                rts_error(VARLSTCNT(1) ERR_TTINVFILTER);
                return;
            }
            switch (fil_type)
            {
            case 0:
                iod->write_filter |= CHAR_FILTER;
                break;
            case 1:
                iod->write_filter |= ESC1;
                break;
            case 2:
                iod->write_filter &= ~CHAR_FILTER;
                break;
            case 3:
                iod->write_filter &= ~ESC1;
                break;
            }
            break;
        case iop_nofilter:
            iod->write_filter = 0;
            break;
        case iop_attach:
            n_specified++;
            attach_specified = TRUE;
            handlea_len = (int)(*(pp->str.addr + p_offset));
            memcpy(handlea, (char *)(pp->str.addr + p_offset + 1), handlea_len);
            break;
        case iop_detach:
            n_specified++;
            detach_specified = TRUE;
            handled_len = (int)(*(pp->str.addr + p_offset));
            memcpy(handled, (char *)(pp->str.addr + p_offset + 1), handled_len);
            break;
        case iop_connect:
            n_specified++;
            connect_specified = TRUE;
            len = *(pp->str.addr + p_offset);
            if (len < SA_MAXLITLEN)
            {
                memcpy(sockaddr, (char *)(pp->str.addr + p_offset + 1), len);
                sockaddr[len] = '\0';
            } else
                rts_error(VARLSTCNT(6) ERR_ADDRTOOLONG,
                          4, len, pp->str.addr + p_offset + 1, len, SA_MAXLITLEN);
            break;
        case iop_delimiter:
            n_specified++;
            delimiter_len = (int4)(unsigned char)*(pp->str.addr + p_offset);
            if (((MAX_DELIM_LEN + 1) * MAX_N_DELIMITER) >= delimiter_len)
                memcpy(delimiter_buffer, (pp->str.addr + p_offset + 1), delimiter_len);
            else
                rts_error(VARLSTCNT(1) ERR_DELIMSIZNA);
            break;
        case	iop_nodelimiter:
            delimiter_len = 0;
            break;
        case	iop_zdelay:
            delay_specified = TRUE;
            break;
        case	iop_znodelay:
            nodelay_specified = TRUE;
            break;
        case	iop_zbfsize:
            bfsize_specified = TRUE;
            GET_ULONG(bfsize, pp->str.addr + p_offset);
            if ((0 == bfsize) || (MAX_SOCKET_BUFFER_SIZE < bfsize))
                rts_error(VARLSTCNT(3) ERR_ILLESOCKBFSIZE, 1, bfsize);
            break;
        case	iop_zibfsize:
            ibfsize_specified = TRUE;
            GET_ULONG(ibfsize, pp->str.addr + p_offset);
            if ((0 == ibfsize) || (MAX_INTERNAL_SOCBUF_SIZE < ibfsize))
                rts_error(VARLSTCNT(3) ERR_ILLESOCKBFSIZE, 1, ibfsize);
            break;
        case iop_ioerror:
            n_specified++;
            ioerror_specified = TRUE;
            ioerror = *(char *)(pp->str.addr + p_offset + 1);
            break;
        case iop_zlisten:
            n_specified++;
            listen_specified = TRUE;
            len = *(pp->str.addr + p_offset);
            if (len < SA_MAXLITLEN)
            {
                memcpy(sockaddr, (char *)(pp->str.addr + p_offset + 1), len);
                sockaddr[len] = '\0';
            } else
                rts_error(VARLSTCNT(6) ERR_ADDRTOOLONG,
                          4, len, pp->str.addr + p_offset + 1, len, SA_MAXLITLEN);
            break;
        case iop_socket:
            n_specified++;
            socket_specified = TRUE;
            handles_len = (int)(*(pp->str.addr + p_offset));
            memcpy(handles, (char *)(pp->str.addr + p_offset + 1), handles_len);
            break;
        case iop_ipchset:
#if defined(KEEP_zOS_EBCDIC) || defined(VMS)
            if ((iconv_t)0 != iod->input_conv_cd)
                ICONV_CLOSE_CD(iod->input_conv_cd);
            SET_CODE_SET(iod->in_code_set, (char *)(pp->str.addr + p_offset + 1));
            if (DEFAULT_CODE_SET != iod->in_code_set)
                ICONV_OPEN_CD(iod->input_conv_cd, INSIDE_CH_SET, (char *)(pp->str.addr + p_offset + 1));
#endif
            break;
        case iop_opchset:
#if defined(KEEP_zOS_EBCDIC) || defined(VMS)
            if ((iconv_t)0 != iod->output_conv_cd)
                ICONV_CLOSE_CD(iod->output_conv_cd);
            SET_CODE_SET(iod->out_code_set, (char *)(pp->str.addr + p_offset + 1));
            if (DEFAULT_CODE_SET != iod->out_code_set)
                ICONV_OPEN_CD(iod->output_conv_cd, (char *)(pp->str.addr + p_offset + 1), INSIDE_CH_SET);
#endif
            break;
        case iop_zff:
            if (MAX_ZFF_LEN >= (zff_len = (int4)(unsigned char)*(pp->str.addr + p_offset)))
                memcpy(zff_buffer, (char *)(pp->str.addr + p_offset + 1), zff_len);
            else
                rts_error(VARLSTCNT(4) ERR_ZFF2MANY, 2, zff_len, MAX_ZFF_LEN);
            break;
        case iop_znoff:
            zff_len = 0;
            break;
        case iop_length:
            GET_LONG(length, pp->str.addr + p_offset);
            if (length < 0)
                rts_error(VARLSTCNT(1) ERR_DEVPARMNEG);
            iod->length = length;
            break;
        case iop_width:
            /* SOCKET WIDTH is handled the same way as TERMINAL WIDTH */
            GET_LONG(width, pp->str.addr + p_offset);
            if (width < 0)
                rts_error(VARLSTCNT(1) ERR_DEVPARMNEG);
            if (0 == width)
            {
                iod->width = TCPDEF_WIDTH;
                iod->wrap = FALSE;
            } else
            {
                iod->width = width;
                iod->wrap = TRUE;
            }
            break;
        case iop_wrap:
            iod->wrap = TRUE;
            break;
        case iop_nowrap:
            iod->wrap = FALSE;
            break;
        case iop_morereadtime:
            /* Time in milliseconds socket read will wait for more data before returning */
            GET_LONG(moreread_timeout, pp->str.addr + p_offset);
            if (-1 == moreread_timeout)
                moreread_timeout = DEFAULT_MOREREAD_TIMEOUT;
            else if (-1 > moreread_timeout)
                rts_error(VARLSTCNT(1) ERR_DEVPARMNEG);
            else if (MAX_MOREREAD_TIMEOUT < moreread_timeout)
                rts_error(VARLSTCNT(3) ERR_MRTMAXEXCEEDED, 1, MAX_MOREREAD_TIMEOUT);
            moreread_specified = TRUE;
            break;
        default:
            /* ignore deviceparm */
            break;
        }
        p_offset += ((io_params_size[ch] == IOP_VAR_SIZE) ?
                     (unsigned char)*(pp->str.addr + p_offset) + 1 : io_params_size[ch]);
    }
    /* ------ return immediately if no flag, worth a check because it is mostly true ------------ */
    if (1 == p_offset)
        return;
    /* ------------------------------ compatibility verification -------------------------------- */
    if ((socket_specified) && ((n_specified > 2) || ((2 == n_specified) && (0 >= delimiter_len))))
    {
        rts_error(VARLSTCNT(8) ERR_ACOMPTBINC, 6, LEN_AND_LIT("SOCKET"), LEN_AND_LIT("DELIMITER"), LEN_AND_LIT("USE"));
        return;
    }
    if (connect_specified && listen_specified)
    {
        rts_error(VARLSTCNT(8) ERR_ABNCOMPTINC, 6, LEN_AND_LIT("CONNECT"), LEN_AND_LIT("ZLISTEN"), LEN_AND_LIT("USE"));
        return;
    }
    if (delay_specified && nodelay_specified)
    {
        rts_error(VARLSTCNT(8) ERR_ABNCOMPTINC, 6, LEN_AND_LIT("DELAY"), LEN_AND_LIT("NODELAY"), LEN_AND_LIT("OPEN"));
        return;
    }
    /* ------------------ make a local copy of device structure to play with -------------------- */
    d_socket_struct_len = SIZEOF(d_socket_struct) + (SIZEOF(socket_struct) * (gtm_max_sockets - 1));
    memcpy(newdsocket, dsocketptr, d_socket_struct_len);
    /* --------------- handle the two special cases attach/detach first ------------------------- */
    if (detach_specified)
    {
        if (1 < n_specified)
        {
            rts_error(VARLSTCNT(6) ERR_ANCOMPTINC, 4, LEN_AND_LIT("DETACH"), LEN_AND_LIT("USE"));
            return;
        }
        if (NULL == socket_pool)
            iosocket_poolinit();
        iosocket_switch(handled, handled_len, newdsocket, socket_pool);
        memcpy(dsocketptr, newdsocket, d_socket_struct_len);
        if (0 > dsocketptr->current_socket)
        {
            io_curr_device.in = io_std_device.in;
            io_curr_device.out = io_std_device.out;
        }
        return; /* detach can only be specified by itself */
    }
    if (attach_specified)
    {   /* NOTE: A socket could be moved from one device to another using DETACH/ATTACH. A socket does not carry I[O]CHSET with
         * it while being moved. Such a socket will use the I[O]CHSET of the device it is ATTACHed to. If there is input still
         * buffered, this may cause unintentional consequences in the application if I[O]CHSET changes. GT.M does not detect
         * (or report) a change in I[O]CHSET due to DETACH/ATTACH.
         */
        if (1 < n_specified)
        {
            rts_error(VARLSTCNT(6) ERR_ANCOMPTINC, 4, LEN_AND_LIT("ATTACH"), LEN_AND_LIT("USE"));
            return;
        }
        if (NULL == socket_pool)
        {
            rts_error(VARLSTCNT(4) ERR_SOCKNOTFND, 2, handlea_len, handlea);
            return;
        }
        iosocket_switch(handlea, handlea_len, socket_pool, newdsocket);
        memcpy(dsocketptr, newdsocket, d_socket_struct_len);
        return; /* attach can only be specified by itself */
    }
    /* ------------ create/identify the socket to work on and make a local copy ----------------- */
    if (create_new_socket = (listen_specified || connect_specified))	/* real "=" */
    {
        /* allocate the structure for a new socket */
        if (NULL == (socketptr = iosocket_create(sockaddr, bfsize, -1)))
            return;
        /* give the new socket a handle */
        iosocket_handle(handles, &handles_len, TRUE, dsocketptr);
        socketptr->handle_len = handles_len;
        memcpy(socketptr->handle, handles, handles_len);
        socketptr->dev = newdsocket;	/* use newdsocket temporarily for the sake of bind/connect */
    } else
    {
        if (socket_specified)
        {
            /* use the socket flag to identify which socket to apply changes */
            if (0 > (index = iosocket_handle(handles, &handles_len, FALSE, newdsocket)))
            {
                rts_error(VARLSTCNT(4) ERR_SOCKNOTFND, 2, handles_len, handles);
                return;
            }
            newdsocket->current_socket = index;
            socketptr = newdsocket->socket[index];
        } else
        {
            socketptr = newdsocket->socket[newdsocket->current_socket];
            if (newdsocket->n_socket <= newdsocket->current_socket)
            {
                assert(FALSE);
                rts_error(VARLSTCNT(4) ERR_CURRSOCKOFR, 2, newdsocket->current_socket, newdsocket->n_socket);
                return;
            }
        }
    }
    newsocket = *socketptr;
    /* ---------------------- apply changes to the local copy of the socket --------------------- */
    if (0 <= delimiter_len)
    {
        iosocket_delimiter(delimiter_buffer, delimiter_len, &newsocket, (0 == delimiter_len));
        /* The delimiter has changed. The iosocket_readfl/write routine won't notice so we have to do
           the UTF16xx conversion since we changed it.
        */
        DBGSOCK2((stdout, "socuse: Delimiter(s) replaced - num delims: %d  delimiter_len: %d  ichset: %d  ochset: %d\n",
                  newsocket.n_delimiter, delimiter_len, iod->ichset, iod->ochset));
        if  (0 < delimiter_len)
        {
            if (!newsocket.first_read && (CHSET_UTF16BE == iod->ichset || CHSET_UTF16LE == iod->ichset))
            {   /* We have been reading with this socket so convert this new delimiter set */
                DBGSOCK2((stdout, "socuse: Converting new delimiters for input\n"));
                iosocket_delim_conv(&newsocket, iod->ichset);
            }
            if (!newsocket.first_write && (CHSET_UTF16BE == iod->ochset || CHSET_UTF16LE == iod->ochset))
            {   /* We have been writing with this socket so convert the new default output delimiter */
                DBGSOCK2((stdout, "socuse: Converting new delimiters for output\n"));
                if (newsocket.first_read || (CHSET_UTF16BE != iod->ichset && CHSET_UTF16LE != iod->ichset))
                {   /* Need to do conversion as iosocket_delim_conv above didn't do it for us */
                    DBGSOCK2((stdout, "socuse: running convert for write since input didn't do it\n"));
                    new_len = gtm_conv(chset_desc[CHSET_UTF8], chset_desc[iod->ochset],
                                       &newsocket.delimiter[0], NULL, NULL);
                    if (MAX_DELIM_LEN < new_len)
                    {
                        rts_error(VARLSTCNT(1) ERR_DELIMSIZNA);
                        return;
                    }
                } else
                {
                    DBGSOCK2((stdout, "socuse: using previous length from read conversion\n"));
                    new_len = newsocket.idelimiter[0].len;
                }
                newsocket.odelimiter0.len = new_len;
                UNICODE_ONLY(newsocket.odelimiter0.char_len = newsocket.delimiter[0].char_len);
                newsocket.odelimiter0.addr = malloc(new_len);
                memcpy(newsocket.odelimiter0.addr,
                       (newsocket.first_read ? (char *)stringpool.free : newsocket.idelimiter[0].addr),
                       new_len);
            }
        }
    }
    if (iod->wrap && 0 != newsocket.n_delimiter && iod->width < newsocket.delimiter[0].len)
        rts_error(VARLSTCNT(4) ERR_DELIMWIDTH, 2, iod->width, newsocket.delimiter[0].len);
    if (0 <= zff_len && /* ZFF or ZNOFF specified */
            0 < (newsocket.zff.len = zff_len)) /* assign the new ZFF len, might be 0 from ZNOFF, or ZFF="" */
    {   /* ZFF="non-zero-len-string" specified */
        if (CHSET_UTF16BE == iod->ochset || CHSET_UTF16LE == iod->ochset) /* need conversion of ZFF */
        {
            DBGSOCK2((stdout, "socuse: Converting zff\n"));
            lcl_zff.addr = (char *)zff_buffer;
            lcl_zff.len = zff_len;
            new_len = gtm_conv(chset_desc[CHSET_UTF8], chset_desc[iod->ochset], &lcl_zff, NULL, NULL);
            if (MAX_ZFF_LEN < new_len)
                rts_error(VARLSTCNT(4) ERR_ZFF2MANY, 2, new_len, MAX_ZFF_LEN);
            if (NULL == newsocket.zff.addr) /* we rely on newsocket.zff.addr being set to 0 in iosocket_create() */
                newsocket.zff.addr = (char *)malloc(MAX_ZFF_LEN);
            newsocket.zff.len = new_len;
            UNICODE_ONLY(newsocket.zff.char_len = 0); /* don't care */
            memcpy(newsocket.zff.addr, stringpool.free, new_len);

        } else
        {   /* Store parm without conversion */
            if (gtm_utf8_mode) /* Check if ZFF has any invalid UTF-8 character */
            {   /* Note: the ZFF string originates from the source program, so is in UTF-8 mode or M mode
                   regardless of OCHSET of this device. ZFF is output on WRITE # command, and MUST contain
                   valid UTF-8 sequence. This validation is handled by gtm_conv in the path above.
                */
                utf8_len_strict(zff_buffer, zff_len);
            }
            if (NULL == newsocket.zff.addr) /* we rely on newsocket.zff.addr being set to 0 in iosocket_create() */
                newsocket.zff.addr = (char *)malloc(MAX_ZFF_LEN);
            memcpy(newsocket.zff.addr, zff_buffer, zff_len);
        }
    }
    if (ioerror_specified)
        newsocket.ioerror = ('T' == ioerror || 't' == ioerror);
    if (nodelay_specified || delay_specified)
        newsocket.nodelay = nodelay_specified;	/* defaults to DELAY */
    if (ibfsize_specified)
        newsocket.bufsiz = ibfsize;
    if (moreread_specified)
    {
        newsocket.moreread_timeout = moreread_timeout;
        newsocket.def_moreread_timeout = TRUE;	/* need to know this was user-defined in iosocket_readfl.c */
    }
    if (!create_new_socket)
    {
        /* these changes apply to only pre-existing sockets */
        if (bfsize_specified)
            newsocket.buffer_size = bfsize;
#ifdef TCP_NODELAY
        nodelay = newsocket.nodelay ? 1 : 0;
        if ((socketptr->nodelay != newsocket.nodelay) &&
                (-1 == tcp_routines.aa_setsockopt(newsocket.sd, IPPROTO_TCP,
                        TCP_NODELAY, &nodelay, SIZEOF(nodelay))))
        {
            save_errno = errno;
            errptr = (char *)STRERROR(save_errno);
            rts_error(VARLSTCNT(7) ERR_SETSOCKOPTERR, 5, LEN_AND_LIT("TCP_NODELAY"), save_errno, LEN_AND_STR(errptr));
            return;
        }
#endif
        if ((socketptr->bufsiz != newsocket.bufsiz) &&
                (-1 == tcp_routines.aa_setsockopt(newsocket.sd, SOL_SOCKET,
                        SO_RCVBUF, &newsocket.bufsiz, SIZEOF(newsocket.bufsiz))))
        {
            save_errno = errno;
            errptr = (char *)STRERROR(save_errno);
            rts_error(VARLSTCNT(7) ERR_SETSOCKOPTERR, 5, LEN_AND_LIT("SO_RCVBUF"), save_errno, LEN_AND_STR(errptr));
            return;
        }
        if (socketptr->buffer_size != newsocket.buffer_size)
        {
            if (socketptr->buffered_length > bfsize)
                rts_error(VARLSTCNT(4) ERR_SOCKBFNOTEMPTY, 2, bfsize, socketptr->buffered_length);
            newsocket.buffer = (char *)malloc(bfsize);
            if (0 < socketptr->buffered_length)
            {
                memcpy(newsocket.buffer, socketptr->buffer + socketptr->buffered_offset,
                       socketptr->buffered_length);
                newsocket.buffered_offset = 0;
            }
        }
    }
    /* -------------------------------------- action -------------------------------------------- */
    if ((listen_specified && (!iosocket_bind(&newsocket, NO_M_TIMEOUT, ibfsize_specified))) ||
            (connect_specified && (!iosocket_connect(&newsocket, 0, ibfsize_specified))))
    {   /* error message should be printed from bind/connect */
        if (socketptr->sd > 0)
            (void)tcp_routines.aa_close(socketptr->sd);
        iosocket_delimiter((unsigned char *)NULL, 0, &newsocket, TRUE);
        if (NULL != socketptr->zff.addr)
            free(socketptr->zff.addr);
        if (NULL != socketptr->buffer)
            free(socketptr->buffer);
        free(socketptr);
        return;
    }
    /* ------------------------------------ commit changes -------------------------------------- */
    if (create_new_socket)
    {
        if (gtm_max_sockets <= newdsocket->n_socket)
        {
            rts_error(VARLSTCNT(3) ERR_SOCKMAX, 1, gtm_max_sockets);
            return;
        }
        /* a new socket is created. so add to the list */
        newsocket.dev = dsocketptr;
        newdsocket->socket[newdsocket->n_socket++] = socketptr;
        newdsocket->current_socket = newdsocket->n_socket - 1;
    }
    else if (socketptr->buffer_size != newsocket.buffer_size)
        free(socketptr->buffer);
    *socketptr = newsocket;
    memcpy(dsocketptr, newdsocket, d_socket_struct_len);
    return;
}
示例#3
0
int one_job_param (char **parptr)
{
	boolean_t	neg;
	int		x, num;
        int		len;

	error_def	(ERR_JOBPARUNK);
	error_def	(ERR_JOBPARNOVAL);
	error_def	(ERR_JOBPARVALREQ);
	error_def	(ERR_JOBPARNUM);
	error_def	(ERR_JOBPARSTR);

	if ((window_token != TK_IDENT) ||
	    ((x = namelook (job_param_index, job_param_names, window_ident.addr, window_ident.len)) < 0))
	{
		stx_error (ERR_JOBPARUNK);
		return FALSE;
	}
	advancewindow ();
	*(*parptr)++ = job_param_data[x];
	if (job_param_datatypes[job_param_data[x]] != jpdt_nul)
	{
		if (window_token != TK_EQUAL)
		{
			stx_error (ERR_JOBPARVALREQ);
			return FALSE;
		}
		advancewindow ();
		switch (job_param_datatypes[job_param_data[x]])
		{
			case jpdt_num:
				neg = FALSE;
				if (window_token == TK_MINUS && director_token == TK_INTLIT)
				{
					advancewindow();
					neg = TRUE;
				}
				if (window_token != TK_INTLIT)
				{
					stx_error (ERR_JOBPARNUM);
					return FALSE;
				}
				num = MV_FORCE_INTD(&window_mval);
				*((int4 *) (*parptr)) = (neg ? -num : num);
				*parptr += SIZEOF(int4);
				break;
			case jpdt_str:
				if (window_token != TK_STRLIT)
				{
					stx_error (ERR_JOBPARSTR);
					return FALSE;
				}
				len = window_mval.str.len;
				*(*parptr)++ = len;
				memcpy (*parptr, window_mval.str.addr, len);
				*parptr += len;
				break;
			default:
				GTMASSERT;
		}
		advancewindow ();
	} else if (window_token == TK_EQUAL)
	{
		stx_error (ERR_JOBPARNOVAL);
		return FALSE;
	}
	return TRUE;
}
示例#4
0
int m_set(void)
{
	/* Some comment on "parse_warn". It is set to TRUE whenever the parse encounters an
	   invalid setleft target.

	   * Note that even if "parse_warn" is TRUE, we should not return FALSE right away but need to continue the parse
	   * until the end of the current SET command. This way any remaining commands in the current parse line will be
	   * parsed and triples generated for them. This is necessary just in case the currently parsed invalid SET command
	   * does not get executed at runtime (due to postconditionals etc.)
	   *
	   * Some comment on the need for "first_setleft_invalid". This variable is needed only in the
	   * case we encounter an invalid-SVN/invalid-FCN/unsettable-SVN as a target of the SET. We need to evaluate the
	   * right-hand-side of the SET command only if at least one valid setleft target is parsed before an invalid setleft
	   * target is encountered. This is because we still need to execute the valid setlefts at runtime before triggering
	   * a runtime error for the invalid setleft. If the first setleft target is an invalid one, then there is no need
	   * to evaluate the right-hand-side. In fact, in this case, adding triples (corresponding to the right hand side)
	   * to the execution chain could cause problems with emit_code later in the compilation as the destination
	   * for the right hand side triples could now be undefined (for example a valid SVN on the left side of the
	   * SET would have generated an OC_SVPUT triple with one of its operands holding the result of the right
	   * hand side evaluation, but an invalid SVN on the left side which would have instead caused an OC_RTERROR triple
	   * to have been generated leaving no triple to receive the result of the right hand side evaluation thus causing
	   * emit_code to be confused and GTMASSERT). Therefore discard all triples generated by the right hand side in this case.
	   * By the same reasoning, discard all triples generated by setleft targets AFTER this invalid one as well.
	   * "first_setleft_invalid" is set to TRUE if the first setleft target is invalid and set to FALSE if the first setleft
	   * target is valid. It is initialized to -1 before the start of the parse.
	   */

	int		index, setop, delimlen;
	int		first_val_lit, last_val_lit, nakedzalias;
	boolean_t	first_is_lit, last_is_lit, got_lparen, delim1char, is_extract, valid_char;
	boolean_t 	alias_processing, have_lh_alias;
	opctype		put_oc;
	oprtype		v, delimval, firstval, lastval, *result, resptr;
	triple		*curtargchain, *delimiter, discardcurtchain, *first, *get, *jmptrp1, *jmptrp2, *last, *obp, *put;
	triple		*s, *s0, *s1, save_targchain, *save_curtchain, *save_curtchain1, *sub, targchain, *tmp;
	mint		delimlit;
	mval		*delim_mval;
	mvar		*mvarptr;
	boolean_t	parse_warn;	/* set to TRUE in case of an invalid SVN etc. */
	boolean_t	curtchain_switched;	/* set to TRUE if a setcurtchain was done */
	int		first_setleft_invalid;	/* set to TRUE if the first setleft target is invalid */
	boolean_t	temp_subs_was_FALSE;
	union
	{
		uint4		unichar_val;
		unsigned char	unibytes_val[4];
	} unichar;
	DCL_THREADGBL_ACCESS;

	SETUP_THREADGBL_ACCESS;
	TREF(temp_subs) = FALSE;
	dqinit(&targchain, exorder);
	result = (oprtype *)mcalloc(SIZEOF(oprtype));
	resptr = put_indr(result);
	delimiter = sub = last = NULL;
	/* A SET clause must be entirely alias related or a normal set. Parenthized multiple sets of aliases are not allowed
	 * and will trigger an error. This is because the source and targets of aliases require different values and references
	 * than normal sets do and thus cannot be mixed.
	 */
	if (alias_processing = (TK_ASTERISK == window_token))
		advancewindow();
	if (got_lparen = (TK_LPAREN == window_token))
	{
		if (alias_processing)
			stx_error(ERR_NOALIASLIST);
		advancewindow();
		TREF(temp_subs) = TRUE;
	}
	/* Some explanation: The triples from the left hand side of the SET expression that are
	 * expressly associated with fetching (in case of set $piece/$extract) and/or storing of
	 * the target value are removed from curtchain and placed on the targchain. Later, these
	 * triples will be added to the end of curtchain to do the finishing store of the target
	 * after the righthand side has been evaluated. This is per the M standard.
	 *
	 * Note that SET $PIECE/$EXTRACT have special conditions in which the first argument is not referenced at all.
	 * (e.g. set $piece(^a," ",3,2) in this case 3 > 2 so this should not evaluate ^a and therefore should not
	 * modify the naked indicator). That is, the triples that do these conditional checks need to be inserted
	 * ahead of the OC_GVNAME of ^a, all of which need to be inserted on the targchain. But the conditionalization
	 * can be done only after parsing the first argument of the SET $PIECE and examining the remaining arguments.
	 * Therefore we maintain the "curtargchain" variable which stores the value of the "targchain" at the beginning
	 * of the iteration (at the start of the $PIECE parsing) and all the conditionalization will be inserted right
	 * here which is guaranteed to be ahead of where the OC_GVNAME gets inserted.
	 *
	 * For example, SET $PIECE(^A(x,y),delim,first,last)=RHS will generate a final triple chain as follows
	 *
	 *	A - Triples to evaluate subscripts (x,y) of the global ^A
	 *	A - Triples to evaluate delim
	 *	A - Triples to evaluate first
	 *	A - Triples to evaluate last
	 *	B - Triples to evaluate RHS
	 *	C - Triples to do conditional check (e.g. first > last etc.)
	 *	C - Triples to branch around if the checks indicate this is a null operation SET $PIECE
	 *	D - Triple that does OC_GVNAME of ^A
	 *	D - Triple that does OC_SETPIECE to determine the new value
	 *	D - Triple that does OC_GVPUT of the new value into ^A(x,y)
	 *	This is the point where the conditional check triples will branch around to if they chose to.
	 *
	 *	A - triples that evaluates the arguments/subscripts in the left-hand-side of the SET command
	 *		These triples are built in "curtchain"
	 *	B - triples that evaluates the arguments/subscripts in the right-hand-side of the SET command
	 *		These triples are built in "curtchain"
	 *	C - triples that do conditional check for any $PIECE/$EXTRACT in the left side of the SET command.
	 *		These triples are built in "curtargchain"
	 *	D - triples that generate the reference to the target of the SET and the store into the target.
	 *		These triples are built in "targchain"
	 *
	 * Note alias processing does not support the SET *(...)=.. type syntax because the type of argument
	 * created for RHS processing is dependent on the LHS receiver type and we do not support more than one
	 * type of source argument in a single SET.
	 */
	first_setleft_invalid = FIRST_SETLEFT_NOTSEEN;
	curtchain_switched = FALSE;
	nakedzalias = have_lh_alias = FALSE;
	save_curtchain = NULL;
	assert(FIRST_SETLEFT_NOTSEEN != TRUE);
	assert(FIRST_SETLEFT_NOTSEEN != FALSE);
	for (parse_warn = FALSE; ; parse_warn = FALSE)
	{
		curtargchain = targchain.exorder.bl;
		jmptrp1 = jmptrp2 = NULL;
		delim1char = is_extract = FALSE;
		allow_dzwrtac_as_mident();	/* Allows $ZWRTACxxx as target to be treated as an mident */
		switch (window_token)
		{
			case TK_IDENT:
				/* A slight diversion first. If this is a $ZWRTAC set (indication of $ in first char
				 * is currently enough to signify that), then we need to check a few conditions first.
				 * If this is a "naked $ZWRTAC", meaning no numeric suffix, then this is a flag that
				 * all the $ZWRTAC vars in the local variable tree need to be kill *'d which will not
				 * be generating a SET instruction. First we need to verify that fact and make sure
				 * we are not in PARENs and not doing alias processing. Note *any* value can be
				 * specified as the source but while it will be evaluated, it is NOT stored anywhere.
				 */
				if ('$' == *window_ident.addr)
				{	/* We have a $ZWRTAC<xx> target */
					if (got_lparen)
						/* We don't allow $ZWRTACxxx to be specified in a parenthesized list.
						 * Verify that first
						 */
						SYNTAX_ERROR(ERR_DZWRNOPAREN);
					if (STR_LIT_LEN(DOLLAR_ZWRTAC) == window_ident.len)
					{	/* Ok, this is a naked $ZWRTAC targeted set */
						if (alias_processing)
							SYNTAX_ERROR(ERR_DZWRNOALIAS);
						nakedzalias = TRUE;
						/* This opcode doesn't really need args but it is easier to fit in with the rest
						 * of m_set processing to pass it the result arg, which there may actually be
						 * a use for someday..
						 */
						put = maketriple(OC_CLRALSVARS);
						put->operand[0] = resptr;
						dqins(targchain.exorder.bl, exorder, put);
						advancewindow();
						break;
					}
				}
				/* If we are doing alias processing, there are two possibilities:
				 *  1) LHS is unsubscripted - it is an alias variable being created or replaced. Need to parse
				 *  the varname as if this were a regular set.
				 *  2) LHS is subscripted - it is an alias container variable being created or replaced. The
				 *  processing here is to pass the base variable index to the store routine so bypass the
				 *  lvn() call.
				 */
				if (!alias_processing || TK_LPAREN == director_token)
				{	/* Normal variable processing or we have a lh alias container */
					if (!lvn(&v, OC_PUTINDX, 0))
						SYNTAX_ERROR_NOREPORT_HERE;
					if (OC_PUTINDX == v.oprval.tref->opcode)
					{
						dqdel(v.oprval.tref, exorder);
						dqins(targchain.exorder.bl, exorder, v.oprval.tref);
						sub = v.oprval.tref;
						put_oc = OC_PUTINDX;
						if (TREF(temp_subs))
							m_set_create_temporaries(sub, put_oc);
					}
				} else
				{	/* Have alias variable. Argument is index into var table rather than pointer to var */
					have_lh_alias = TRUE;
					/* We only want the variable index in this case. Since the entire hash structure to which
					 * this variable is going to be pointing to is changing, doing anything that calls fetch()
					 * is somewhat pointless so we avoid it by just accessing the variable information
					 * directly.
					 */
					mvarptr = get_mvaddr(&window_ident);
					v = put_ilit(mvarptr->mvidx);
					advancewindow();
				}
				/* Determine correct storing triple */
				put = maketriple((!alias_processing ? OC_STO :
						  (have_lh_alias ? OC_SETALS2ALS : OC_SETALSIN2ALSCT)));
				put->operand[0] = v;
				put->operand[1] = resptr;
				dqins(targchain.exorder.bl, exorder, put);
				break;
			case TK_CIRCUMFLEX:
				if (alias_processing)
					SYNTAX_ERROR(ERR_ALIASEXPECTED);
				s1 = curtchain->exorder.bl;
				if (!gvn())
					SYNTAX_ERROR_NOREPORT_HERE;
				for (sub = curtchain->exorder.bl; sub != s1; sub = sub->exorder.bl)
				{
					put_oc = sub->opcode;
					if (OC_GVNAME == put_oc || OC_GVNAKED == put_oc || OC_GVEXTNAM == put_oc)
						break;
				}
				assert(OC_GVNAME == put_oc || OC_GVNAKED == put_oc || OC_GVEXTNAM == put_oc);
				dqdel(sub, exorder);
				dqins(targchain.exorder.bl, exorder, sub);
				if (TREF(temp_subs))
					m_set_create_temporaries(sub, put_oc);
				put = maketriple(OC_GVPUT);
				put->operand[0] = resptr;
				dqins(targchain.exorder.bl, exorder, put);
				break;
			case TK_ATSIGN:
				if (alias_processing)
					SYNTAX_ERROR(ERR_ALIASEXPECTED);
				if (!indirection(&v))
					SYNTAX_ERROR_NOREPORT_HERE;
				if (!got_lparen && TK_EQUAL != window_token)
				{
					assert(!curtchain_switched);
					put = newtriple(OC_COMMARG);
					put->operand[0] = v;
					put->operand[1] = put_ilit(indir_set);
					return TRUE;
				}
				put = maketriple(OC_INDSET);
				put->operand[0] = v;
				put->operand[1] = resptr;
				dqins(targchain.exorder.bl, exorder, put);
				break;
			case TK_DOLLAR:
				if (alias_processing)
					SYNTAX_ERROR(ERR_ALIASEXPECTED);
				advancewindow();
				if (TK_IDENT != window_token)
					SYNTAX_ERROR(ERR_VAREXPECTED);
				if (TK_LPAREN != director_token)
				{	/* Look for intrinsic special variables */
					s1 = curtchain->exorder.bl;
					if (0 > (index = namelook(svn_index, svn_names, window_ident.addr, window_ident.len)))
					{
						STX_ERROR_WARN(ERR_INVSVN);	/* sets "parse_warn" to TRUE */
					} else if (!svn_data[index].can_set)
					{
						STX_ERROR_WARN(ERR_SVNOSET);	/* sets "parse_warn" to TRUE */
					}
					advancewindow();
					if (!parse_warn)
					{
						if (SV_ETRAP != svn_data[index].opcode && SV_ZTRAP != svn_data[index].opcode)
						{	/* Setting of $ZTRAP or $ETRAP must go through opp_svput because they
							 * may affect the stack pointer. All others directly to op_svput().
							 */
							put = maketriple(OC_SVPUT);
						} else
							put = maketriple(OC_PSVPUT);
						put->operand[0] = put_ilit(svn_data[index].opcode);
						put->operand[1] = resptr;
						dqins(targchain.exorder.bl, exorder, put);
					} else
					{	/* OC_RTERROR triple would have been inserted in curtchain by ins_errtriple
						 * (invoked by stx_error). To maintain consistency with the "if" portion of
						 * this code, we need to move this triple to the "targchain".
						 */
						tmp = curtchain->exorder.bl; /* corresponds to put_ilit(FALSE) in ins_errtriple */
						tmp = tmp->exorder.bl;	/* corresponds to put_ilit(in_error) in ins_errtriple */
						tmp = tmp->exorder.bl;	/* corresponds to newtriple(OC_RTERROR) in ins_errtriple */
						assert(OC_RTERROR == tmp->opcode);
						dqdel(tmp, exorder);
						dqins(targchain.exorder.bl, exorder, tmp);
						CHKTCHAIN(&targchain);
					}
					break;
				}
				/* Only 4 function names allowed on left side: $[Z]Piece and $[Z]Extract */
				index = namelook(fun_index, fun_names, window_ident.addr, window_ident.len);
				if (0 > index)
				{
					STX_ERROR_WARN(ERR_INVFCN);	/* sets "parse_warn" to TRUE */
					/* OC_RTERROR triple would have been inserted in "curtchain" by ins_errtriple
					 * (invoked by stx_error). We need to switch it to "targchain" to be consistent
					 * with every other codepath in this module.
					 */
					tmp = curtchain->exorder.bl; /* corresponds to put_ilit(FALSE) in ins_errtriple */
					tmp = tmp->exorder.bl;	/* corresponds to put_ilit(in_error) in ins_errtriple */
					tmp = tmp->exorder.bl;	/* corresponds to newtriple(OC_RTERROR) in ins_errtriple */
					assert(OC_RTERROR == tmp->opcode);
					dqdel(tmp, exorder);
					dqins(targchain.exorder.bl, exorder, tmp);
					CHKTCHAIN(&targchain);
					advancewindow();	/* skip past the function name */
					advancewindow();	/* skip past the left paren */
					/* Parse the remaining arguments until corresponding RIGHT-PAREN/SPACE/EOL is reached */
					if (!parse_until_rparen_or_space())
						SYNTAX_ERROR_NOREPORT_HERE;
				} else
				{
					switch(fun_data[index].opcode)
					{
						case OC_FNPIECE:
							setop = OC_SETPIECE;
							break;
						case OC_FNEXTRACT:
							is_extract = TRUE;
							setop = OC_SETEXTRACT;
							break;
						case OC_FNZPIECE:
							setop = OC_SETZPIECE;
							break;
						case OC_FNZEXTRACT:
							is_extract = TRUE;
							setop = OC_SETZEXTRACT;
							break;
						default:
							SYNTAX_ERROR(ERR_VAREXPECTED);
					}
					advancewindow();
					advancewindow();
					/* Although we see the get (target) variable first, we need to save it's processing
					 * on another chain -- the targchain -- because the retrieval of the target is bypassed
					 * and the naked indicator is not reset if the first/last parameters are not set in a
					 * logical manner (must be > 0 and first <= last). So the evaluation order is
					 * delimiter (if $piece), first, last, RHS of the set and then the target if applicable.
					 * Set up primary action triple now since it is ref'd by the put triples generated below.
					 */
					s = maketriple(setop);
					/* Even for SET[Z]PIECE and SET[Z]EXTRACT, the SETxxxxx opcodes
					 * do not do the final store, they only create the final value TO be
					 * stored so generate the triples that will actually do the store now.
					 * Note we are still building triples on the original curtchain.
					 */
					switch (window_token)
					{
						case TK_IDENT:
							if (!lvn(&v, OC_PUTINDX, 0))
								SYNTAX_ERROR(ERR_VAREXPECTED);
							if (OC_PUTINDX == v.oprval.tref->opcode)
							{
								dqdel(v.oprval.tref, exorder);
								dqins(targchain.exorder.bl, exorder, v.oprval.tref);
								sub = v.oprval.tref;
								put_oc = OC_PUTINDX;
								if (TREF(temp_subs))
									m_set_create_temporaries(sub, put_oc);
							}
							get = maketriple(OC_FNGET);
							get->operand[0] = v;
							put = maketriple(OC_STO);
							put->operand[0] = v;
							put->operand[1] = put_tref(s);
							break;
						case TK_ATSIGN:
							if (!indirection(&v))
								SYNTAX_ERROR(ERR_VAREXPECTED);
							get = maketriple(OC_INDGET);
							get->operand[0] = v;
							get->operand[1] = put_str(0, 0);
							put = maketriple(OC_INDSET);
							put->operand[0] = v;
							put->operand[1] = put_tref(s);
							break;
						case TK_CIRCUMFLEX:
							s1 = curtchain->exorder.bl;
							if (!gvn())
								SYNTAX_ERROR_NOREPORT_HERE;
							for (sub = curtchain->exorder.bl; sub != s1 ; sub = sub->exorder.bl)
							{
								put_oc = sub->opcode;
								if ((OC_GVNAME == put_oc) || (OC_GVNAKED == put_oc)
								    || (OC_GVEXTNAM == put_oc))
									break;
							}
							assert((OC_GVNAME == put_oc) || (OC_GVNAKED == put_oc)
							       || (OC_GVEXTNAM == put_oc));
							dqdel(sub, exorder);
							dqins(targchain.exorder.bl, exorder, sub);
							if (TREF(temp_subs))
								m_set_create_temporaries(sub, put_oc);
							get = maketriple(OC_FNGVGET);
							get->operand[0] = put_str(0, 0);
							put = maketriple(OC_GVPUT);
							put->operand[0] = put_tref(s);
							break;
						default:
							SYNTAX_ERROR(ERR_VAREXPECTED);
					}
					s->operand[0] = put_tref(get);
					/* Code to fetch args for target triple are on targchain. Put get there now too. */
					dqins(targchain.exorder.bl, exorder, get);
					CHKTCHAIN(&targchain);
					if (!is_extract)
					{	/* Set $[z]piece */
						delimiter = newtriple(OC_PARAMETER);
						s->operand[1] = put_tref(delimiter);
						first = newtriple(OC_PARAMETER);
						delimiter->operand[1] = put_tref(first);
						/* Process delimiter string ($[z]piece only) */
						if (TK_COMMA != window_token)
							SYNTAX_ERROR(ERR_COMMA);
						advancewindow();
						if (!strexpr(&delimval))
							SYNTAX_ERROR_NOREPORT_HERE;
						assert(TRIP_REF == delimval.oprclass);
					} else
					{	/* Set $[Z]Extract */
						first = newtriple(OC_PARAMETER);
						s->operand[1] = put_tref(first);
					}
					/* Process first integer value */
					if (window_token != TK_COMMA)
						firstval = put_ilit(1);
					else
					{
						advancewindow();
						if (!intexpr(&firstval))
							SYNTAX_ERROR(ERR_COMMA);
						assert(firstval.oprclass == TRIP_REF);
					}
					first->operand[0] = firstval;
					if (first_is_lit = (OC_ILIT == firstval.oprval.tref->opcode))
					{
						assert(ILIT_REF ==firstval.oprval.tref->operand[0].oprclass);
						first_val_lit = firstval.oprval.tref->operand[0].oprval.ilit;
					}
					if (TK_COMMA != window_token)
					{	/* There is no "last" value. Only if 1 char literal delimiter and
						 * no "last" value can we generate shortcut code to op_set[z]p1 entry
						 * instead of op_set[z]piece. Note if UTF8 mode is in effect, then this
						 * optimization applies if the literal is one unicode char which may in
						 * fact be up to 4 bytes but will still be passed as a single unsigned
						 * integer.
						 */
						if (!is_extract)
						{
							delim_mval = &delimval.oprval.tref->operand[0].oprval.mlit->v;
							valid_char = TRUE;	/* Basic assumption unles proven otherwise */
							if (delimval.oprval.tref->opcode == OC_LIT &&
							    (1 == (gtm_utf8_mode ?
								   MV_FORCE_LEN(delim_mval) : delim_mval->str.len)))
							{	/* Single char delimiter for set $piece */
								UNICODE_ONLY(
									if (gtm_utf8_mode)
									{	/*  We have a supposed single char delimiter but it
										 *  must be a valid utf8 char to be used by
										 *  op_setp1() and MV_FORCE_LEN won't tell us that.
										 */
										valid_char = UTF8_VALID(delim_mval->str.addr,
													(delim_mval->str.addr
													 + delim_mval->str.len),
													delimlen);
										if (!valid_char && !badchar_inhibit)
											UTF8_BADCHAR(0, delim_mval->str.addr,
												     (delim_mval->str.addr
												      + delim_mval->str.len),
												     0, NULL);
									}
									     );
								if (valid_char || 1 == delim_mval->str.len)
								{	/* This reference to a one character literal or a single
									 * byte invalid utf8 character that needs to be turned into
									 * an explict formated integer literal instead
									 */
									unichar.unichar_val = 0;
									if (!gtm_utf8_mode)
									{	/* Single byte delimiter */
										assert(1 == delim_mval->str.len);
										UNIX_ONLY(s->opcode = OC_SETZP1);
										VMS_ONLY(s->opcode = OC_SETP1);
										unichar.unibytes_val[0] = *delim_mval->str.addr;
									}
									UNICODE_ONLY(
								        else
									{	/* Potentially multiple bytes in one int */
										assert(SIZEOF(int) >= delim_mval->str.len);
										memcpy(unichar.unibytes_val,
										       delim_mval->str.addr,
										       delim_mval->str.len);
										s->opcode = OC_SETP1;
									}
										     );
									delimlit = (mint)unichar.unichar_val;
									delimiter->operand[0] = put_ilit(delimlit);
									delim1char = TRUE;
								}
							}
						}
示例#5
0
int m_new(void)
{
	oprtype		tmparg;
	triple		*ref, *next, *org, *tmp, *s, *fetch;
	int		n;
	int		count;
	mvar		*var;
	boolean_t	parse_warn;
	DCL_THREADGBL_ACCESS;

	SETUP_THREADGBL_ACCESS;
	switch (window_token)
	{
		case TK_IDENT:
			var = get_mvaddr(&window_ident);
			if (var->last_fetch != curr_fetch_trip)
			{
				fetch = newtriple(OC_PARAMETER);
				curr_fetch_opr->operand[1] = put_tref(fetch);
				fetch->operand[0] = put_ilit(var->mvidx);
				curr_fetch_count++;
				curr_fetch_opr = fetch;
				var->last_fetch = curr_fetch_trip;
			}
			tmp = maketriple(OC_NEWVAR);
			tmp->operand[0] = put_ilit(var->mvidx);
			ins_triple(tmp);
			advancewindow();
			return TRUE;
		case TK_ATSIGN:
			if (!indirection(&tmparg))
				return FALSE;
			ref = maketriple(OC_COMMARG);
			ref->operand[0] = tmparg;
			ref->operand[1] = put_ilit((mint) indir_new);
			ins_triple(ref);
			start_fetches(OC_FETCH);
			return TRUE;
		case TK_DOLLAR:
			advancewindow();
			if (TK_IDENT == window_token)
			{
				parse_warn = FALSE;
				if ((n = namelook(svn_index, svn_names, window_ident.addr, window_ident.len)) >= 0)
				{
					switch(svn_data[n].opcode)
					{
						case SV_ZTRAP:
						case SV_ETRAP:
						case SV_ESTACK:
						case SV_ZYERROR:
						case SV_ZGBLDIR:
						GTMTRIG_ONLY(case SV_ZTWORMHOLE:)
							tmp = maketriple(OC_NEWINTRINSIC);
							tmp->operand[0] = put_ilit(svn_data[n].opcode);
							break;
						default:
							STX_ERROR_WARN(ERR_SVNONEW);	/* sets "parse_warn" to TRUE */
					}
				} else
				{
					STX_ERROR_WARN(ERR_INVSVN);	/* sets "parse_warn" to TRUE */
				}
				advancewindow();
				if (!parse_warn)
					ins_triple(tmp);
				else
				{	/* OC_RTERROR triple would have been inserted in curtchain by ins_errtriple
					 * (invoked by stx_error). No need to do anything else.
					 */
					assert(OC_RTERROR == curtchain->exorder.bl->exorder.bl->exorder.bl->opcode);
				}
				return TRUE;
			}
示例#6
0
void iott_use(io_desc *iod, mval *pp)
{
	boolean_t		flush_input;
	char			dc1, *ttab;
	d_tt_struct		*temp_ptr, *tt_ptr;
	int			p_offset, fil_type, save_errno, status;
	int4			length, width;
	io_desc			*d_in, *d_out;
	io_termmask		mask_term;
	struct sigaction	act;
	struct termios		t;
	uint4			mask_in;
	unsigned char		ch, len;
	boolean_t		ch_set;

	p_offset = 0;
	assert(iod->state == dev_open);
	ESTABLISH_GTMIO_CH(&iod->pair, ch_set);
	iott_flush(iod);
	tt_ptr = (d_tt_struct *)iod->dev_sp;
	if (*(pp->str.addr + p_offset) != iop_eol)
	{
		if (tt_ptr->mupintr)
			if (dollar_zininterrupt)
				rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_ZINTRECURSEIO);
			else
			{	/* The interrupted read was not properly resumed so clear it now */
				tt_ptr->mupintr = FALSE;
				tt_ptr->tt_state_save.who_saved = ttwhichinvalid;
				io_find_mvstent(iod, TRUE);
			}
		status = tcgetattr(tt_ptr->fildes, &t);
		if (0 != status)
		{
			save_errno = errno;
			ISSUE_NOPRINCIO_IF_NEEDED_TT(io_curr_device.out);
			rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_TCGETATTR, 1, tt_ptr->fildes, save_errno);
		}
		flush_input = FALSE;
		d_in = iod->pair.in;
		d_out = iod->pair.out;
		temp_ptr = (d_tt_struct *)d_in->dev_sp;
		mask_in = temp_ptr->term_ctrl;
		mask_term = temp_ptr->mask_term;
		while (*(pp->str.addr + p_offset) != iop_eol)
		{
			switch (ch = *(pp->str.addr + p_offset++))
			{
				case iop_canonical:
					tt_ptr->canonical = TRUE;
					t.c_lflag |= ICANON;
					break;
				case iop_nocanonical:
					tt_ptr->canonical = FALSE;
					t.c_lflag &= ~(ICANON);
					break;
				case iop_empterm:
					tt_ptr->ext_cap |= TT_EMPTERM;
					break;
				case iop_noempterm:
					tt_ptr->ext_cap &= ~TT_EMPTERM;
					break;
				case iop_cenable:
					if (!ctrlc_on)
					{	/* if it's already cenable, no need to change */
						temp_ptr = (d_tt_struct *)io_std_device.in->dev_sp;
						if (tt_ptr->fildes == temp_ptr->fildes)
						{	/* if this is $PRINCIPAL make sure the ctrlc_handler is enabled */
							sigemptyset(&act.sa_mask);
							act.sa_flags = 0;
							act.sa_handler = ctrlc_handler_ptr;
							sigaction(SIGINT, &act, 0);
							ctrlc_on = TRUE;
						}
					}
					break;
				case iop_nocenable:
					if (ctrlc_on)
					{	/* if it's already nocenable, no need to change */
						temp_ptr = (d_tt_struct *)io_std_device.in->dev_sp;
						if (tt_ptr->fildes == temp_ptr->fildes)
						{	/* if this is $PRINCIPAL may disable the ctrlc_handler */
							if (0 == (CTRLC_MSK & tt_ptr->enbld_outofbands.mask))
							{	/* but only if ctrap=$c(3) is not active */
								sigemptyset(&act.sa_mask);
								act.sa_flags = 0;
								act.sa_handler = SIG_IGN;
								sigaction(SIGINT, &act, 0);
							}
							ctrlc_on = FALSE;
						}
					}
					break;
				case iop_clearscreen:
					if (NULL != CLR_EOS)
						gtm_tputs(CLR_EOS, 1, outc);
					break;
				case iop_convert:
					mask_in |= TRM_CONVERT;
					break;
				case iop_noconvert:
					mask_in &= ~TRM_CONVERT;
					break;
				case iop_ctrap:
					GET_LONG(tt_ptr->enbld_outofbands.mask, pp->str.addr + p_offset);
					if (!ctrlc_on)
					{	/* if cenable, ctrlc_handler active anyway, otherwise, depends on ctrap=$c(3) */
						sigemptyset(&act.sa_mask);
						act.sa_flags = 0;
						act.sa_handler = (CTRLC_MSK & tt_ptr->enbld_outofbands.mask)
							? ctrlc_handler_ptr : SIG_IGN;
						sigaction(SIGINT, &act, 0);
					}
					break;
				case iop_downscroll:
					if (d_out->dollar.y > 0)
					{
						d_out->dollar.y--;
						if (NULL != CURSOR_ADDRESS)
							gtm_tputs(gtm_tparm(CURSOR_ADDRESS, d_out->dollar.y, d_out->dollar.x), 1,
								  outc);
					}
					break;
				case iop_echo:
					mask_in &= (~TRM_NOECHO);
					break;
				case iop_noecho:
					mask_in |= TRM_NOECHO;
					break;
				case iop_editing:
					if (io_curr_device.in == io_std_device.in)
					{	/* $PRINCIPAL only */
						tt_ptr->ext_cap |= TT_EDITING;
						if (!tt_ptr->recall_buff.addr)
						{
							assert(tt_ptr->in_buf_sz);
							tt_ptr->recall_buff.addr = malloc(tt_ptr->in_buf_sz);
							tt_ptr->recall_size = tt_ptr->in_buf_sz;
							tt_ptr->recall_buff.len = 0;    /* nothing in buffer */
						}
					}
					break;
				case iop_noediting:
					if (io_curr_device.in == io_std_device.in)
						tt_ptr->ext_cap &= ~TT_EDITING;	/* $PRINCIPAL only */
					break;
				case iop_escape:
					mask_in |= TRM_ESCAPE;
					break;
				case iop_noescape:
					mask_in &= (~TRM_ESCAPE);
					default:
					break;
				case iop_eraseline:
					if (NULL != CLR_EOL)
						gtm_tputs(CLR_EOL, 1, outc);
					break;
				case iop_exception:
					iod->error_handler.len = *(pp->str.addr + p_offset);
					iod->error_handler.addr = (char *)(pp->str.addr + p_offset + 1);
					s2pool(&iod->error_handler);
					break;
				case iop_filter:
					len = *(pp->str.addr + p_offset);
					ttab = pp->str.addr + p_offset + 1;
					if ((fil_type = namelook(filter_index, filter_names, ttab, len)) < 0)
					{
						rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_TTINVFILTER);
						return;
					}
					switch (fil_type)
					{
					case 0:
						iod->write_filter |= CHAR_FILTER;
						break;
					case 1:
						iod->write_filter |= ESC1;
						break;
					case 2:
						iod->write_filter &= ~CHAR_FILTER;
						break;
					case 3:
						iod->write_filter &= ~ESC1;
						break;
					}
					break;
				case iop_nofilter:
					iod->write_filter = 0;
					break;
				case iop_flush:
					flush_input = TRUE;
					break;
				case iop_hostsync:
					t.c_iflag |= IXOFF;
					break;
				case iop_nohostsync:
					t.c_iflag &= ~IXOFF;
					break;
				case iop_insert:
					if (io_curr_device.in == io_std_device.in)
						tt_ptr->ext_cap &= ~TT_NOINSERT;	/* $PRINCIPAL only */
					break;
				case iop_noinsert:
					if (io_curr_device.in == io_std_device.in)
						tt_ptr->ext_cap |= TT_NOINSERT;	/* $PRINCIPAL only */
					break;
				case iop_length:
					GET_LONG(length, pp->str.addr + p_offset);
					if (0 > length)
						rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_DEVPARMNEG);
					d_out->length = length;
					break;
				case iop_pasthru:
					mask_in |= TRM_PASTHRU;
					break;
				case iop_nopasthru:
					mask_in &= (~TRM_PASTHRU);
					break;
				case iop_readsync:
					mask_in |= TRM_READSYNC;
					break;
				case iop_noreadsync:
					dc1 = (char)17;
					temp_ptr = (d_tt_struct *)io_std_device.in->dev_sp;
					DOWRITERC(temp_ptr->fildes, &dc1, 1, status);
					if (0 != status)
						rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) status);
					mask_in &= (~TRM_READSYNC);
					break;
				case iop_terminator:
					memcpy(&mask_term.mask[0], (pp->str.addr + p_offset), SIZEOF(io_termmask));
					temp_ptr = (d_tt_struct *)d_in->dev_sp;
					if (mask_term.mask[0] == NUL &&
						mask_term.mask[1] == NUL &&
						mask_term.mask[2] == NUL &&
						mask_term.mask[3] == NUL &&
						mask_term.mask[4] == NUL &&
						mask_term.mask[5] == NUL &&
						mask_term.mask[6] == NUL &&
						mask_term.mask[7] == NUL)
					{
						temp_ptr->default_mask_term = TRUE;
						if (CHSET_UTF8 == d_in->ichset)
						{
							mask_term.mask[0] = TERM_MSK_UTF8_0;
							mask_term.mask[4] = TERM_MSK_UTF8_4;
						} else
							mask_term.mask[0] = TERM_MSK;
					} else
						temp_ptr->default_mask_term = FALSE;
						break;
				case iop_noterminator:
					temp_ptr = (d_tt_struct *)d_in->dev_sp;
					temp_ptr->default_mask_term = FALSE;
					memset(&mask_term.mask[0], 0, SIZEOF(io_termmask));
					break;
				case iop_ttsync:
					t.c_iflag |= IXON;
					break;
				case iop_nottsync:
					t.c_iflag &= ~IXON;
					break;
				case iop_typeahead:
					mask_in &= (~TRM_NOTYPEAHD);
					break;
				case iop_notypeahead:
					mask_in |= TRM_NOTYPEAHD;
					break;
				case iop_upscroll:
					d_out->dollar.y++;
					if (d_out->length)
						d_out->dollar.y %= d_out->length;
					if (NULL != CURSOR_ADDRESS)
						gtm_tputs(gtm_tparm(CURSOR_ADDRESS, d_out->dollar.y, d_out->dollar.x), 1, outc);
					break;
				case iop_width:
					GET_LONG(width, pp->str.addr + p_offset);
					if (0 > width)
						rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_DEVPARMNEG);
					/* Do not allow a WIDTH of 1 if UTF mode (ICHSET or OCHSET is not M) */
					if ((1 == width) && ((CHSET_M != d_in->ochset) || (CHSET_M != d_in->ichset)))
						rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_WIDTHTOOSMALL);
					if (0 == width)
					{
						d_out->wrap = FALSE;
						d_out->width = TTDEF_PG_WIDTH;
					} else
					{
						d_out->width = width;
						d_out->wrap = TRUE;
					}
					break;
				case iop_wrap:
					d_out->wrap = TRUE;
					break;
				case iop_nowrap:
					d_out->wrap = FALSE;
					break;
				case iop_x:
					GET_LONG(d_out->dollar.x, pp->str.addr + p_offset);
					if (0 > (int4)d_out->dollar.x)
						d_out->dollar.x = 0;
					if (d_out->dollar.x > d_out->width && d_out->wrap)
					{
						d_out->dollar.y += (d_out->dollar.x / d_out->width);
						if (d_out->length)
							d_out->dollar.y %= d_out->length;
						d_out->dollar.x	%= d_out->width;
					}
					if (NULL != CURSOR_ADDRESS)
						gtm_tputs(gtm_tparm(CURSOR_ADDRESS, d_out->dollar.y, d_out->dollar.x), 1, outc);
					break;
				case iop_y:
					GET_LONG(d_out->dollar.y, pp->str.addr + p_offset);
					if (0 > (int4)d_out->dollar.y)
						d_out->dollar.y = 0;
					if (d_out->length)
						d_out->dollar.y %= d_out->length;
					if (NULL != CURSOR_ADDRESS)
						gtm_tputs(gtm_tparm(CURSOR_ADDRESS, d_out->dollar.y, d_out->dollar.x), 1, outc);
					break;
				case iop_ipchset:
					{
#						ifdef KEEP_zOS_EBCDIC
						if ( (iconv_t)0 != iod->input_conv_cd )
						{
							ICONV_CLOSE_CD(iod->input_conv_cd);
						}
						SET_CODE_SET(iod->in_code_set, (char *)(pp->str.addr + p_offset + 1));
						if (DEFAULT_CODE_SET != iod->in_code_set)
							ICONV_OPEN_CD(iod->input_conv_cd,
								(char *)(pp->str.addr + p_offset + 1), INSIDE_CH_SET);
#						endif
						break;
					}
				case iop_opchset:
					{
#						ifdef KEEP_zOS_EBCDIC
						if ( (iconv_t)0 != iod->output_conv_cd)
						{
							ICONV_CLOSE_CD(iod->output_conv_cd);
						}
						SET_CODE_SET(iod->out_code_set, (char *)(pp->str.addr + p_offset + 1));
						if (DEFAULT_CODE_SET != iod->out_code_set)
							ICONV_OPEN_CD(iod->output_conv_cd, INSIDE_CH_SET,
								(char *)(pp->str.addr + p_offset + 1));
#						endif
						break;
					}
			}
			p_offset += ((IOP_VAR_SIZE == io_params_size[ch]) ?
				(unsigned char)*(pp->str.addr + p_offset) + 1 : io_params_size[ch]);
		}
		temp_ptr = (d_tt_struct *)d_in->dev_sp;
		Tcsetattr(tt_ptr->fildes, TCSANOW, &t, status, save_errno);
		if (0 != status)
			rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_TCSETATTR, 1, tt_ptr->fildes, save_errno);
		temp_ptr->term_ctrl = mask_in;
		memcpy(&temp_ptr->mask_term, &mask_term, SIZEOF(io_termmask));
		if (flush_input)
		{
			TCFLUSH(tt_ptr->fildes, TCIFLUSH, status);
			if (0 != status)
				rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, LIT_AND_LEN("tcflush input"),
					CALLFROM, errno);
		}
	} else if (tt_ptr->mupintr && !dollar_zininterrupt)
	{	/* The interrupted read was not properly resumed so clear it now */
		tt_ptr->mupintr = FALSE;
		tt_ptr->tt_state_save.who_saved = ttwhichinvalid;
		io_find_mvstent(iod, TRUE);	/* clear mv stack entry */
	}
	REVERT_GTMIO_CH(&iod->pair, ch_set);
	return;
}
示例#7
0
short iomt_open(io_log_name *dev_name, mval *pp, int fd, mval *mspace, int4 timeout)
{
	bool		do_rewind, do_erase;
	int		lab_type;
	unsigned char	ch, *buff, len;
	int4		blocksize, recordsize, length;
	uint4		status;
	d_mt_struct	*mt, newmt;
	iosb		io_status_blk;
	io_desc		*ioptr;
	mident		tab;
	int		p_offset;

	error_def(ERR_MTRECTOOBIG);
	error_def(ERR_MTRECGTRBLK);
	error_def(ERR_MTBLKTOOBIG);
	error_def(ERR_MTBLKTOOSM);
	error_def(ERR_MTFIXRECSZ);
	error_def(ERR_MTRECTOOSM);
	error_def(ERR_VARRECBLKSZ);
	error_def(ERR_MTINVLAB);
	error_def(ERR_MTDOSFOR);
	error_def(ERR_MTANSIFOR);
	error_def(ERR_MTIS);
	error_def(ERR_DEVPARMNEG);
	error_def(ERR_MTIOERR);

#ifdef DP
	FPRINTF(stderr, ">> iomt_open(%d)\n", fd);
#endif
	ioptr = dev_name->iod;
	buff = 0;
	memset(&newmt, 0, sizeof(newmt));	/* zero structure to start */
	if (ioptr->state == dev_never_opened)
		ioptr->dev_sp = (void *)(malloc(sizeof(d_mt_struct)));
	mt = (d_mt_struct *)dev_name->iod->dev_sp;
	if (ioptr->state == dev_open && mt->buffer)
	{
		if (mt->bufftoggle < 0)
			buff = (mt->buffer + mt->bufftoggle);
		else
			buff = (mt->buffer);
	}
	do_rewind = do_erase = FALSE;
	if (ioptr->state == dev_never_opened)
	{
		length = DEF_MT_LENGTH;
		newmt.read_mask = IO_READLBLK;
		newmt.write_mask = IO_WRITELBLK;
		newmt.block_sz = MTDEF_BUF_SZ;
		newmt.record_sz = MTDEF_REC_SZ;
		newmt.ebcdic = FALSE;
		newmt.labeled = FALSE;
		newmt.fixed = FALSE;
		newmt.stream = FALSE;
		newmt.read_only = FALSE;
		newmt.newversion = FALSE;
		newmt.last_op = mt_null;
		newmt.wrap = TRUE;
	} else
	{
		length = ioptr->length;
		newmt = *mt;
	}
	p_offset = 0;
	while (*(pp->str.addr + p_offset) != iop_eol)
	{
		switch (ch = *(pp->str.addr + p_offset++))
		{
		case iop_blocksize:
			GET_LONG(blocksize, (pp->str.addr + p_offset));
			if (blocksize < 0)
				rts_error(VARLSTCNT(1) ERR_DEVPARMNEG);
			if (blocksize > MAX_BLK_SZ)
				rts_error(VARLSTCNT(1) ERR_MTBLKTOOBIG);
			newmt.block_sz = blocksize;
			break;
		case iop_recordsize:
			GET_LONG(recordsize, (pp->str.addr + p_offset));
			if (recordsize < 0)
				rts_error(VARLSTCNT(1) ERR_DEVPARMNEG);
			if (recordsize > MAX_REC_SZ)
				rts_error(VARLSTCNT(1) ERR_MTRECTOOBIG);
			newmt.record_sz = recordsize;
			break;
		case iop_rewind:
			do_rewind = TRUE;
			break;
		case iop_erasetape:
			do_erase = TRUE;
			break;
		case iop_newversion:
			newmt.newversion = TRUE;
			break;
		case iop_readonly:
			newmt.read_only = TRUE;
			break;
		case iop_noreadonly:
			newmt.read_only = FALSE;
			break;
		case iop_ebcdic:
			newmt.ebcdic = TRUE;
			break;
		case iop_noebcdic:
			newmt.ebcdic = FALSE;
			break;
		case iop_nolabel:
			newmt.labeled = FALSE;
			break;
		case iop_label:
			memset(&tab, 0, sizeof(mident));
			len = *(pp->str.addr + p_offset);
			memcpy(&tab.c[0], (pp->str.addr + p_offset + 1), (len < sizeof(mident) ? len : sizeof(mident)));
			if ((lab_type = namelook(mtlab_index, mtlab_names, tab.c)) < 0)
			{
				iomt_closesp(fd);
				rts_error(VARLSTCNT(1) ERR_MTINVLAB);
				return FALSE;
			}
			newmt.labeled = mtlab_type[lab_type];
			break;
		case iop_fixed:
			newmt.fixed = TRUE;
			break;
		case iop_nofixed:
			newmt.fixed = FALSE;
			break;
		case iop_rdcheckdata:
			newmt.read_mask |= IO_M_DATACHECK;
			break;
		case iop_nordcheckdata:
			newmt.read_mask &= (~(IO_M_DATACHECK));
			break;
		case iop_wtcheckdata:
			newmt.write_mask |= IO_M_DATACHECK;
			break;
		case iop_nowtcheckdata:
			newmt.write_mask &= (~(IO_M_DATACHECK));
			break;
		case iop_inhretry:
			newmt.write_mask |= IO_M_INHRETRY;
			newmt.read_mask |= IO_M_INHRETRY;
			break;
		case iop_retry:
			newmt.write_mask &= ~IO_M_INHRETRY;
			newmt.read_mask &= ~IO_M_INHRETRY;
			break;
		case iop_inhextgap:
			newmt.write_mask |= IO_M_INHEXTGAP;
			break;
		case iop_extgap:
			newmt.write_mask &= ~IO_M_INHEXTGAP;
			break;
		case iop_stream:
			newmt.stream = TRUE;
			break;
		case iop_nostream:
			newmt.stream = FALSE;
			break;
		case iop_wrap:
			newmt.wrap = TRUE;
			break;
		case iop_nowrap:
			newmt.wrap = FALSE;
			break;
		case iop_length:
			GET_LONG(length, (pp->str.addr + p_offset));
			if (length < 0)
			{
				iomt_closesp(fd);
				rts_error(VARLSTCNT(1) ERR_DEVPARMNEG);
			}
			break;
		case iop_exception:
			ioptr->error_handler.len = *(pp->str.addr + p_offset);
			ioptr->error_handler.addr = (char *)(pp->str.addr + p_offset + 1);
			s2pool(&ioptr->error_handler);
			break;
		default:
			break;
		}
		p_offset += ((IOP_VAR_SIZE == io_params_size[ch]) ?
			(unsigned char)*(pp->str.addr + p_offset) + 1 : io_params_size[ch]);
	}
	if (newmt.labeled == MTLAB_DOS11)
	{
		if (!newmt.stream)
		{
			iomt_closesp(fd);
			rts_error(VARLSTCNT(6) ERR_MTDOSFOR, 0, ERR_MTIS, 2,
			ioptr->trans_name->len, ioptr->trans_name->dollar_io);
		}
	}
	if (newmt.labeled == MTLAB_ANSI)
	{
		if (newmt.stream)
		{
			iomt_closesp(fd);
			rts_error(VARLSTCNT(6) ERR_MTANSIFOR, 0, ERR_MTIS, 2,
			ioptr->trans_name->len, ioptr->trans_name->dollar_io);
		}
	}
	if (newmt.stream)
	{
		newmt.wrap = TRUE;
		newmt.fixed = FALSE;
	}
	if (newmt.fixed)
	{
		if (newmt.record_sz < MIN_FIXREC_SZ)
		{
			iomt_closesp(fd);
			rts_error(VARLSTCNT(1) ERR_MTRECTOOSM);
		}
		if (newmt.block_sz / newmt.record_sz * newmt.record_sz != newmt.block_sz)
		{
			iomt_closesp(fd);
			rts_error(VARLSTCNT(3) ERR_MTFIXRECSZ, newmt.block_sz, newmt.record_sz);
		}
	} else
	{
		if (newmt.record_sz > MAX_VARREC_SZ)
		{
			iomt_closesp(fd);
			rts_error(VARLSTCNT(1) ERR_MTRECTOOBIG);
		}
		if (newmt.record_sz < MIN_VARREC_SZ)
		{
			iomt_closesp(fd);
			rts_error(VARLSTCNT(1) ERR_MTRECTOOSM);
		}
		if ((int)newmt.block_sz < (int)newmt.record_sz + (newmt.stream ? 2 : VREC_HDR_LEN))
		{
			iomt_closesp(fd);
			rts_error(VARLSTCNT(1) ERR_VARRECBLKSZ);
		}
	}
	if (newmt.record_sz > newmt.block_sz)
	{
		iomt_closesp(fd);
		rts_error(VARLSTCNT(1) ERR_MTRECGTRBLK);
	}
	if (ioptr->state != dev_open)
	{
		newmt.filepos = newmt.recpos = 0;
		newmt.mode = MT_M_READ;
		newmt.access_id = fd;
		/* get mag tape characteristics */
		if (!iomt_info(&newmt))
		{
			status = errno;
			iomt_closesp(fd);
			rts_error(VARLSTCNT(5) ERR_MTIOERR, 2, ioptr->trans_name->len, ioptr->trans_name->dollar_io, status);
		}
	}
	if ((int4)newmt.block_sz < newmt.cap.block_size)
	{
		iomt_closesp(fd);
		rts_error(VARLSTCNT(3) ERR_MTBLKTOOSM, 1,
			(int4)newmt.cap.block_size);
	}
	if (newmt.fixed)
	{
		newmt.buffer = (unsigned char *)malloc(newmt.block_sz);
		newmt.bufftoggle = 0;
	} else
	{
		newmt.buffer = (unsigned char *)malloc(newmt.block_sz * 2);
		newmt.bufftoggle = newmt.block_sz;
	}
	if (buff)
		free(buff);
	newmt.bufftop = newmt.buffptr = newmt.buffer;
	newmt.last_op = mt_null;
	ioptr->state = dev_open;
	*mt = newmt;
	ioptr->width = newmt.record_sz;
	ioptr->length = length;
	ioptr->dollar.zeof = FALSE;
	ioptr->dollar.x = 0;
	ioptr->dollar.y = 0;
	if (do_erase)
		iomt_erase(ioptr);
	if (do_rewind)
		iomt_rewind(ioptr);
	if (mt->labeled)
	{
		status = iomt_sense(mt, &io_status_blk);
		if (status != SS_NORMAL)
		{
			ioptr->dollar.za = 9;
			iomt_closesp(fd);
			rts_error(VARLSTCNT(5) status,
				ERR_MTIS, 2, ioptr->trans_name->len, ioptr->trans_name->dollar_io);
		}
		if (io_status_blk.dev_dep_info & MT_M_BOT)
			mt->last_op = mt_rewind;
	}
#ifdef DP
	FPRINTF(stderr, "<< iomt_open\n");
#endif
	return TRUE;
}
示例#8
0
void ionl_use(io_desc *iod, mval *pp)
{
	unsigned char	ch, len;
	int		fil_type;
	int4		width, length;
	io_desc		*d_in, *d_out;
	mident		tab;
	int		p_offset;

	error_def(ERR_TTINVFILTER);
	error_def(ERR_DEVPARMNEG);

	p_offset = 0;
	d_in = iod->pair.in;
	d_out = iod->pair.out;
	assert(iod->state == dev_open);
	while (*(pp->str.addr + p_offset) != iop_eol)
	{
		switch (ch = *(pp->str.addr + p_offset++))
		{
		case iop_exception:
			iod->error_handler.len = *(pp->str.addr + p_offset);
			iod->error_handler.addr = (char *)(pp->str.addr + p_offset + 1);
			s2pool(&iod->error_handler);
			break;
		case iop_filter:
			memset(&tab, 0, sizeof(mident));
			len = *(pp->str.addr + p_offset);
			memcpy(&tab.c[0], pp->str.addr + p_offset + 1, (len < sizeof(mident) ? len : sizeof(mident)));
			if ((fil_type = namelook(filter_index, filter_names, tab.c)) < 0)
			{
				rts_error(VARLSTCNT(1) ERR_TTINVFILTER);
				return;
			}
			switch (fil_type)
			{
				case 0:
					iod->write_filter |= CHAR_FILTER;
					break;
				case 1:
					iod->write_filter |= ESC1;
					break;
				case 2:
					iod->write_filter &= ~CHAR_FILTER;
					break;
				case 3:
					iod->write_filter &= ~ESC1;
					break;
			}
			break;
		case iop_nofilter:
			iod->write_filter = 0;
			break;
		case iop_length:
			GET_LONG(length, pp->str.addr + p_offset);
			if (length < 0)
				rts_error(VARLSTCNT(1) ERR_DEVPARMNEG);
			d_out->length = length;
			break;
		case iop_width:
			GET_LONG(width, pp->str.addr + p_offset);
			if (width < 0)
				rts_error(VARLSTCNT(1) ERR_DEVPARMNEG);
			if (width == 0)
			{
				d_out->wrap = FALSE;
				d_out->width = TTDEF_PG_WIDTH;
			}
			else
			{
				d_out->width = width;
				d_out->wrap = TRUE;
			}
			break;
		case iop_wrap:
			d_out->wrap = TRUE;
			break;
		case iop_nowrap:
			d_out->wrap = FALSE;
			break;
		case iop_x:
		{
			int4 col;

			GET_LONG(col, pp->str.addr + p_offset);
			d_out->dollar.x = col;
			if ((d_out->dollar.x) < 0)
				d_out->dollar.x = 0;
			if (d_out->dollar.x > d_out->width && d_out->wrap)
				d_out->dollar.x %= d_out->width;
			break;
		}
		case iop_y:
		{
			int4 row;

			GET_LONG(row, (pp->str.addr + p_offset));
			d_out->dollar.y = row;
			if ((d_out->dollar.y) < 0)
				d_out->dollar.y = 0;
			if (d_out->length)
				d_out->dollar.y %= d_out->length;
			break;
		}
		case iop_ipchset:
			{
				if ( (iconv_t)0 != iod->input_conv_cd )
				{
					ICONV_CLOSE_CD(iod->input_conv_cd);
				}
				SET_CODE_SET(iod->in_code_set, (char *)(pp->str.addr + p_offset + 1));
				if (DEFAULT_CODE_SET != iod->in_code_set)
					ICONV_OPEN_CD(iod->input_conv_cd, (char *)(pp->str.addr + p_offset + 1), INSIDE_CH_SET);
                        	break;
			}
                case iop_opchset:
			{
				if ( (iconv_t) 0 != iod->output_conv_cd )
				{
					ICONV_CLOSE_CD(iod->output_conv_cd);
				}
				SET_CODE_SET(iod->out_code_set, (char *)(pp->str.addr + p_offset + 1));
				if (DEFAULT_CODE_SET != iod->out_code_set)
					ICONV_OPEN_CD(iod->output_conv_cd, INSIDE_CH_SET, (char *)(pp->str.addr + p_offset + 1));
                        	break;
			}
		}
		p_offset += ((IOP_VAR_SIZE == io_params_size[ch]) ?
			(unsigned char)*(pp->str.addr + p_offset) + 1 : io_params_size[ch]);
	}
	return;
}
示例#9
0
int m_new(void)
{
	oprtype tmparg;
	triple *ref, *next, *org, *tmp, *s, *fetch;
	int n;
	int count;
	mvar *var;
	error_def(ERR_INVSVN);
	error_def(ERR_RPARENMISSING);
	error_def(ERR_VAREXPECTED);

	switch (window_token)
	{
		case TK_IDENT:
			var = get_mvaddr(&window_ident);
			if (var->last_fetch != curr_fetch_trip)
			{
				fetch = newtriple(OC_PARAMETER);
				curr_fetch_opr->operand[1] = put_tref(fetch);
				fetch->operand[0] = put_ilit(var->mvidx);
				curr_fetch_count++;
				curr_fetch_opr = fetch;
				var->last_fetch = curr_fetch_trip;
			}
			tmp = maketriple(OC_NEWVAR);
			tmp->operand[0] = put_ilit(var->mvidx);
			ins_triple(tmp);
			advancewindow();
			return TRUE;
		case TK_ATSIGN:
			if (!indirection(&tmparg))
				return FALSE;
			ref = maketriple(OC_COMMARG);
			ref->operand[0] = tmparg;
			ref->operand[1] = put_ilit((mint) indir_new);
			ins_triple(ref);
			start_fetches(OC_FETCH);
			return TRUE;
		case TK_DOLLAR:
			advancewindow();
			if (window_token == TK_IDENT)
				if ((n = namelook(svn_index, svn_names, window_ident.c)) >= 0)
				{
					tmp = maketriple(OC_NEWINTRINSIC);
					switch(svn_data[n].opcode)
					{
						case SV_ZTRAP:
						case SV_ETRAP:
						case SV_ESTACK:
						case SV_ZYERROR:
						case SV_ZGBLDIR:
							tmp->operand[0] = put_ilit(svn_data[n].opcode);
							break;
						default:
							stx_error(ERR_INVSVN);
							return FALSE;
					}
					advancewindow();
					ins_triple(tmp);
					return TRUE;
				}
			stx_error(ERR_INVSVN);
			return FALSE;
		case TK_EOL:
		case TK_SPACE:
			tmp = maketriple(OC_XNEW);
			tmp->operand[0] = put_ilit((mint) 0);
			ins_triple(tmp);
			if (for_stack_ptr == for_stack)
				start_fetches (OC_FETCH);
			else
				start_for_fetches ();
			return TRUE;
		case TK_LPAREN:
			ref = org = maketriple(OC_XNEW);
			count = 0;
			do
			{
				advancewindow();
				next = maketriple(OC_PARAMETER);
				ref->operand[1] = put_tref(next);
				switch (window_token)
				{
				case TK_IDENT:
					next->operand[0] = put_str(&window_ident.c[0],sizeof(mident));
					advancewindow();
					break;
				case TK_ATSIGN:
					if (!indirection(&tmparg))
						return FALSE;
					s = newtriple(OC_INDLVARG);
					s->operand[0] = tmparg;
					next->operand[0] = put_tref(s);
					break;
				default:
					stx_error(ERR_VAREXPECTED);
					return FALSE;
				}
				ins_triple(next);
				ref = next;
				count++;
			} while (window_token == TK_COMMA);
			if (window_token != TK_RPAREN)
			{
				stx_error(ERR_RPARENMISSING);
				return FALSE;
			}
			advancewindow();
			org->operand[0] = put_ilit((mint) count);
			ins_triple(org);
			if (for_stack_ptr == for_stack)
				start_fetches (OC_FETCH);
			else
				start_for_fetches ();
			return TRUE;
		default:
			stx_error(ERR_VAREXPECTED);
			return FALSE;
	}
}