/* returns the truth value based on the sense indicated by 'negate'. * If negate is FALSE (i.e. in regular mode), * returns TRUE if the env variable/logical log is defined and evaluates to "TRUE" (or part thereof), * or "YES" (or part thereof), or a non zero integer * returns FALSE otherwise * If negate is TRUE(i.e. in negative mode), * returns TRUE if the env variable/logical log is defined and evaluates to "FALSE" (or part thereof), * or "NO" (or part thereof), or a zero integer * returns FALSE otherwise */ boolean_t logical_truth_value(mstr *log, boolean_t negate, boolean_t *is_defined) { int4 status; mstr tn; char buf[1024]; boolean_t zero, is_num; int index; error_def(ERR_LOGTOOLONG); error_def(ERR_TRNLOGFAIL); tn.addr = buf; if (NULL != is_defined) *is_defined = FALSE; if (SS_NORMAL == (status = TRANS_LOG_NAME(log, &tn, buf, SIZEOF(buf), dont_sendmsg_on_log2long))) { if (NULL != is_defined) *is_defined = TRUE; if (tn.len <= 0) return FALSE; for (is_num = TRUE, zero = TRUE, index = 0; index < tn.len; index++) { if (!ISDIGIT_ASCII(buf[index])) { is_num = FALSE; break; } zero = (zero && ('0' == buf[index])); } if (!negate) { /* regular mode */ return (!is_num ? (0 == STRNCASECMP(buf, LOGICAL_TRUE, MIN(STR_LIT_LEN(LOGICAL_TRUE), tn.len)) || 0 == STRNCASECMP(buf, LOGICAL_YES, MIN(STR_LIT_LEN(LOGICAL_YES), tn.len))) : !zero); } else { /* negative mode */ return (!is_num ? (0 == STRNCASECMP(buf, LOGICAL_FALSE, MIN(STR_LIT_LEN(LOGICAL_FALSE), tn.len)) || 0 == STRNCASECMP(buf, LOGICAL_NO, MIN(STR_LIT_LEN(LOGICAL_NO), tn.len))) : zero); } } else if (SS_NOLOGNAM == status) return (FALSE); # ifdef UNIX else if (SS_LOG2LONG == status) { rts_error(VARLSTCNT(5) ERR_LOGTOOLONG, 3, log->len, log->addr, SIZEOF(buf) - 1); return (FALSE); } # endif else { rts_error(VARLSTCNT(5) ERR_TRNLOGFAIL, 2, log->len, log->addr, status); return (FALSE); } }
STATICFNDEF boolean_t process_pieces(char *piece_str, uint4 *piece_len) { uint bit; uint4 bitmap[MAX_PIECE_INT]; uint bitval; uint bitword; boolean_t have_low_num; boolean_t have_num; boolean_t have_num_in_str; uint i; uint4 len; int low; int num; char *ptr; char *ptr1; boolean_t have_error = FALSE; int num_len; memset((void *)bitmap, 0, MAX_PIECE_CHARS); ptr = piece_str; len = *piece_len; have_num = have_low_num = FALSE; if ('"' == *ptr) { ptr++; len--; } while ((0 < len) && !have_error) { switch (*ptr) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': ptr1 = ptr; A2I(ptr1, ptr + len, num); if ((0 == num) || (MAX_PIECE_VALUE < num)) { CONV_NUM_AND_STR_AND_PRINT("Invalid value !UL in PIECES - !AD", num, *piece_len, piece_str); have_error = TRUE; break; } len -= (int)(ptr1 - ptr); ptr = ptr1; bitmap[num / BITS_PER_INT] |= 1 << (num % BITS_PER_INT); have_num = TRUE; have_low_num = TRUE; break; case ';': if (!have_num) { CONV_STR_AND_PRINT("Expected an integer in PIECES - ", *piece_len, piece_str); have_error = TRUE; break; } have_num = FALSE; ptr++; len--; break; case ':': if (!have_low_num) { CONV_STR_AND_PRINT("Expected an integer for lower value in range in PIECES - ", *piece_len, piece_str); have_error = TRUE; break; } ptr++; len--; low = num; if (!ISDIGIT_ASCII(*ptr)) { CONV_STR_AND_PRINT("Expected an integer for upper value in range in PIECES - ", *piece_len, piece_str); have_error = TRUE; break; } ptr1 = ptr; A2I(ptr1, ptr + len, num); if (MAX_PIECE_VALUE < num) { CONV_NUM_AND_STR_AND_PRINT("Invalid value \"!UL\" in PIECES - !AD", num, *piece_len, piece_str); have_error = TRUE; break; } if (num <= low) { CONV_STR_AND_PRINT("Low value of range not less than high value in PIECES - ", *piece_len, piece_str); have_error = TRUE; break; } len -= (int)(ptr1 - ptr); ptr = ptr1; for (i = low + 1; i <= num; i++) bitmap[i / BITS_PER_INT] |= 1 << (i % BITS_PER_INT); have_num = TRUE; have_low_num = FALSE; break; case '"': if (1 == len) { len--; break; } default: CONV_CH_AND_STR_AND_PRINT("Invalid character !AD in PIECES - !AD", ptr, *piece_len, piece_str); have_error = TRUE; break; } } if ((0 != len) || !have_num || have_error) { if (!have_error) CONV_STR_AND_PRINT("Invalid PIECE entry - ", *piece_len, piece_str); return FALSE; } have_num = have_low_num = have_num_in_str = FALSE; ptr = piece_str; len = 0; for (i = 0; i < MAX_PIECE_INT; i++) { if ((0 == bitmap[i] && !have_low_num)) continue; bitword = bitmap[i]; bit = 0; while ((0 != bitword) || have_low_num) { bitval = bitword & 1; if (!have_low_num) { if (0 == bitval) { bitword = bitword >> 1; bit++; continue; } have_num = TRUE; have_low_num = TRUE; low = i * BITS_PER_INT + bit; if (have_num_in_str) { *ptr++ = ';'; len++; } num_len = 0; I2A(ptr, num_len, low); len += num_len; ptr += num_len; have_num_in_str = TRUE; } while ((1 == bitval) && (BITS_PER_INT > bit)) { bitword = bitword >> 1; bitval = bitword & 1; bit++; } if (BITS_PER_INT == bit) break; num = (0 == bit) ? i * BITS_PER_INT - 1 : i * BITS_PER_INT + bit - 1; have_low_num = FALSE; if (num == low) continue; *ptr++ = ':'; len++; num_len = 0; I2A(ptr, num_len, num); len += num_len; ptr += num_len; } }
STATICFNDEF boolean_t process_subscripts(char *subscr_str, uint4 *subscr_len, char **next_str, char *out_str, int4 *out_max) { boolean_t alternation; char dst[MAX_GVSUBS_LEN]; int dst_len; char *dst_ptr; int len; boolean_t have_pattern; boolean_t have_range; boolean_t have_star; boolean_t have_dot; int i; int lvn_count; uint4 lvn_len[MAX_LVN_COUNT]; char *lvn_start; char *lvn_str[MAX_LVN_COUNT]; int multiplier; boolean_t newsub; int num1; int num2; char *ptr; char *ptr1; char *save_dst_ptr; int save_len; char *start_dst_ptr; uint4 start_len; uint4 subsc_count; uint4 tmp_len; boolean_t valid_sub; have_pattern = have_range = valid_sub = have_star = FALSE; ptr = subscr_str; start_len = len = *subscr_len; dst_len = 0; newsub = TRUE; subsc_count = lvn_count = 0; start_dst_ptr = dst_ptr = dst; while ((0 < len) && (')' != *ptr)) { if (ISDIGIT_ASCII(*ptr) || ('-' == *ptr)) { PROCESS_NUMERIC(ptr, len, have_star, dst_ptr, dst_len, MAX_GVSUBS_LEN); newsub = FALSE; valid_sub = TRUE; } else if (ISALPHA_ASCII(*ptr) || ('%' == *ptr)) { if (!newsub) { util_out_print_gtmio("Invalid subscript", FLUSH); return FALSE; } lvn_start = ptr; tmp_len = 0; do { if (MAX_MIDENT_LEN < ++tmp_len) { util_out_print_gtmio("Variable name too long", FLUSH); return FALSE; } if (MAX_GVSUBS_LEN < ++dst_len) { util_out_print_gtmio("Subscript too long", FLUSH); return FALSE; } *dst_ptr++ = *ptr++; len--; } while (ISALNUM_ASCII(*ptr)); if ('=' != *ptr) { util_out_print_gtmio("Invalid variable name in subscript", FLUSH); return FALSE; } for (i = 0; i < lvn_count; i++) { if ((lvn_len[i] == tmp_len) && (0 == strncmp(lvn_str[i], lvn_start, tmp_len))) { util_out_print_gtmio("Duplicate variable name in subscript", FLUSH); return FALSE; } } lvn_str[lvn_count] = lvn_start; lvn_len[lvn_count] = tmp_len; lvn_count++; if (MAX_GVSUBS_LEN < ++dst_len) { util_out_print_gtmio("Subscript too long", FLUSH); return FALSE; } *dst_ptr++ = *ptr++; /* move past = */ start_dst_ptr = dst_ptr; len--; if ((0 < len) && ((',' == *ptr) || (')' == *ptr))) { util_out_print_gtmio("Variable name not followed by valid subscript", FLUSH); return FALSE; } continue; } else { switch (*ptr) { case '"': PROCESS_STRING(ptr, len, have_star, dst_ptr, dst_len, MAX_GVSUBS_LEN); valid_sub = TRUE; newsub = FALSE; break; case '$': if (!process_dollar_char(&ptr, &len, have_star, &dst_ptr, &dst_len)) { util_out_print_gtmio("Invalid subscript", FLUSH); return FALSE; } newsub = FALSE; valid_sub = TRUE; break; case '?': if (have_range) { util_out_print_gtmio("Range and pattern match not valid in same subscript", FLUSH); return FALSE; } UPDATE_DST(ptr, len, have_star, dst_ptr, dst_len, MAX_GVSUBS_LEN); ptr1 = ptr; alternation = FALSE; while ((0 < len) && ((',' != *ptr) || alternation) && ((')' != *ptr) || alternation) && (';' != *ptr)) { num1 = num2 = -1; have_dot = FALSE; if (ISDIGIT_ASCII(*ptr)) { PROCESS_AND_GET_NUMERIC(ptr, len, have_star, dst_ptr, dst_len, num1, MAX_GVSUBS_LEN); } if ('.' == *ptr) { have_dot = TRUE; if (MAX_GVSUBS_LEN < ++dst_len) { util_out_print_gtmio("Subscript too long", FLUSH); return FALSE; } *dst_ptr++ = *ptr++; len--; if (ISDIGIT_ASCII(*ptr)) { PROCESS_AND_GET_NUMERIC(ptr, len, have_star, dst_ptr, dst_len, num2, MAX_GVSUBS_LEN); } if (-1 == num1) num1 = 0; } switch (*ptr) { case '(': if (!alternation && (0 <= num1)) { UPDATE_DST(ptr, len, have_star, dst_ptr, dst_len, MAX_GVSUBS_LEN); alternation = TRUE; continue; } break; case ',': if (alternation && (-1 == num1) && (-1 == num2)) { UPDATE_DST(ptr, len, have_star, dst_ptr, dst_len, MAX_GVSUBS_LEN); continue; } break; case ')': if (alternation && (-1 == num1) && (-1 == num2)) { UPDATE_DST(ptr, len, have_star, dst_ptr, dst_len, MAX_GVSUBS_LEN); alternation = FALSE; continue; } break; default: break; } if ((0 <= num1) && (0 <= num2) && (num2 < num1)) { util_out_print_gtmio("Invalid pattern match range", FLUSH); return FALSE; } switch (TOUPPER(*ptr)) { case 'E': if (have_dot && (0 >= num1) && (-1 == num2)) { /* Treat ?.E the same as * */ have_star = TRUE; dst_ptr = start_dst_ptr; if (MAX_GVSUBS_LEN < ++dst_len) { util_out_print_gtmio("Subscript too long", FLUSH); return FALSE; } *dst_ptr++ = '*'; } /* Note: we're dropping into the following case */ case 'A': case 'C': case 'K': case 'L': case 'N': case 'P': case 'U': case 'V': UPDATE_DST(ptr, len, have_star, dst_ptr, dst_len, MAX_GVSUBS_LEN); break; case '"': PROCESS_STRING(ptr, len, have_star, dst_ptr, dst_len, MAX_GVSUBS_LEN); break; /* Note: we're dropping into the default/error case */ default: CONV_CH_AND_PRINT("Unexpected character !AD in pattern code", ptr); return FALSE; } } have_pattern = TRUE; valid_sub = TRUE; newsub = FALSE; break; case ':': if (have_range) { util_out_print_gtmio("Range within a range not allowed", FLUSH); return FALSE; } if (have_pattern) { util_out_print_gtmio("Pattern not allowed as a range", FLUSH); return FALSE; } UPDATE_DST(ptr, len, have_star, dst_ptr, dst_len, MAX_GVSUBS_LEN); if (ISDIGIT_ASCII(*ptr) || ('-' == *ptr)) { PROCESS_NUMERIC(ptr, len, have_star, dst_ptr, dst_len, MAX_GVSUBS_LEN); } else if ('"' == *ptr) { PROCESS_STRING(ptr, len, have_star, dst_ptr, dst_len, MAX_GVSUBS_LEN); } else if ('$' == *ptr) { if (!process_dollar_char(&ptr, &len, have_star, &dst_ptr, &dst_len)) { util_out_print_gtmio("Invalid range value", FLUSH); return FALSE; } } else if ((0 < len) && (',' != *ptr) && (';' != *ptr) && (')' != *ptr)) { util_out_print_gtmio("Invalid string range", FLUSH); return FALSE; } else { /* A range with no lower end - just scan the numeric or string */ ptr1 = ptr; if (ISDIGIT_ASCII(*ptr) || ('-' == *ptr)) { PROCESS_NUMERIC(ptr, len, have_star, dst_ptr, dst_len, MAX_GVSUBS_LEN); } else if ('"' == *ptr1) { PROCESS_STRING(ptr, len, have_star, dst_ptr, dst_len, MAX_GVSUBS_LEN); } else if ((0 < len) && ((',' != *ptr) && (';' != *ptr) && (')' != *ptr))) { util_out_print_gtmio("Range value must be integer or string", FLUSH); return FALSE; } else if (!valid_sub) { /* this is a single ":" - treat it just like a * */ have_star = TRUE; dst_ptr = start_dst_ptr; if (MAX_GVSUBS_LEN < ++dst_len) { util_out_print_gtmio("Subscript too long", FLUSH); return FALSE; } *dst_ptr++ = '*'; } } valid_sub = TRUE; newsub = FALSE; have_range = TRUE; break; case '*': if (!have_star) { have_star = TRUE; dst_ptr = start_dst_ptr; if (MAX_GVSUBS_LEN < ++dst_len) { util_out_print_gtmio("Subscript too long", FLUSH); return FALSE; } *dst_ptr++ = '*'; } ptr++; len--; if ((0 < len) && (',' != *ptr) && (';' != *ptr) && (')' != *ptr)) { util_out_print_gtmio("Invalid use of *", FLUSH); return FALSE; } else valid_sub = TRUE; newsub = FALSE; break; case ';': UPDATE_DST(ptr, len, have_star, dst_ptr, dst_len, MAX_GVSUBS_LEN); /* Delete extraneous ; in the subscript */ if ((!have_star) && (newsub || ((0 < len) && ((',' == *ptr) || (';' == *ptr) || ISALPHA_ASCII(*ptr) || ('%' == *ptr) || (')' == *ptr))))) dst_ptr--; valid_sub = FALSE; have_pattern = have_range = FALSE; break; case ',': if (newsub) { util_out_print_gtmio("Empty subscript not allowed", FLUSH); return FALSE; } if (MAX_GVSUBSCRIPTS <= ++subsc_count) { util_out_print_gtmio("Too many subscripts", FLUSH); return FALSE; } if (MAX_GVSUBS_LEN < ++dst_len) { util_out_print_gtmio("Subscript too long", FLUSH); return FALSE; } *dst_ptr++ = *ptr++; len--; start_dst_ptr = dst_ptr; newsub = TRUE; have_range = have_pattern = valid_sub = have_star = FALSE; break; default: CONV_CH_AND_PRINT("Invalid character !AD in subscript", ptr); return FALSE; } } } if ((0 == len) && (')' != *ptr)) { util_out_print_gtmio("Missing \")\" after global subscript", FLUSH); return FALSE; } if ((start_len == len) || newsub) { util_out_print_gtmio("Empty subscript not allowed", FLUSH); return FALSE; } if ((')' == *ptr) && (MAX_GVSUBSCRIPTS <= ++subsc_count)) { util_out_print_gtmio("Too many subscripts", FLUSH); return FALSE; } CHECK_FOR_ROOM_IN_OUTPUT_AND_COPY(dst, out_str, (int)(dst_ptr - dst), *out_max); *subscr_len = (uint4)(dst_ptr - dst); *next_str = ptr + 1; return TRUE; }
int gtcm_bgn_net(omi_conn_ll *cll) { extern int4 omi_nxact, omi_nerrs, omi_brecv, omi_bsent; omi_fd fd; int i; int save_errno; int rc; #ifdef NET_TCP struct servent *se; unsigned short port; char port_buffer[NI_MAXSERV]; #endif /* defined(NET_TCP) */ #ifdef BSD_TCP struct addrinfo *ai_ptr, hints; const boolean_t reuseaddr = TRUE; int errcode; #else /* defined(BSD_TCP) */ #ifdef SYSV_TCP struct t_bind *bind; #endif /* defined(SYSV_TCP) */ #endif /* !defined(BSD_TCP) */ /* The linked list of connections */ cll->head = cll->tail = (omi_conn *)0; /* The statistics */ cll->stats.conn = cll->stats.clos = cll->stats.disc = 0; cll->st_cn.bytes_recv = 0; cll->st_cn.bytes_send = 0; cll->st_cn.start = 0; for (i = 0; i < OMI_OP_MAX; i++) cll->st_cn.xact[i] = 0; for (i = 0; i < OMI_ER_MAX; i++) cll->st_cn.errs[i] = 0; omi_nxact = omi_nerrs = omi_brecv = omi_bsent = 0; /* Fall back on a compile time constant */ if (!omi_service) omi_service = SRVC_NAME; #ifdef NET_TCP /* NET_TCP is defined only when BSD_TCP is defined or SYSV_TCP is defined, but SYSV_TCP is never defined (a bug?) * so we move the code of obtaining port information from service down to #ifdef BSD_TCP */ #ifdef SYSV_TCP GTMASSERT; #endif #endif /* defined(NET_TCP) */ #ifdef BSD_TCP /* Create a socket always tries IPv6 first */ SERVER_HINTS(hints, ((GTM_IPV6_SUPPORTED && !ipv4_only) ? AF_INET6 : AF_INET)); if ((fd = socket(hints.ai_family, SOCK_STREAM, 0)) < 0) { if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { save_errno = errno; return save_errno; } hints.ai_family = AF_INET; } /* Bind an address to the socket */ if (0 != (errcode = getaddrinfo(NULL, omi_service, &hints, &ai_ptr))) { RTS_ERROR_ADDRINFO(NULL, ERR_GETADDRINFO, errcode); return errcode; } if (ISDIGIT_ASCII(*omi_service)) port = atoi(omi_service); else { if (0 != (errcode = getnameinfo(ai_ptr->ai_addr, ai_ptr->ai_addrlen, NULL, 0, port_buffer, NI_MAXSERV, NI_NUMERICSERV))) { assert(FALSE); RTS_ERROR_ADDRINFO(NULL, ERR_GETNAMEINFO, errcode); return errcode; } port = atoi(port_buffer); } /* Reuse a specified address */ if (port && setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&reuseaddr, SIZEOF(reuseaddr)) < 0) { save_errno = errno; CLOSEFILE_RESET(fd, rc); /* resets "fd" to FD_INVALID */ return save_errno; } if (bind(fd, ai_ptr->ai_addr, ai_ptr->ai_addrlen) < 0) { save_errno = errno; CLOSEFILE_RESET(fd, rc); /* resets "fd" to FD_INVALID */ return save_errno; } /* Initialize the listen queue */ if (listen(fd, 5) < 0) { save_errno = errno; CLOSEFILE_RESET(fd, rc); /* resets "fd" to FD_INVALID */ return save_errno; } /* set up raw socket for use with pinging option */ if (ping_keepalive) psock = init_ping(); /* Store the file descriptor away for use later */ cll->nve = fd; OMI_DBG_STMP; OMI_DBG((omi_debug, "%s: socket registered at port %d\n", SRVR_NAME, (int)port)); #ifdef GTCM_RC OMI_DBG((omi_debug, "RC server ID %d, Process ID %d\n", rc_server_id, omi_pid)); #endif if (authenticate) OMI_DBG((omi_debug, "Password verification on OMI connections enabled.\n")); if (!one_conn_per_inaddr) OMI_DBG((omi_debug, "Multiple connections from the same internet address allowed.\n")); if (psock > 0) OMI_DBG((omi_debug, "Keepalive option (-ping) enabled.\n")); return 0; #else /* defined(BSD_TCP) */ #ifdef SYSV_TCP GTMASSERT; if ((fd = t_open(SYSV_TCP, O_RDWR, NULL)) < 0) { save_errno = errno; return save_errno; } if (!(bind = (struct t_bind *)t_alloc(fd, T_BIND, T_ALL))) { save_errno = errno; (void) t_close(fd); return save_errno; } bind->qlen = 5; bind->addr.len = 0; bind->addr.buf = 0; if (t_bind(fd, bind, bind) < 0) { save_errno = errno; (void) t_free(bind, T_BIND); (void) t_close(fd); return save_errno; } /* Store the file descriptor away for use later */ cll->nve = fd; OMI_DBG_STMP; OMI_DBG((omi_debug, "%s: socket registered at port %d\n", SRVR_NAME, (int)port)); #ifdef GTCM_RC OMI_DBG((omi_debug, "RC server ID %d\n", rc_server_id)); #endif return 0; #else /* defined(SYSV_TCP) */ cll->nve = FD_INVALID; return -1; #endif /* !defined(SYSV_TCP) */ #endif /* !defined(BSD_TCP) */ }
/* given the bounds of a particular subscript (assumed correct), we convert the subscript into * a form that mimics the GDS representation of that subscript */ boolean_t convert_key_to_db(mval *gvn, int start, int stop, gv_key *gvkey, unsigned char **key) { mval tmpval, *mvptr, dollarcharmval; int isrc; char strbuff[MAX_KEY_SZ + 1], *str, *str_top; char fnname[MAX_LEN_FOR_CHAR_FUNC], *c; boolean_t is_zchar; int4 num; DCL_THREADGBL_ACCESS; SETUP_THREADGBL_ACCESS; if (ISDIGIT_ASCII(gvn->str.addr[start]) || '-' == gvn->str.addr[start] || '+' == gvn->str.addr[start] || '.' == gvn->str.addr[start]) { /* convert a number */ tmpval.str.addr = &gvn->str.addr[start]; tmpval.str.len = stop - start; tmpval.mvtype = MV_STR; mvptr = &tmpval; MV_FORCE_NUM(mvptr); if (MVTYPE_IS_NUM_APPROX(tmpval.mvtype)) return FALSE; mval2subsc(&tmpval, gvkey, gv_cur_region->std_null_coll); } else { /* It's a string. We need to accept strings, $CHAR args, and $ZCHAR args. */ str = &strbuff[0]; str_top = &strbuff[0] + MAX_KEY_SZ + 1; /* MV_NUM_APPROX needed by mval2subsc to skip val_iscan call */ tmpval.mvtype = (MV_STR | MV_NUM_APPROX); for (isrc = start; isrc < stop; ) { if ('_' == gvn->str.addr[isrc]) { /* We can skip this case, since we're already "appending" * the strings on the lhs to the string on the rhs. */ isrc++; } else if ('$' == gvn->str.addr[isrc]) { /* We determine if what comes after is a Char or a ZCHar, * and copy over accordingly */ c = &fnname[0]; isrc++; /* skip the '$' */ while ('(' != gvn->str.addr[isrc]) *c++ = TOUPPER(gvn->str.addr[isrc++]); *c = '\0'; assert(strlen(c) <= MAX_LEN_FOR_CHAR_FUNC - 1); if (!MEMCMP_LIT(fnname, "ZCHAR") || !MEMCMP_LIT(fnname, "ZCH")) is_zchar = TRUE; else if (!MEMCMP_LIT(fnname, "CHAR") || !MEMCMP_LIT(fnname, "C")) is_zchar = FALSE; else assert(FALSE); /* Parse the arguments */ isrc++; /* skip the '(' */ while (TRUE) { /* Inside the argument list for $[Z]CHAR */ /* STRTOUL will stop at the ',' or ')' */ num = (int4)STRTOUL(&gvn->str.addr[isrc], NULL, 10); # ifdef UNICODE_SUPPORTED if (!is_zchar && is_gtm_chset_utf8) op_fnchar(2, &dollarcharmval, num); else # endif op_fnzchar(2, &dollarcharmval, num); assert(MV_IS_STRING(&dollarcharmval)); if (dollarcharmval.str.len) { if (str + dollarcharmval.str.len > str_top) /* String overflows capacity. */ return FALSE; memcpy(str, dollarcharmval.str.addr, dollarcharmval.str.len); str += dollarcharmval.str.len; } /* move on to the next argument */ while (',' != gvn->str.addr[isrc] && ')' != gvn->str.addr[isrc]) isrc++; if (',' == gvn->str.addr[isrc]) isrc++; else { assert(')' == gvn->str.addr[isrc]); isrc++; /* skip ')' */ break; } } } else if ('"' == gvn->str.addr[isrc]) { /* Assume valid string. */ isrc++; while (isrc < stop && !('"' == gvn->str.addr[isrc] && '"' != gvn->str.addr[isrc+1])) { if (str == str_top) /* String overflows capacity. */ return FALSE; if ('"' == gvn->str.addr[isrc] && '"' == gvn->str.addr[isrc+1]) { *str++ = '"'; isrc += 2; } else *str++ = gvn->str.addr[isrc++]; } isrc++; /* skip over '"' */ } else assert(FALSE); } tmpval.str.addr = strbuff; tmpval.str.len = str - strbuff; DEBUG_ONLY(TREF(skip_mv_num_approx_assert) = TRUE;) mval2subsc(&tmpval, gvkey, gv_cur_region->std_null_coll); DEBUG_ONLY(TREF(skip_mv_num_approx_assert) = FALSE;) }
boolean_t str2gvargs(char *cp, int len, gvargs_t *op_gvargs) { /* IMPORTANT : op_gvargs will point to static area which gets overwritten by the next call to this function. Callers should make a copy of op_gvargs if necessary */ char *p1, *p2, *c_top, *c_ref, ch, *subsc_ptr, *dstptr, *strnext; int count; mval *spt; int chcode, chtmp; mstr_len_t chlen; boolean_t naked, concat, dot_seen, dollarzch, isdolar; error_def(ERR_NOTGBL); error_def(ERR_GVINVALID); error_def(ERR_LPARENREQD); error_def(ERR_NUMUNXEOR); error_def(ERR_STRUNXEOR); error_def(ERR_DLRCUNXEOR); error_def(ERR_DLRCTOOBIG); error_def(ERR_EORNOTFND); error_def(ERR_RPARENREQD); error_def(ERR_DLRCILLEGAL); assert(SIZEOF(op_gvargs->count) == SIZEOF(op_gvargs->args[0])); naked = FALSE; concat = FALSE; c_ref = cp; c_top = cp + len; assert(0 < len); /* why is our code calling with "" string? */ if (len > subsc_buffer.len) { if (NULL != subsc_buffer.addr) free(subsc_buffer.addr); subsc_buffer.len = (ZWR_EXP_RATIO(MAX_KEY_SZ) < len ? len : ZWR_EXP_RATIO(MAX_KEY_SZ)); subsc_buffer.addr = malloc(subsc_buffer.len); } spt = subsc; count = 0; if (0 >= len || '^' != *cp++) rts_error(VARLSTCNT(4) ERR_NOTGBL, 2, (len > 0) ? len : 0, c_ref); spt->mvtype = MV_STR; spt->str.addr = cp; ch = *cp; if ('(' == ch) { spt->str.len = INTCAST(cp - spt->str.addr - 1); naked = TRUE; } else { cp++; if (!(VALFIRSTCHAR_WITH_TRIG(ch))) rts_error(VARLSTCNT(4) ERR_GVINVALID, 2, len, c_ref); for ( ; cp < c_top && *cp != '('; ) { ch = *cp++; if (!ISALPHA_ASCII(ch) && !ISDIGIT_ASCII(ch)) rts_error(VARLSTCNT(4) ERR_GVINVALID, 2, len, c_ref); } spt->str.len = INTCAST(cp - spt->str.addr); op_gvargs->args[count] = spt; count++; spt++; } subsc_ptr = subsc_buffer.addr; if (cp < c_top) { if ('(' != *cp++) rts_error(VARLSTCNT(4) ERR_LPARENREQD, 2, len, c_ref); for (; ;) { spt->mvtype = MV_STR; ch = *cp; if ('\"' == ch) { if (!concat) { spt->str.addr = subsc_ptr; p1 = subsc_ptr; } else p2 = p1; ++cp; for (; ;) { if (cp == c_top) rts_error(VARLSTCNT(4) ERR_STRUNXEOR, 2, len, c_ref); if ('\"' == *cp) if ('\"' != *++cp) break; *p1++ = *cp++; } if (!concat) { spt->str.len = INTCAST(p1 - spt->str.addr); subsc_ptr = p1; } else { spt->str.len += (mstr_len_t)(p1 - p2); subsc_ptr += p1 - p2; } if ('_' == *cp) { cp++; concat = TRUE; continue; } } else if ('$' == ch) { cp++; chtmp = toupper(*cp); isdolar = (3 <= c_top - cp && 'C' == chtmp || '(' == cp[1]); if (!isdolar) isdolar = (5 <= c_top - cp && 'Z' == chtmp && 'C' == cp[1] && 'H' == cp[2] && '(' == cp[3]); if (!isdolar) rts_error(VARLSTCNT(4) ERR_DLRCUNXEOR, 2, len, c_ref); if ('Z' == chtmp) { dollarzch = TRUE; cp += 4; } else { dollarzch = FALSE; cp += 2; } for (; ;) { A2I(cp, c_top, chcode); if (0 > chcode) rts_error(VARLSTCNT(4) ERR_DLRCUNXEOR, 2, len, c_ref); dstptr = (!concat) ? subsc_ptr : p1; if (!gtm_utf8_mode || dollarzch) { if (255 < chcode) { if (dollarzch) rts_error(VARLSTCNT(6) ERR_DLRCTOOBIG, 4, len, c_ref, LEN_AND_LIT("$CHAR()")); else rts_error(VARLSTCNT(6) ERR_DLRCTOOBIG, 4, len, c_ref, LEN_AND_LIT("$ZCHAR()")); } *dstptr = chcode; chlen = 1; } #ifdef UNICODE_SUPPORTED else { strnext = (char *)UTF8_WCTOMB(chcode, dstptr); chlen = INTCAST(strnext - dstptr); if (0 == chlen) rts_error(VARLSTCNT(5) ERR_DLRCILLEGAL, 3, len, c_ref, chcode); } #endif if (!concat) { spt->str.addr = subsc_ptr; spt->str.len = chlen; subsc_ptr += chlen; p1 = subsc_ptr; } else { p1 += chlen; spt->str.len += chlen; subsc_ptr += chlen; } if (',' == *cp) { concat = TRUE; if (++cp == c_top) rts_error(VARLSTCNT(4) ERR_DLRCUNXEOR, 2, len, c_ref); continue; } if (')' != *cp) rts_error(VARLSTCNT(4) ERR_DLRCUNXEOR, 2, len, c_ref); break; } cp++; if ('_' == *cp) { cp++; concat = TRUE; continue; } } else { dot_seen = FALSE; if (!ISDIGIT_ASCII(ch) && '.' != ch && '-' != ch && '+' != ch) rts_error(VARLSTCNT(4) ERR_NUMUNXEOR, 2, len, c_ref); if (!concat) { spt->str.addr = subsc_ptr; p1 = subsc_ptr; } else p2 = p1; *p1++ = *cp++; for (; ;) { if (cp == c_top) rts_error(VARLSTCNT(4) ERR_NUMUNXEOR, 2, len, c_ref); if (!ISDIGIT_ASCII(*cp)) { if ('.' != *cp) break; else if (!dot_seen) dot_seen = TRUE; else rts_error(VARLSTCNT(4) ERR_NUMUNXEOR, 2, len, c_ref); } *p1++ = *cp++; } if (!concat) { spt->str.len = INTCAST(p1 - spt->str.addr); subsc_ptr = p1; } else { spt->str.len += (mstr_len_t)(p1 - p2); subsc_ptr += p1 - p2; } if ('_' == *cp) { cp++; concat = TRUE; continue; } } op_gvargs->args[count] = spt; count++; spt++; if (',' != *cp) break; concat = FALSE; cp++; } if (')' != *cp++) rts_error(VARLSTCNT(4) ERR_RPARENREQD, 2, len, c_ref); if (cp < c_top) rts_error(VARLSTCNT(4) ERR_EORNOTFND, 2, len, c_ref); } op_gvargs->count = count; return naked; }