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]); } }
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; }
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; }
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; } } }
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; }
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; }
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; }
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; }
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; } }