int get_config(char *file, struct config **complete_config) { size_t buffer_len = 80; char *line_buffer; struct config *server_config; FILE *fh; int return_value = 0; unsigned int line_number = 0; line_buffer = (char *) malloc(buffer_len); if (0 == line_buffer) return -1; fh = fopen(file, "r"); if (0 == fh) { return_value = -1; goto ret; } server_config = (struct config *) malloc(sizeof(struct config)); if (0 == server_config) { return_value = -1; goto ret; } while ( getline(&line_buffer, &buffer_len, fh) > 0 ) { char *tokptr; line_number += 1; if (1 == line_number) { /* First line is how many servers total */ server_config->num_servers = atoi(line_buffer); server_config->servers = (struct server_info *) malloc(server_config->num_servers * sizeof(struct server_info)); continue; } /* Address entry */ tokptr = (char *) strtok(line_buffer, ":"); server_config->servers[line_number - 2].address = copy_token(tokptr); /* Port number entry */ tokptr = strtok(NULL, ":"); server_config->servers[line_number - 2].port = copy_token(tokptr); server_config->servers[line_number - 2].socket_fd = 0; } *complete_config = server_config; ret: fclose(fh); free(line_buffer); return return_value; }
static enum proto_parse_status tns_parse_connect(struct tns_parser unused_ *tns_parser, struct sql_proto_info *info, struct cursor *cursor) { if (! info->is_query) return PROTO_PARSE_ERR; SLOG(LOG_DEBUG, "Parsing TNS connect PDU of size %zu", cursor->cap_len); /* A connect is (in network byte order) : * - 2 bytes version * - 2 bytes back compatibility * - 2 bytes service options * - 2 bytes session data unit size * - 2 bytes max transm. data unit size * - 2 bytes proto characteristics * - 2 bytes line turnaround * - 2 bytes value of one * - 2 bytes connect data length * - 2 bytes connect data offset * - 4 bytes connect data max * - 1 byte connect flags 0 * - 1 byte connect flags 1 * - optionaly, 16 bytes for trace things * - padding until data offset * - then connect data */ size_t const pdu_len = cursor->cap_len; if (pdu_len < 26) return PROTO_PARSE_ERR; unsigned version = cursor_read_u16n(cursor); info->version_maj = version/100; info->version_min = version%100; info->set_values |= SQL_VERSION; cursor_drop(cursor, 14); // jump to connect data length unsigned data_length = cursor_read_u16n(cursor); unsigned data_offset = cursor_read_u16n(cursor); SLOG(LOG_DEBUG, "Connect, data length=%u, data offset=%u", data_length, data_offset); if (data_offset > pdu_len || data_offset < 26 + 8) return PROTO_PARSE_ERR; if (data_length + data_offset > pdu_len + 8) return PROTO_PARSE_ERR; cursor_drop(cursor, data_offset - 20 - 8); // jump to data // Now look for user and dbname (ie. service_name) # define USER_TOKEN "(USER="******"(SERVICE_NAME=" char const *data_end = (char const *)(cursor->head + data_length); char const *str; if (NULL != (str = strnstr((char const *)cursor->head, USER_TOKEN, data_length))) { str += strlen(USER_TOKEN); info->set_values |= SQL_USER; copy_token(info->u.startup.user, sizeof(info->u.startup.user), str, data_end-str); } if (NULL != (str = strnstr((char const *)cursor->head, DBNAME_TOKEN, data_length))) { str += strlen(DBNAME_TOKEN); info->set_values |= SQL_DBNAME; copy_token(info->u.startup.dbname, sizeof(info->u.startup.dbname), str, data_end-str); } return PROTO_OK; }
void setVariable(Token& var, Token& value, bool saveAsReference = false) { stutskInteger i1; if (var.tokenType != T_VARIABLE) { throw StutskException(ET_ERROR, "Token is not a variable"); } else { if (!saveAsReference) recurseVariables(value); if (var.index.size() > 0) { i1 = recurseVariables(var, false, false); if (var.tokenType == T_ARRAY) { if (i1 < (signed)var.asTokenList->size()) { if (saveAsReference) (*var.asTokenList)[i1] = value; else (*var.asTokenList)[i1] = copy_token(value); } else throw StutskException(ET_ERROR, "Array index overflow"); } else if (var.tokenType == T_STRING && !saveAsReference) { if (i1 < (signed)var.asString->length()) { string s1 = *giveString(value); if (s1.length() == 1) (*var.asString)[i1] = s1[0]; else throw StutskException(ET_ERROR, "Left side is not a char"); } else throw StutskException(ET_ERROR, "String index overflow"); } else throw StutskException(ET_ERROR, "Right side cannot be assigned to"); } else { if (saveAsReference) var.data.asVariable.context->variables [var.data.asVariable.name] = value; else var.data.asVariable.context->variables [var.data.asVariable.name] = copy_token(value); } } }
/* ---------------------------------------------------------------------- */ static int get_option_string (const char **opt_list, int count_opt_list, char **next_char) /* ---------------------------------------------------------------------- */ { /* * Read a line and check for options */ int j; int opt_l, opt; char *opt_ptr; char option[MAX_LENGTH]; opt_ptr = *next_char; if (opt_ptr[0] == '-') { opt_ptr++; copy_token (option, &opt_ptr, &opt_l); if (find_option (&(option[1]), &opt, opt_list, count_opt_list, FALSE) == OK) { j = opt; *next_char = opt_ptr; } else { error_msg ("Unknown option.", CONTINUE); error_msg (*next_char, CONTINUE); input_error++; j = OPTION_ERROR; } } else { copy_token (option, &opt_ptr, &opt_l); if (find_option (&(option[0]), &opt, opt_list, count_opt_list, TRUE) == OK) { j = opt; *next_char = opt_ptr; } else { j = OPTION_DEFAULT; } } return (j); }
/************************************************************************ * Function : copy_URL_list * * Parameters : * URL_list *in ; Source URL list * URL_list *out ; Destination URL list * * Description : Copies one URL_list into another. This includes * dynamically allocating the out->URLs field (the full string), * and the structures used to hold the parsedURLs. This memory MUST * be freed by the caller through: free_URL_list(&out) * * Return : int ; * HTTP_SUCCESS - On Success * UPNP_E_OUTOF_MEMORY - On Failure to allocate memory * * Note : ************************************************************************/ int copy_URL_list( URL_list * in, URL_list * out ) { int len = strlen( in->URLs ) + 1; int i = 0; out->URLs = NULL; out->parsedURLs = NULL; out->size = 0; #ifdef _UPNP_MM_ out->URLs = ( char * )upnp_malloc( len ); out->parsedURLs = ( uri_type * ) upnp_malloc( sizeof( uri_type ) * in->size ); #else out->URLs = ( char * )malloc( len ); out->parsedURLs = ( uri_type * ) malloc( sizeof( uri_type ) * in->size ); #endif if( ( out->URLs == NULL ) || ( out->parsedURLs == NULL ) ) return UPNP_E_OUTOF_MEMORY; memcpy( out->URLs, in->URLs, len ); for( i = 0; i < in->size; i++ ) { //copy the parsed uri out->parsedURLs[i].type = in->parsedURLs[i].type; copy_token( &in->parsedURLs[i].scheme, in->URLs, &out->parsedURLs[i].scheme, out->URLs ); out->parsedURLs[i].path_type = in->parsedURLs[i].path_type; copy_token( &in->parsedURLs[i].pathquery, in->URLs, &out->parsedURLs[i].pathquery, out->URLs ); copy_token( &in->parsedURLs[i].fragment, in->URLs, &out->parsedURLs[i].fragment, out->URLs ); copy_token( &in->parsedURLs[i].hostport.text, in->URLs, &out->parsedURLs[i].hostport.text, out->URLs ); copy_sockaddr_in( &in->parsedURLs[i].hostport.IPv4address, &out->parsedURLs[i].hostport.IPv4address ); } out->size = in->size; return HTTP_SUCCESS; }
static int sip_extract_content_type(unsigned unused_ field, struct liner *liner, void *info_) { struct sip_proto_info *info = info_; info->set_values |= SIP_MIME_SET; copy_token(info->mime_type, sizeof(info->mime_type), liner); return 0; }
static void handle_time_macro(CppContext *ctx, Token *tmpl) { Token *tok = copy_token(tmpl); tok->toktype = TOKTYPE_STRING; struct tm *now = get_tm(ctx); tok->val.str = make_string_printf("%02d:%02d:%02d", now->tm_hour, now->tm_min, now->tm_sec); unget_cpp_token(ctx, tok); }
static int sip_extract_to(unsigned unused_ field, struct liner *liner, void *info_) { struct sip_proto_info *info = info_; info->set_values |= SIP_TO_SET; copy_token(info->to, sizeof info->to, liner); return 0; }
static void handle_date_macro(CppContext *ctx, Token *tmpl) { Token *tok = copy_token(tmpl); tok->toktype = TOKTYPE_STRING; char *month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; struct tm *now = get_tm(ctx); tok->val.str = make_string_printf("%s %02d %04d", month[now->tm_mon], now->tm_mday, 1900 + now->tm_year); unget_cpp_token(ctx, tok); }
static int sip_extract_callid(unsigned unused_ field, struct liner *liner, void *info_) { struct sip_proto_info *info = info_; info->set_values |= SIP_CALLID_SET; memset(info->call_id, 0, sizeof info->call_id); // because it's used in HASH_LOOKUP copy_token(info->call_id, sizeof info->call_id, liner); return 0; }
/* * Added a given hide set to tokens in a given list. */ static List *add_hide_set(List *tokens, List *hideset) { List *r = make_list(); for (int i = 0; i < LIST_LEN(tokens); i++) { Token *t = copy_token((Token *)LIST_REF(tokens, i)); t->hideset = list_union(t->hideset, hideset); list_push(r, t); } return r; }
/** * Get next 4-byte token, return it at address specified by 'token' */ static void next_token( struct tgsi_parse_context *ctx, void *token ) { assert( !tgsi_parse_end_of_tokens( ctx ) ); copy_token(token, &ctx->Tokens[ctx->Position]); ctx->Position++; }
static unsigned long copy_ulong(char ** c, char delim) { unsigned long val = 0; char * str = copy_token(c, delim); if (!str) malformed_events(); val = strtoul(str, NULL, 0); free(str); return val; }
static Token *to_keyword_maybe(Token *tok) { ASSERT(tok->toktype == TOKTYPE_IDENT); int id = (intptr)dict_get(keyword_dict(), tok->val.str); if (id) { Token *r = copy_token(tok); r->toktype = TOKTYPE_KEYWORD; r->val.i = id; return r; } return tok; }
void poss_macro_expand(TokenStream& tok, char*&q, char*& p) { char temp_buff[TT_BUFFSIZE]; char token[MAX_IDEN_SIZE]; p = copy_token(p,token); // is it a macro? Otherwise just copy out.... if (tok.macro_attempt_process(p,temp_buff,token)) q = copy_chars(q,temp_buff); else q = copy_chars(q,token); }
/* * Reads "defined" unary operator of the form "defined <identifier>" or * "defined(<identifier>)". The token "defined" is already read when the * function is called. * * (C99 6.10.1 Conditional inclusion, paragraph 1) */ static Token *read_defined(CppContext *ctx) { Token *tok = read_cpp_token(ctx); if (is_punct(tok, '(')) { tok = read_cpp_token(ctx); Token *tok1 = read_cpp_token(ctx); if (!tok1 || !is_punct(tok1, ')')) error_token(tok1, "')' expected, but got '%s'", token_to_string(tok1)); } Token *r = copy_token(tok); r->toktype = TOKTYPE_CPPNUM; r->val.i = is_defined(ctx, tok); return r; }
int copy_URL_list(URL_list *in, URL_list *out) { size_t len = strlen(in->URLs) + (size_t)1; size_t i = (size_t)0; out->URLs = NULL; out->parsedURLs = NULL; out->size = (size_t)0; out->URLs = malloc(len); out->parsedURLs = malloc(sizeof(uri_type) * in->size); if ( !out->URLs || !out->parsedURLs) return UPNP_E_OUTOF_MEMORY; memcpy(out->URLs, in->URLs, len); for( i = (size_t)0; i < in->size; i++ ) { /*copy the parsed uri */ out->parsedURLs[i].type = in->parsedURLs[i].type; copy_token( &in->parsedURLs[i].scheme, in->URLs, &out->parsedURLs[i].scheme, out->URLs ); out->parsedURLs[i].path_type = in->parsedURLs[i].path_type; copy_token( &in->parsedURLs[i].pathquery, in->URLs, &out->parsedURLs[i].pathquery, out->URLs ); copy_token( &in->parsedURLs[i].fragment, in->URLs, &out->parsedURLs[i].fragment, out->URLs ); copy_token( &in->parsedURLs[i].hostport.text, in->URLs, &out->parsedURLs[i].hostport.text, out->URLs ); memcpy( &out->parsedURLs[i].hostport.IPaddress, &in->parsedURLs[i].hostport.IPaddress, sizeof(struct sockaddr_storage) ); } out->size = in->size; return HTTP_SUCCESS; }
void opd_parse_events(char const * events) { char * ev = xstrdup(events); char * c; size_t cur = 0; if (cpu_type == CPU_TIMER_INT) { struct opd_event * event = &opd_events[0]; event->name = xstrdup("TIMER"); event->value = event->counter = event->count = event->um = 0; event->kernel = 1; event->user = 1; return; } if (!ev || !strlen(ev)) { fprintf(stderr, "oprofiled: no events passed.\n"); exit(EXIT_FAILURE); } verbprintf(vmisc, "Events: %s\n", ev); c = ev; while (*c && cur < op_nr_counters) { struct opd_event * event = &opd_events[cur]; if (!(event->name = copy_token(&c, ':'))) malformed_events(); event->value = copy_ulong(&c, ':'); event->counter = copy_ulong(&c, ':'); event->count = copy_ulong(&c, ':'); event->um = copy_ulong(&c, ':'); event->kernel = copy_ulong(&c, ':'); event->user = copy_ulong(&c, ','); ++cur; } if (*c) { fprintf(stderr, "oprofiled: too many events passed.\n"); exit(EXIT_FAILURE); } free(ev); cpu_speed = op_cpu_frequency(); }
static Token *cpp_token_to_token(Token *tok) { if (!tok) return NULL; tok->hideset = NULL; if (tok->toktype == TOKTYPE_IDENT) return to_keyword_maybe(tok); if (tok->toktype == TOKTYPE_CPPNUM) return cppnum_to_num(tok); if (tok->toktype == TOKTYPE_PUNCT) { Token *r = copy_token(tok); r->toktype = TOKTYPE_KEYWORD; return r; } ASSERT(tok->toktype == TOKTYPE_CHAR || tok->toktype == TOKTYPE_STRING); return tok; }
static Token *cppnum_to_int(Token *tok) { char *p = STRING_BODY(tok->val.str); int base = 10; int val = 0; // Read prefix such as "0" or "0x". if (*p == '0') { p++; if (*p == 'x' || *p == 'X') { base = 16; p++; } else if (*p == 'b' || *p == 'B') { // Binary constant using '0b' prefix is GNU extension base = 2; p++; } else { base = 8; } } // Read numbers until non-number character. for (; *p; p++) { int v; if ('0' <= *p && *p <= '9') v = *p - '0'; else if ('a' <= *p && *p <= 'f') v = *p - 'a' + 10; else if ('A' <= *p && *p <= 'F') v = *p - 'A' + 10; else break; if (v >= base) error_token(tok, "invalid digit '%c' in base %d number", *p, base); val *= base; val += v; } // Ignore all suffixes for now while (*p == 'U' || *p == 'u' || *p == 'L' || *p == 'l') p++; if (*p) error_token(tok, "invalid char '%c' in a number '%s'", *p, STRING_BODY(tok->val.str)); Token *r = copy_token(tok); r->toktype = TOKTYPE_INT; r->val.i = val; return r; }
/* * Joins given two tokens and returns it. Used by "##" operator. */ static Token *glue_tokens(Token *t0, Token *t1) { String *b = make_string(); paste(b, t0); paste(b, t1); Token *r = copy_token(t0); if (isdigit(STRING_BODY(b)[0])) { r->toktype = TOKTYPE_CPPNUM; r->val.str = b; return r; } int punct = (intptr)dict_get(punct_dict(), b); if (punct) { r->toktype = TOKTYPE_PUNCT; r->val.i = punct; return r; } r->toktype = TOKTYPE_IDENT; r->val.str = b; return r; }
char *massage_subst_string(char *buff, char **args, char *str) { char *p = str, *q = buff; int i; char token[MAX_IDEN_SIZE]; while (*p) { // *fix 1.2.2 Argument may begin with '_' as well as a letter! while (*p && !iscsymf(*p)) { // *fix 1.2.2 (Eric)..quoted strings are copied verbatim if (*p == '\"') { copy_quote(q,p); break; } if (p[0] == '#' && p[1] == '#') { // *fix 1.2.2 (Eric) Skip whitespace before and after the ## while (q > buff && isspace(q[-1])) --q; // *change 1.2.2 keep token-pasting operator... *q++ = *p++; *q++ = *p++; while (isspace(*p)) ++p; } else *q++ = *p++; } if (*p == 0) break; //...pick up the identifier, and check it against the map p = copy_token(p,token); i = index_into(args,token); i++; //...if it is indeed a formal argument, then encode as the byte index, //...otherwise just copy to output buffer. // *change 1.2.2b (Eric) encode as unique macro-arg marker followed by byte index if (i > 0) { *q++ = ARG_MARKER; *q++ = (char)i; } else q = copy_chars(q,token); } *q = '\0'; return buff; }
static Token *cppnum_to_float(Token *tok) { Token *r = copy_token(tok); r->toktype = TOKTYPE_FLOAT; r->val.f = atof(STRING_BODY(tok->val.str)); return r; }
static void handle_file_macro(CppContext *ctx, Token *tmpl) { Token *tok = copy_token(tmpl); tok->toktype = TOKTYPE_STRING; tok->val.str = ctx->file->filename; unget_cpp_token(ctx, tok); }
void tgsi_parse_token( struct tgsi_parse_context *ctx ) { struct tgsi_token token; unsigned i; next_token( ctx, &token ); switch( token.Type ) { case TGSI_TOKEN_TYPE_DECLARATION: { struct tgsi_full_declaration *decl = &ctx->FullToken.FullDeclaration; memset(decl, 0, sizeof *decl); copy_token(&decl->Declaration, &token); next_token( ctx, &decl->Range ); if (decl->Declaration.Dimension) { next_token(ctx, &decl->Dim); } if( decl->Declaration.Semantic ) { next_token( ctx, &decl->Semantic ); } if (decl->Declaration.File == TGSI_FILE_IMMEDIATE_ARRAY) { unsigned i, j; decl->ImmediateData.u = (union tgsi_immediate_data*) &ctx->Tokens[ctx->Position]; for (i = 0; i <= decl->Range.Last; ++i) { for (j = 0; j < 4; ++j) { ctx->Position++; } } } break; } case TGSI_TOKEN_TYPE_IMMEDIATE: { struct tgsi_full_immediate *imm = &ctx->FullToken.FullImmediate; uint imm_count; memset(imm, 0, sizeof *imm); copy_token(&imm->Immediate, &token); imm_count = imm->Immediate.NrTokens - 1; switch (imm->Immediate.DataType) { case TGSI_IMM_FLOAT32: for (i = 0; i < imm_count; i++) { next_token(ctx, &imm->u[i].Float); } break; case TGSI_IMM_UINT32: for (i = 0; i < imm_count; i++) { next_token(ctx, &imm->u[i].Uint); } break; case TGSI_IMM_INT32: for (i = 0; i < imm_count; i++) { next_token(ctx, &imm->u[i].Int); } break; default: assert( 0 ); } break; } case TGSI_TOKEN_TYPE_INSTRUCTION: { struct tgsi_full_instruction *inst = &ctx->FullToken.FullInstruction; memset(inst, 0, sizeof *inst); copy_token(&inst->Instruction, &token); if (inst->Instruction.Predicate) { next_token(ctx, &inst->Predicate); } if (inst->Instruction.Label) { next_token( ctx, &inst->Label); } if (inst->Instruction.Texture) { next_token( ctx, &inst->Texture); } assert( inst->Instruction.NumDstRegs <= TGSI_FULL_MAX_DST_REGISTERS ); for( i = 0; i < inst->Instruction.NumDstRegs; i++ ) { next_token( ctx, &inst->Dst[i].Register ); if( inst->Dst[i].Register.Indirect ) { next_token( ctx, &inst->Dst[i].Indirect ); /* * No support for indirect or multi-dimensional addressing. */ assert( !inst->Dst[i].Indirect.Dimension ); assert( !inst->Dst[i].Indirect.Indirect ); } if( inst->Dst[i].Register.Dimension ) { next_token( ctx, &inst->Dst[i].Dimension ); /* * No support for multi-dimensional addressing. */ assert( !inst->Dst[i].Dimension.Dimension ); if( inst->Dst[i].Dimension.Indirect ) { next_token( ctx, &inst->Dst[i].DimIndirect ); /* * No support for indirect or multi-dimensional addressing. */ assert( !inst->Dst[i].Indirect.Indirect ); assert( !inst->Dst[i].Indirect.Dimension ); } } } assert( inst->Instruction.NumSrcRegs <= TGSI_FULL_MAX_SRC_REGISTERS ); for( i = 0; i < inst->Instruction.NumSrcRegs; i++ ) { next_token( ctx, &inst->Src[i].Register ); if( inst->Src[i].Register.Indirect ) { next_token( ctx, &inst->Src[i].Indirect ); /* * No support for indirect or multi-dimensional addressing. */ assert( !inst->Src[i].Indirect.Indirect ); assert( !inst->Src[i].Indirect.Dimension ); } if( inst->Src[i].Register.Dimension ) { next_token( ctx, &inst->Src[i].Dimension ); /* * No support for multi-dimensional addressing. */ assert( !inst->Src[i].Dimension.Dimension ); if( inst->Src[i].Dimension.Indirect ) { next_token( ctx, &inst->Src[i].DimIndirect ); /* * No support for indirect or multi-dimensional addressing. */ assert( !inst->Src[i].Indirect.Indirect ); assert( !inst->Src[i].Indirect.Dimension ); } } } break; } case TGSI_TOKEN_TYPE_PROPERTY: { struct tgsi_full_property *prop = &ctx->FullToken.FullProperty; uint prop_count; memset(prop, 0, sizeof *prop); copy_token(&prop->Property, &token); prop_count = prop->Property.NrTokens - 1; for (i = 0; i < prop_count; i++) { next_token(ctx, &prop->u[i]); } break; } default: assert( 0 ); } }
static void handle_line_macro(CppContext *ctx, Token *tmpl) { Token *tok = copy_token(tmpl); tok->toktype = TOKTYPE_CPPNUM; tok->val.str = make_string_printf("%d", ctx->file->line); unget_cpp_token(ctx, tok); }
token *do_the_splits(token *word, entry *lexicon, FILE *dest) { unichar u_SPAL[] = {0x53, 0x50, 0x41, 0x4c, 0x00}; unichar u_SPGUNA[] = {0x53, 0x50, 0x47, 0x55, 0x4e, 0x41, 0x00}; unichar u_SPKE[] = {0x53, 0x50, 0x4b, 0x45, 0x00}; unichar u_SPXYM[] = {0x53, 0x50, 0x58, 0x59, 0x4d, 0x00}; unichar u_SPXDYM[] = {0x53, 0x50, 0x58, 0x44, 0x59, 0x4d, 0x00}; unichar u_SPXHYM[] = {0x53, 0x50, 0x58, 0x48, 0x59, 0x4d, 0x00}; unichar u_SPHY[] = {0x53, 0x50, 0x48, 0x59, 0x00}; unichar u_SPHDY[] = {0x53, 0x50, 0x48, 0x44, 0x59, 0x00}; unichar u_SPLIE[] = {0x53, 0x50, 0x4c, 0x49, 0x45, 0x00}; unichar t_AL[] = {0x41, 0x4c, 0x00}; unichar t_JDNUC[] = {0x4a, 0x44, 0x4e, 0x55, 0x43, 0x00}; unichar t_IIC[] = {0x49, 0x49, 0x43, 0x00}; unichar t_XHC[] = {0x58, 0x48, 0x43, 0x00}; unichar t_IIM1N[] = {0x49, 0x49, 0x4d, 0x31, 0x4e, 0x00}; unichar t_RR[] = {0x52, 0x52, 0x00}; token *word1; token *word2; /* copy the token*/ word1 = word; word2 = copy_token(word); if (ustrident(word->tag[0], u_SPAL)) { /* 1st copy: wipe all but first two characters */ word1->wordform[2] = 0; /* give it the tag AL */ clear_tags(word1); ustrcpy(word1->tag[0], t_AL); /* write it to file */ if (write_token(word1, dest)) { puts("Error! Error! writing split form to file... aborting now..."); fcloseall(); exit(1); } /* 2nd copy: trim off first two characters */ ustrimstart(word2->wordform, 2); /* 2nd copy: resubmit that word, still with SPAL */ urdutag(lexicon, word2); } else if (ustrident(word->tag[0], u_SPGUNA)) { /* 1st copy: shorten by three chars (length of gunaa) */ ustrimend(word1->wordform, 3); /* give it the JDNUC tag */ clear_tags(word1); ustrcpy(word1->tag[0], t_JDNUC); /* write it to file */ if (write_token(word1, dest)) { puts("It's all gone horribly wrong... aborting program!"); fcloseall(); exit(1); } /* 2nd copy: remove all but the three last characters */ ustrimstart(word2->wordform, (ustrlen(word2->wordform) - 3)); /* 2nd copy: resubmit that word, having nulled its tags */ clear_tags(word2); urdutag(lexicon, word2); } else if (ustrident(word->tag[0], u_SPKE)) { /* 1st copy: shorten by 1 char */ ustrimend(word1->wordform, 1); /* clear tags, resubmit to urdutag */ clear_tags(word1); urdutag(lexicon, word1); /* write it to file */ if (write_token(word1, dest)) { puts("I didn't want to be an analysis program, you know."); puts("I wanted to be... a lumberjack!"); fcloseall(); exit(1); } /* 2nd copy: remove all but the last 1 character */ ustrimstart(word2->wordform, (ustrlen(word2->wordform) - 1)); /* 2nd copy: give it the IIC tag, clearing tags first */ clear_tags(word2); ustrcpy(word2->tag[0], t_IIC); } else if (ustrident(word->tag[0], u_SPXHYM )) { /* 1st copy: shorten by three chars */ ustrimend(word1->wordform, 3); /* clear tags, resubmit to urdutag */ clear_tags(word1); urdutag(lexicon, word1); /* write it to file */ if (write_token(word1, dest)) { puts("I'm going to end it all... Goodbye cruel world!"); fcloseall(); exit(1); } /* 2nd copy: remove all but the three last characters */ ustrimstart(word2->wordform, (ustrlen(word2->wordform) - 3)); /* 2nd copy: give tags XHC and IIC */ clear_tags(word2); ustrcpy(word2->tag[0], t_IIC); ustrcpy(word2->tag[1], t_XHC); } else if (ustrident(word->tag[0], u_SPHY)) { /* 1st copy: shorten by 1 char */ ustrimend(word1->wordform, 1); /* clear tags, resubmit to urdutag */ clear_tags(word1); urdutag(lexicon, word1); /* write it to file */ if (write_token(word1, dest)) { puts("It's not working, OKAY? Sod off and leave me alone."); fcloseall(); exit(1); } /* 2nd copy: remove all but the last 1 character */ ustrimstart(word2->wordform, (ustrlen(word2->wordform) - 1)); /* 2nd copy: give tag XHC */ clear_tags(word2); ustrcpy(word2->tag[0], t_XHC); } else if (ustrident(word->tag[0], u_SPHDY)) { /* 1st copy: lose all but first two characters */ ustrimend(word1->wordform, 2); /* clear tags, resubmit to urdutag */ clear_tags(word1); urdutag(lexicon, word1); /* write it to file */ if (write_token(word1, dest)) { puts("OK, the good news is your program was working really, really well."); puts("The bad news is it ain't no more."); fcloseall(); exit(1); } /* 2nd copy: remove all but final 2 chars */ ustrimstart(word2->wordform, (ustrlen(word2->wordform) - 2)); /* 2nd copy: give tag XHC */ clear_tags(word2); ustrcpy(word2->tag[0], t_XHC); } else if (ustrident(word->tag[0], u_SPLIE)) { /* 1st copy: wipe all but first two characters */ word1->wordform[2] = 0; /* make end char to E to make sure it's kE not kY - it may have been disemvowelled! */ word1->wordform[1] = 0x06d2; /* give it the tag IIM1N */ clear_tags(word1); ustrcpy(word1->tag[0], t_IIM1N); /* write it to file */ if (write_token(word1, dest)) { puts("I'm a poor ickle anawysis pwogwam an I don't feel vewy well...."); fcloseall(); exit(1); } /* 2nd copy: remove first 2 chars */ ustrimstart(word2->wordform, 2); /* 2nd copy: give tag RR */ clear_tags(word2); ustrcpy(word2->tag[0], t_RR); } /* if none of these apply, just leave the whole thing the same and return as-is */ free(word1); /* return word 2 to be written by calling function */ return word2; }
void tgsi_parse_token( struct tgsi_parse_context *ctx ) { struct tgsi_token token; unsigned i; next_token( ctx, &token ); switch( token.Type ) { case TGSI_TOKEN_TYPE_DECLARATION: { struct tgsi_full_declaration *decl = &ctx->FullToken.FullDeclaration; memset(decl, 0, sizeof *decl); copy_token(&decl->Declaration, &token); next_token( ctx, &decl->Range ); if (decl->Declaration.Dimension) { next_token(ctx, &decl->Dim); } if (decl->Declaration.Interpolate) { next_token( ctx, &decl->Interp ); } if (decl->Declaration.Semantic) { next_token( ctx, &decl->Semantic ); } if (decl->Declaration.File == TGSI_FILE_RESOURCE) { next_token(ctx, &decl->Resource); } if (decl->Declaration.File == TGSI_FILE_SAMPLER_VIEW) { next_token(ctx, &decl->SamplerView); } if (decl->Declaration.Array) { next_token(ctx, &decl->Array); } break; } case TGSI_TOKEN_TYPE_IMMEDIATE: { struct tgsi_full_immediate *imm = &ctx->FullToken.FullImmediate; uint imm_count; memset(imm, 0, sizeof *imm); copy_token(&imm->Immediate, &token); imm_count = imm->Immediate.NrTokens - 1; switch (imm->Immediate.DataType) { case TGSI_IMM_FLOAT32: case TGSI_IMM_FLOAT64: for (i = 0; i < imm_count; i++) { next_token(ctx, &imm->u[i].Float); } break; case TGSI_IMM_UINT32: for (i = 0; i < imm_count; i++) { next_token(ctx, &imm->u[i].Uint); } break; case TGSI_IMM_INT32: for (i = 0; i < imm_count; i++) { next_token(ctx, &imm->u[i].Int); } break; default: assert( 0 ); } break; } case TGSI_TOKEN_TYPE_INSTRUCTION: { struct tgsi_full_instruction *inst = &ctx->FullToken.FullInstruction; memset(inst, 0, sizeof *inst); copy_token(&inst->Instruction, &token); if (inst->Instruction.Predicate) { next_token(ctx, &inst->Predicate); } if (inst->Instruction.Label) { next_token( ctx, &inst->Label); } if (inst->Instruction.Texture) { next_token( ctx, &inst->Texture); for (i = 0; i < inst->Texture.NumOffsets; i++) { next_token( ctx, &inst->TexOffsets[i] ); } } assert( inst->Instruction.NumDstRegs <= TGSI_FULL_MAX_DST_REGISTERS ); for (i = 0; i < inst->Instruction.NumDstRegs; i++) { next_token( ctx, &inst->Dst[i].Register ); if (inst->Dst[i].Register.Indirect) next_token( ctx, &inst->Dst[i].Indirect ); if (inst->Dst[i].Register.Dimension) { next_token( ctx, &inst->Dst[i].Dimension ); /* * No support for multi-dimensional addressing. */ assert( !inst->Dst[i].Dimension.Dimension ); if (inst->Dst[i].Dimension.Indirect) next_token( ctx, &inst->Dst[i].DimIndirect ); } } assert( inst->Instruction.NumSrcRegs <= TGSI_FULL_MAX_SRC_REGISTERS ); for (i = 0; i < inst->Instruction.NumSrcRegs; i++) { next_token( ctx, &inst->Src[i].Register ); if (inst->Src[i].Register.Indirect) next_token( ctx, &inst->Src[i].Indirect ); if (inst->Src[i].Register.Dimension) { next_token( ctx, &inst->Src[i].Dimension ); /* * No support for multi-dimensional addressing. */ assert( !inst->Src[i].Dimension.Dimension ); if (inst->Src[i].Dimension.Indirect) next_token( ctx, &inst->Src[i].DimIndirect ); } } break; } case TGSI_TOKEN_TYPE_PROPERTY: { struct tgsi_full_property *prop = &ctx->FullToken.FullProperty; uint prop_count; memset(prop, 0, sizeof *prop); copy_token(&prop->Property, &token); prop_count = prop->Property.NrTokens - 1; for (i = 0; i < prop_count; i++) { next_token(ctx, &prop->u[i]); } break; } default: assert( 0 ); } }
/* * Write a string representation of a given token sequence. Used by * # operator. */ static Token *stringize(Token *tmpl, List *arg) { Token *r = copy_token(tmpl); r->toktype = TOKTYPE_STRING; r->val.str = join_tokens(arg, true); return r; }
void Operators::doOperator(Context *context, OperatorType oper) { Token token1, token2, token3; stutskFloat f1, f2; stutskInteger i1, i2; string s1, s2; switch (oper) { case OP_ASSIG: token1 = stack_back_safe(); stutskStack.pop_back(); // Variable token2 = stack_back_safe(); stutskStack.pop_back(); // Value setVariable(token1, token2); break; case OP_ASSIG_REF: token1 = stack_back_safe(); stutskStack.pop_back(); // Variable token2 = stack_back_safe(); stutskStack.pop_back(); // Value setVariable(token1, token2, true); break; case OP_FUNC: token1 = stack_back_safe(); stutskStack.pop_back(); // Name token2 = stack_back_safe(); stutskStack.pop_back(); // Codeblock recurseVariables(token2); if (token2.tokenType != T_CODEBLOCK) { throw StutskException(ET_ERROR, "Token is not a codeblock"); } else { OperatorType dummy; string functionName = *giveString(token1); if (readOperator(functionName, dummy)) throw StutskException(ET_ERROR, "Cannot override an operator"); if (functionName.substr(0,10) == "__builtin_") throw StutskException(ET_ERROR, "Cannot override an internal function"); userFunctions[functionName] = *token2.asTokenList; } break; case OP_UNSET: token1 = stack_back_safe(); stutskStack.pop_back(); if (token1.tokenType == T_VARIABLE) { struct Token::_un_TokenData::_un_VariableData *var = & token1.data.asVariable; TokenMap::iterator iter = var->context->variables.find(var->name); if (iter != var->context->variables.end()) var->context->variables.erase(iter); } else { UserFunctionsMap::iterator iter = userFunctions.find(*giveString(token1)); if (iter != userFunctions.end()) userFunctions.erase(iter); } break; case OP_DEREF: token1 = stack_back_safe(); stutskStack.pop_back(); if (token1.tokenType != T_VARIABLE) { throw StutskException(ET_ERROR, "Token is not a variable"); } else { recurseVariables(token1, true); stutskStack.push_back(copy_token(token1)); } break; case OP_PLUSPLUS: token1 = stack_back_safe(); stutskStack.pop_back(); // Name if (token1.tokenType == T_VARIABLE) { switch (giveGCD(token1, f1, i1, s1)) { case NT_INVALID: case NT_STRING: throw StutskException(ET_ERROR, "Variable is not a numeric type"); case NT_INTEGER: token2.tokenType = T_INTEGER; token2.data.asInteger = i1 + 1; setVariable(token1, token2); break; case NT_FLOAT: token2.tokenType = T_FLOAT; token2.data.asFloat = f1 + 1.; setVariable(token1, token2); break; } } else { switch (giveGCD(token1, f1, i1, s1)) { case NT_INVALID: case NT_STRING: throw StutskException(ET_ERROR, "Token is not a numeric type"); case NT_INTEGER: pushInteger(++i1); break; case NT_FLOAT: pushFloat(++f1); break; } } break; case OP_MINMIN: token1 = stack_back_safe(); stutskStack.pop_back(); // Name if (token1.tokenType == T_VARIABLE) { switch (giveGCD(token1, f1, i1, s1)) { case NT_INVALID: case NT_STRING: throw StutskException(ET_ERROR, "Variable is not a numeric type"); case NT_INTEGER: token2.tokenType = T_INTEGER; token2.data.asInteger = i1 - 1; setVariable(token1, token2); break; case NT_FLOAT: token2.tokenType = T_FLOAT; token2.data.asFloat = f1 - 1.; setVariable(token1, token2); break; } } else { switch (giveGCD(token1, f1, i1, s1)) { case NT_INVALID: case NT_STRING: throw StutskException(ET_ERROR, "Token is not a numeric type"); case NT_INTEGER: pushInteger(--i1); break; case NT_FLOAT: pushFloat(--f1); break; } } break; case OP_PLUS: token1 = stack_back_safe(); stutskStack.pop_back(); token2 = stack_back_safe(); stutskStack.pop_back(); switch (giveGCD(token1, f1, i1, s1)) { case NT_STRING: case NT_INVALID: throw StutskException(ET_ERROR, "Token is not a numeric type"); case NT_INTEGER: switch (giveGCD(token2, f2, i2, s1)) { case NT_STRING: case NT_INVALID: throw StutskException(ET_ERROR, "Token is not a numeric type"); case NT_INTEGER: i1 += i2; pushInteger(i1); break; case NT_FLOAT: f2 += i1; pushFloat(f2); break; } break; case NT_FLOAT: f1 += giveFloat(token2); pushFloat(f1); break; } break; case OP_MINUS: token1 = stack_back_safe(); stutskStack.pop_back(); token2 = stack_back_safe(); stutskStack.pop_back(); switch (giveGCD(token1, f1, i1, s1)) { case NT_STRING: case NT_INVALID: throw StutskException(ET_ERROR, "Token is not a numeric type"); case NT_INTEGER: switch (giveGCD(token2, f2, i2, s1)) { case NT_STRING: case NT_INVALID: throw StutskException(ET_ERROR, "Token is not a numeric type"); case NT_INTEGER: i2 -= i1; pushInteger(i2); break; case NT_FLOAT: f2 -= i1; pushFloat(f2); break; } break; case NT_FLOAT: f2 = giveFloat(token2) - f1; pushFloat(f2); break; } break; case OP_MULTIP: token1 = stack_back_safe(); stutskStack.pop_back(); token2 = stack_back_safe(); stutskStack.pop_back(); switch (giveGCD(token1, f1, i1, s1)) { case NT_STRING: case NT_INVALID: throw StutskException(ET_ERROR, "Token is not a numeric type"); case NT_INTEGER: switch (giveGCD(token2, f2, i2, s1)) { case NT_STRING: case NT_INVALID: throw StutskException(ET_ERROR, "Token is not a numeric type"); case NT_INTEGER: i1 *= i2; pushInteger(i1); break; case NT_FLOAT: f2 *= i1; pushFloat(f2); break; } break; case NT_FLOAT: f1 *= giveFloat(token2); pushFloat(f1); break; } break; case OP_DIV: token1 = stack_back_safe(); stutskStack.pop_back(); token2 = stack_back_safe(); stutskStack.pop_back(); switch (giveGCD(token1, f1, i1, s1)) { case NT_STRING: case NT_INVALID: throw StutskException(ET_ERROR, "Token is not a numeric type"); case NT_INTEGER: if (i1 == 0) throw StutskException(ET_ERROR, "Division by zero"); switch (giveGCD(token2, f2, i2, s1)) { case NT_STRING: case NT_INVALID: throw StutskException(ET_ERROR, "Token is not a numeric type"); case NT_INTEGER: f1 = (stutskFloat)i2 / (stutskFloat)i1; pushFloat(f1); break; case NT_FLOAT: f2 /= (stutskFloat)i1; pushFloat(f2); break; } break; case NT_FLOAT: if (f1 == 0.) throw StutskException(ET_ERROR, "Division by zero"); f2 = giveFloat(token2) / f1; pushFloat(f2); break; } break; case OP_DIVINT: token1 = stack_back_safe(); stutskStack.pop_back(); token2 = stack_back_safe(); stutskStack.pop_back(); switch (giveGCD(token1, f1, i1, s1)) { case NT_STRING: case NT_INVALID: throw StutskException(ET_ERROR, "Token is not a numeric type"); case NT_INTEGER: switch (giveGCD(token2, f2, i2, s1)) { case NT_STRING: case NT_INVALID: throw StutskException(ET_ERROR, "Token is not a numeric type"); case NT_INTEGER: i1 = (stutskInteger)i2 / i1; pushInteger(i1); break; case NT_FLOAT: i2 = (stutskInteger)f2 / i1; pushInteger(i2); break; } break; case NT_FLOAT: i2 = giveInteger(token2) / (stutskInteger)f1; pushInteger(i2); break; } break; case OP_MOD: token1 = stack_back_safe(); stutskStack.pop_back(); token2 = stack_back_safe(); stutskStack.pop_back(); switch (giveGCD(token1, f1, i1, s1)) { case NT_STRING: case NT_INVALID: throw StutskException(ET_ERROR, "Token is not a numeric type"); case NT_INTEGER: switch (giveGCD(token2, f2, i2, s1)) { case NT_STRING: case NT_INVALID: throw StutskException(ET_ERROR, "Token is not a numeric type"); case NT_INTEGER: i1 = (stutskInteger)i2 % i1; pushInteger(i1); break; case NT_FLOAT: i2 = (stutskInteger)f2 % i1; pushInteger(i2); break; } break; case NT_FLOAT: i2 = giveInteger(token2) % (stutskInteger)f1; pushInteger(i2); break; } break; case OP_LESSTHAN: token1 = stack_back_safe(); stutskStack.pop_back(); token2 = stack_back_safe(); stutskStack.pop_back(); pushBool(tokenNumericCompare(token1, token2) == CN_SMALLER); break; case OP_MORETHAN: token1 = stack_back_safe(); stutskStack.pop_back(); token2 = stack_back_safe(); stutskStack.pop_back(); pushBool(tokenNumericCompare(token1, token2) == CN_LARGER); break; case OP_LESSTHAN_EQ: token1 = stack_back_safe(); stutskStack.pop_back(); token2 = stack_back_safe(); stutskStack.pop_back(); pushBool(tokenNumericCompare(token1, token2) != CN_LARGER); break; case OP_MORETHAN_EQ: token1 = stack_back_safe(); stutskStack.pop_back(); token2 = stack_back_safe(); stutskStack.pop_back(); pushBool(tokenNumericCompare(token1, token2) != CN_SMALLER); break; case OP_EQ: token1 = stack_back_safe(); stutskStack.pop_back(); token2 = stack_back_safe(); stutskStack.pop_back(); pushBool(tokenEqual(token1, token2)); break; case OP_SAME: token1 = stack_back_safe(); stutskStack.pop_back(); token2 = stack_back_safe(); stutskStack.pop_back(); pushBool(tokenSame(token1, token2)); break; case OP_NOTEQ: token1 = stack_back_safe(); stutskStack.pop_back(); token2 = stack_back_safe(); stutskStack.pop_back(); pushBool(!tokenEqual(token1, token2)); break; case OP_GLOBAL: token1 = stack_back_safe(); stutskStack.pop_back(); // Variable if (token1.tokenType != T_VARIABLE) { throw StutskException(ET_ERROR, "Token is not a variable"); } else { context->variableScopeMap[token1.data.asVariable.name] = VS_GLOBAL; } break; case OP_AUTO: token1 = stack_back_safe(); stutskStack.pop_back(); // Variable if (token1.tokenType != T_VARIABLE) { throw StutskException(ET_ERROR, "Token is not a variable"); } else { context->variableScopeMap[token1.data.asVariable.name] = VS_AUTO; } break; case OP_STATIC: token1 = stack_back_safe(); stutskStack.pop_back(); // Variable if (token1.tokenType != T_VARIABLE) { throw StutskException(ET_ERROR, "Token is not a variable"); } else { context->variableScopeMap[token1.data.asVariable.name] = VS_STATIC; } break; case OP_FOREVER: token1 = stack_back_safe(); stutskStack.pop_back(); // Codeblock recurseVariables(token1); if (token1.tokenType != T_CODEBLOCK) { throw StutskException(ET_ERROR, "Token is not a codeblock"); } else { while (true) { context->run(*token1.asTokenList, "forever"); if (exitVar == OP_CONTINUE) exitVar = OP_INVALID; if (exitVar != OP_INVALID) break; } if (exitVar == OP_BREAK) exitVar = OP_INVALID; } break; case OP_FOREACH: token1 = stack_back_safe(); stutskStack.pop_back(); // Codeblock token2 = stack_back_safe(); stutskStack.pop_back(); // Codeblock recurseVariables(token1); if (token1.tokenType != T_CODEBLOCK) throw StutskException(ET_ERROR, "Token is not a codeblock"); recurseVariables(token2); if (token2.tokenType == T_ARRAY) { for (TokenList::const_iterator it = token2.asTokenList->begin(); it != token2.asTokenList->end(); ++it) { stutskStack.push_back(*it); stringstream ss; ss << "foreach [" << std::distance(token2.asTokenList->cbegin(), it) << "]"; context->run(*token1.asTokenList, ss.str()); if (exitVar == OP_CONTINUE) exitVar = OP_INVALID; if (exitVar != OP_INVALID) break; } } else if (token2.tokenType == T_DICTIONARY) { for (TokenMap::const_iterator it = token2.asDictionary->begin(); it != token2.asDictionary->end(); ++it) { stutskStack.push_back(it->second); StringPtr f = pushString(); *f = it->first; stringstream ss; ss << "foreach [" << it->first << "]"; context->run(*token1.asTokenList, ss.str()); if (exitVar == OP_CONTINUE) exitVar = OP_INVALID; if (exitVar != OP_INVALID) break; } } else { StringPtr s1_ptr = giveString(token2); for (int i = 0; i < (signed)s1_ptr->length(); i++) { *pushString() = (*s1_ptr)[i]; stringstream ss; ss << "foreach [" << i << "]"; context->run(*token1.asTokenList, ss.str()); if (exitVar == OP_CONTINUE) exitVar = OP_INVALID; if (exitVar != OP_INVALID) break; } } if (exitVar == OP_BREAK) exitVar = OP_INVALID; break; case OP_REPEAT: token1 = stack_back_safe(); stutskStack.pop_back(); // Codeblock token2 = stack_back_safe(); stutskStack.pop_back(); // Codeblock i1 = giveInteger(token2); recurseVariables(token1); if (token1.tokenType != T_CODEBLOCK) { throw StutskException(ET_ERROR, "Token is not a codeblock"); } else { while (i1 > 0) { stringstream ss; ss << "repeat [" << i1 << "]"; context->run(*token1.asTokenList, ss.str()); if (exitVar == OP_CONTINUE) exitVar = OP_INVALID; if (exitVar != OP_INVALID) break; i1--; } if (exitVar == OP_BREAK) exitVar = OP_INVALID; } break; case OP_TRY: token1 = stack_back_safe(); stutskStack.pop_back(); // Codeblock token2 = stack_back_safe(); stutskStack.pop_back(); // Codeblock recurseVariables(token1); recurseVariables(token2); if ((token2.tokenType != T_CODEBLOCK) || (token2.tokenType != T_CODEBLOCK)) { throw StutskException(ET_ERROR, "Token is not a codeblock"); } else { try { context->run(*token2.asTokenList, "try"); } catch (StutskException &e) { *pushString() = e.getMessage(); pushInteger(e.getLineNumber()); *pushString() = e.getFileName(); context->run(*token1.asTokenList, "try"); } catch (std::exception &e) { *pushString() = e.what(); pushInteger(errorToken.lineNum); *pushString() = ParseContext::get_by_id(errorToken.context_id).FileName; context->run(*token1.asTokenList, "try"); } } break; case OP_POWER: token1 = stack_back_safe(); stutskStack.pop_back(); // Codeblock token2 = stack_back_safe(); stutskStack.pop_back(); // Codeblock f1 = pow(giveFloat(token2), giveFloat(token1)); pushFloat(f1); break; case OP_THROW: token1 = stack_back_safe(); stutskStack.pop_back(); // Error name throw StutskException(ET_CUSTOM, *giveString(token1)); break; case OP_NOT: token1 = stack_back_safe(); stutskStack.pop_back(); pushBool(!giveBool(token1)); break; case OP_AND: token1 = stack_back_safe(); stutskStack.pop_back(); token2 = stack_back_safe(); stutskStack.pop_back(); pushBool(giveBool(token1) && giveBool(token2)); break; case OP_OR: token1 = stack_back_safe(); stutskStack.pop_back(); token2 = stack_back_safe(); stutskStack.pop_back(); pushBool(giveBool(token1) || giveBool(token2)); break; case OP_IF: token2 = stack_back_safe(); stutskStack.pop_back(); // Codeblock token1 = stack_back_safe(); stutskStack.pop_back(); // Codeblock recurseVariables(token2); if (token2.tokenType != T_CODEBLOCK) { throw StutskException(ET_ERROR, "Token is not a codeblock"); } else { if (giveBool(token1)) { context->run(*token2.asTokenList, "if"); } } break; case OP_IFELSE: token2 = stack_back_safe(); stutskStack.pop_back(); // Codeblock token3 = stack_back_safe(); stutskStack.pop_back(); // Codeblock token1 = stack_back_safe(); stutskStack.pop_back(); // Codeblock recurseVariables(token2); recurseVariables(token3); if ((token2.tokenType != T_CODEBLOCK) || (token3.tokenType != T_CODEBLOCK)) { throw StutskException(ET_ERROR, "Token is not a codeblock"); } else { if (giveBool(token1)) { context->run(*token3.asTokenList, "ifelse"); } else { context->run(*token2.asTokenList, "ifelse"); } } break; case OP_TERNARY: token2 = stack_back_safe(); stutskStack.pop_back(); // Codeblock token3 = stack_back_safe(); stutskStack.pop_back(); // Codeblock token1 = stack_back_safe(); stutskStack.pop_back(); // Codeblock stutskStack.push_back((giveBool(token1) ? token3 : token2)); break; case OP_CONCAT: token1 = stack_back_safe(); stutskStack.pop_back(); // Codeblock token2 = stack_back_safe(); stutskStack.pop_back(); // Codeblock // Be careful NOT to recurse variable here because we wouldn't want // to overwrite the saved value. if (token2.tokenType == T_STRING) // Performance optimization { token2.asString->append(*giveString(token1)); stutskStack.push_back(token2); } else // Should be fast enough ... *pushString() = *giveString(token2) + *giveString(token1); break; case OP_SWITCH: token2 = stack_back_safe(); stutskStack.pop_back(); // Codeblock token1 = stack_back_safe(); stutskStack.pop_back(); // Codeblock recurseVariables(token2); if (token2.tokenType != T_ARRAY) throw StutskException(ET_ERROR, "Token is not an array"); else { for (TokenList::iterator it = token2.asTokenList->begin(); it != token2.asTokenList->end(); ++it) { token3 = *it; recurseVariables(token3); if (token3.tokenType != T_ARRAY) throw StutskException(ET_ERROR, "Token is not an array"); else { if (token3.asTokenList->size() != 2) throw StutskException(ET_ERROR, "Array of wrong length"); if ((*token3.asTokenList)[1].tokenType != T_CODEBLOCK) throw StutskException(ET_ERROR, "Token is not a codeblock"); if (tokenEqual(token1, (*token3.asTokenList)[0])) { context->run(*(*token3.asTokenList)[1].asTokenList, "switch"); break; } } } } break; case OP_BREAK: case OP_CONTINUE: case OP_HALT: case OP_EXIT: exitVar = oper; break; case OP_ARRAY: token1 = stack_back_safe(); stutskStack.pop_back(); // Codeblock token2 = stack_back_safe(); stutskStack.pop_back(); // Codeblock recurseVariables(token1); if (token2.tokenType == T_VARIABLE) { if (token1.tokenType == T_ARRAY) { for (TokenList::iterator it = token1.asTokenList->begin(); it != token1.asTokenList->end(); ++it) token2.index.push_back(giveInteger(*it)); } else token2.index.push_back(giveInteger(token1)); stutskStack.push_back(token2); } else if (token2.tokenType == T_ARRAY) { if (token1.tokenType == T_ARRAY) { for (TokenList::iterator it = token1.asTokenList->begin(); it != token1.asTokenList->end(); ++it) { i1 = giveInteger(*it); if (i1 < 0) throw StutskException(ET_ERROR, "Array index underflow"); if ((signed)token2.asTokenList->size() >= i1 + 1) { token2 = (*token2.asTokenList)[i1]; } else throw StutskException(ET_ERROR, "Array index overflow"); } stutskStack.push_back(token2); } else { i1 = giveInteger(token1); if (i1 < 0) throw StutskException(ET_ERROR, "Array index underflow"); if ((signed)token2.asTokenList->size() >= i1 + 1) { stutskStack.push_back((*token2.asTokenList)[i1]); } else throw StutskException(ET_ERROR, "Array index overflow"); } } else { i1 = giveInteger(token1); StringPtr s1_ptr = giveString(token2); if (i1 < 0) throw StutskException(ET_ERROR, "String index underflow"); if ((signed)s1_ptr->length() >= i1 + 1) { *pushString() = (*s1_ptr)[i1]; } else throw StutskException(ET_ERROR, "String index overflow"); } } }