/** * Adds an array variable with a numeric suffix and its value to * the string (&varN[]=value) * * @note var is not urlencoded */ void str_addQVarArrNrFloat(Str *str, char const *var, int n, float value, int dec) { str_addc(str, '&'); str_add(str, var); str_addInt(str, n); str_add(str, "[]="); str_addFloat(str, value, dec); }
/** * Appends a float to the string. * * @param str the string * @param val the float to add * @param len the length whole number part in char, e.g. 3 for 100. (max 9) * @param dec the number of decimals * @param fixed forces the specified size by padding with spaces * * @note one digit is added to the length to always allow negative numbers * @note if the number doesn't fit ### will be added instead. */ void str_addFloatExt(Str *str, float val, int len, int dec, veBool fixed) { char format[20]; float frac, absval; int fracint; int n; int maxFrac = 1; size_t numchars = 0; size_t totalLength; totalLength = (size_t) (len + dec + 1); // NOTE: %f isn't supported, this must be implemented by integers! // determine whole number and decimals absval = (float) fabs(val); frac = (float) fabs(val); frac -= (int) absval; for (n=0; n<dec; n++) { frac *= 10; maxFrac *= 10; } // then round the decimal itself, and if necessary the whole number // e.g. 0.999999... should always become 1.0 fracint = (int) (frac + 0.5); if (fracint >= maxFrac) { absval += 1; fracint = 0; } // only then display... force minus when negative, for e.g. -0.95 // but not -0.00 if (val < 0 && !((int) absval == 0 && fracint == 0) ) { numchars++; str_add(str, "-"); } // report whole number numchars += str_addIntExt(str, (int) absval, len); if (dec == 0) { if (fixed) str_repeat(str, " ", (int) (totalLength - numchars)); return; } // report decimals as well str_add(str, "."); sprintf(format, "%%0%dd", dec); numchars += str_addIntFmt(str, fracint, dec, format); if (fixed) str_repeat(str, " ", (int) (totalLength - numchars)); }
strlist_t *str_op_or(strlist_t *p, strlist_t *q) { strlist_t *r = 0, *t; // add contents of p for (t = p; t; t = t->next) r = str_add(r, t->data); // add contents of q for (t = q; t; t = t->next) if (!str_search(r, t->data, 0)) r = str_add(r, t->data); return r; }
/** Adds a variable and value to the string (&var=value) * * @note var is not urlencoded */ void str_addQVarFloat(Str *str, char const *var, float value, int dec) { str_addc(str, '&'); str_add(str, var); str_addc(str, '='); str_addFloat(str, value, dec); }
/** Adds a variable and value to the string (&var=value) * * @note var is not urlencoded */ void str_addQVarInt(Str *str, char const *var, s32 value) { str_addc(str, '&'); str_add(str, var); str_addc(str, '='); str_addInt(str, value); }
/** Adds a variable and value to the string (&var=value) * * @note var is not urlencoded, value is */ void str_addQVarStr(Str *str, char const *var, char const *value) { str_addc(str, '&'); str_add(str, var); str_addc(str, '='); str_addUrlEnc(str, value); }
/* * Returns a strlist_t with the groups of an user. */ strlist_t * user_find_groups(char *u) { linefilereader_t lfr; char buf[1024], *tmp, *spc2; strlist_t *groups = 0; hashtable_t *cfg = get_config(); tmp = ht_get(cfg, PROPERTY_GL_USERDIR); if (!tmp) quit(" * Could not find '%s' property in config", PROPERTY_GL_USERDIR); sprintf(buf, "%s/%s", tmp, u); if (lfr_open(&lfr, buf) < 0) quit(" * Could not open your userfile %s", buf); while (lfr_getline(&lfr, buf, 1024) > -1) { if (!strncasecmp(buf, "GROUP ", 6) || !strncasecmp(buf, "PRIVATE ", 8)) { tmp = strchr(buf, ' ') + 1; // fix for glftpd2.x which has 'GROUP group num' spc2 = strchr(tmp, ' '); if (spc2) *spc2 = 0; groups = str_add(groups, tmp); } } lfr_close(&lfr); return groups; }
void do_controller_buffer_code(int idx, const char *postfix, int buf_len, int rows) { int display_idx; char s[1024]; sprintf(s, "u8g2_m_%s_%d_%s", strlowercase(controller_list[idx].name), controller_list[idx].tile_width, postfix); if ( str_exists(s) == 0 ) { str_add(s); //FILE *fp = stdout; fprintf(buf_code_fp, "uint8_t *%s(uint8_t *page_cnt)\n", s); fprintf(buf_code_fp, "{\n"); fprintf(buf_code_fp, " static uint8_t buf[%d];\n", buf_len); fprintf(buf_code_fp, " *page_cnt = %d;\n", rows); fprintf(buf_code_fp, " return buf;\n"); fprintf(buf_code_fp, "}\n"); fprintf(buf_header_fp, "uint8_t *%s(uint8_t *page_cnt);\n", s); } display_idx = 0; fprintf(setup_code_fp, "/* %s %s */\n", controller_list[idx].name, postfix); while( controller_list[idx].display_list[display_idx].name != NULL ) { do_display(idx, display_idx, postfix); display_idx++; } }
/** * Appends an integer to the string with specified format. * * @param str the string * @param val the integer to add * @param len the length of the char of the integer, e.g. 3 for 100. (max 10, 2147483647) * @param fmt the formatter for sprintf * * @note one digit is added to the length to always allow negative numbers * @note if the number doesn't fit ### will be added instead. */ size_t str_addIntFmt(Str *str, int val, int len, char const *fmt) { char invalid[] = "###########"; float max = 1; int n; if (len > 10) return 0; n = len; while (n--) max *= 10; if (abs(val) >= max) { invalid[len] = 0; return str_add(str, invalid); } str_fit(str, len + 1); // 1 for sign if (str->error) return 0; return sprintf(str_cur(str), fmt, val); }
TSTR_LIST read_config(const char *filename) { FILE *f; TSTR_LIST ls; char buff[256]; f=fopen(filename,"r"); if (f==NULL) return NULL; ls=create_list(256); while (!feof(f)) { char *c; buff[0]=0; if (fgets(buff,256,f)==NULL) break; c=strchr(buff,'\n');if (c!=NULL) *c=0; if (ferror(f)) { release_list(ls); fclose(f); return NULL; } str_add(&ls,buff); } fclose(f); return ls; }
TSTR_LIST merge_configs(TSTR_LIST target, TSTR_LIST source) { char buff[256]; int i; char *c; buff[255]=0; for (i=0;i<str_count(source);i++) if (source[i]) { strncpy(buff,source[i],255); c=strchr(buff,' '); if (c!=NULL) { int p; *c=0; p=find_ini_field(target,buff); if (p==-1) { str_add(&target,source[i]); } else { str_replace(&target,p,source[i]); } } } return target; }
// remove expired items from connection_list void _hp_clean_expired(hashtable_t *ht, time_t max_age) { hashtable_item_t *i; _connection_info_t *ci; _connection_list_t *cl; strlist_t *rl = 0; strlist_iterator_t *rli; char *tip; for (ht_reset(ht); ht_hasnext(ht); ) { i = ht_next(ht); ci = (_connection_info_t*) i->value; // remove expired connection times ci->connects = _hp_cl_remove(ci->connects, max_age); // if there are none left, remove the ip from the table. if (_hp_cl_size(ci->connects) < 1) rl = str_add(rl, ci->ip); } // remove ips with no connection-times from hashtable. for (rli = str_iterator(rl); str_iterator_hasnext(rli); ) { tip = str_iterator_next(rli); // printf("DEBUG: expiring %s\n", tip); ht_remove(ht, tip); } str_close(rl); free(rli); }
strlist_t *str_reverse(strlist_t *l) { strlist_t *t, *r = 0; for (t = l; t; t = t->next) r = str_add(r, t->data); return t; }
void get_cookies(const char *headers, char ***dynamic_cookies, int *n_dynamic_cookies, char ***static_cookies, int *n_static_cookies) { int index = 0; char **header_lines = NULL; int n_header_lines = 0; split_string(headers, "\r\n", &header_lines, &n_header_lines); for(index=0; index<n_header_lines; index++) { char use_static = 0; char *result = NULL; int cparts_index = 0; char **cparts = NULL; int n_cparts = 0; if (strncmp(header_lines[index], "Set-Cookie:", 11) != 0) continue; split_string(&header_lines[index][12], ";", &cparts, &n_cparts); for(cparts_index=0; cparts_index<n_cparts; cparts_index++) { char *part = cparts[cparts_index]; while(*part == ' ') part++; if (strncmp(part, "expires=", 8) == 0) { use_static = 1; continue; } if (strncmp(part, "path=", 5) == 0) continue; if (strncmp(part, "domain=", 7) == 0) continue; if (strncmp(part, "HttpOnly", 8) == 0) continue; str_add(&result, "%s ", part); } free_splitted_string(cparts, n_cparts); if (use_static) add_cookie(static_cookies, n_static_cookies, result); else add_cookie(dynamic_cookies, n_dynamic_cookies, result); free(result); } free_splitted_string(header_lines, n_header_lines); }
static int _new_map_set_str (MAP map, char *dst, char *val, int add) { if (add) str_add(dst, val); else str_copy(dst, val); return 0; }
token * lex_next(lexer * lex) { switch(lex->state) { case LEX_DEF: _lex_adv(lex); if(EOF == lex->current_char) { return lex_next(_lex_set_state(lex, LEX_DONE)); } else if(_is_int(lex->current_char)) { return lex_next(_lex_set_state(lex, LEX_IN_INT)); } else if(_is_space(lex->current_char)) { return lex_next(lex); } else if(_is_str_end(lex->current_char)) { return lex_next(_lex_adv(_lex_set_state(lex, LEX_IN_STR))); } else if(_is_id_start(lex->current_char)) { return lex_next(_lex_set_state(lex, LEX_IN_ID)); } else if(_is_ctrl_char(lex->current_char)) { return _token_ctrl_char(lex->current_char); } else { return lex_next(_lex_set_state(lex, LEX_ERR)); } case LEX_IN_INT: if(_is_int(lex->current_char)) { if(0 == str_add(lex->tok_buf, lex->current_char)) { return lex_next(_lex_set_state(lex, LEX_ERR)); } return lex_next(_lex_adv(lex)); } return _tok_new(lex, TOK_INT, LEX_DEF); case LEX_IN_ID: if(_is_id(lex->current_char)) { if(0 == str_add(lex->tok_buf, lex->current_char)) { return lex_next(_lex_set_state(lex, LEX_ERR)); } return lex_next(_lex_adv(lex)); } if(_is_keyword(lex->tok_buf)) { return _tok_new(lex, TOK_KEY, LEX_DEF); } return _tok_new(lex, TOK_ID, LEX_DEF); case LEX_IN_STR: if(!_is_str_end(lex->current_char)) { if(_is_escape(lex->current_char)) { return lex_next(_lex_adv(_lex_set_state(lex, LEX_IN_ESC))); } if(0 == str_add(lex->tok_buf, lex->current_char)) { return lex_next(_lex_set_state(lex, LEX_ERR)); } return lex_next(_lex_adv(lex)); } return _tok_new(lex, TOK_STR, LEX_DEF); case LEX_IN_ESC: if(_is_escapable(lex->current_char)) { _lex_set_char(lex, _make_escape(lex->current_char)); if(0 == str_add(lex->tok_buf, lex->current_char)) { return lex_next(_lex_set_state(lex, LEX_ERR)); } return lex_next(_lex_adv(_lex_set_state(lex, LEX_IN_STR))); } return lex_next(_lex_set_state(lex, LEX_ERR)); case LEX_ERR: return _tok_new(lex, TOK_ERR, LEX_DEF); case LEX_DONE: default: return _tok_new(lex, TOK_EOF, LEX_DONE); } }
strlist_t *str_op_and(strlist_t *p, strlist_t *q) { strlist_t *r = 0, *t; // add items in both p and q. for (t = p; t; t = t->next) if (str_search(q, t->data, 0)) r = str_add(r, t->data); return r; }
/** Sets the string to a value. * * @param str the string * @param value the string to set */ size_t str_set(Str *str, char const *value) { if (str->data == NULL) return 0; str->data[0] = 0; str->str_len = 0; dbg_memset(str->data, 0, str->buf_size); return str_add(str, value); }
void add_field_txt(TSTR_LIST *ls,const char *name,const char *text) { int i; char *d; d=alloca(strlen(name)+strlen(text)+2); sprintf(d,"%s %s",name,text); i=find_ini_field(*ls,name); if (i==-1) str_add(ls,d); else str_replace(ls,i,d); }
/* Adds value(s) to the option (+= operator). Returns zero on success. */ static int set_add(opt_t *opt, const char value[]) { if(opt->type != OPT_INT && opt->type != OPT_SET && opt->type != OPT_STRLIST && opt->type != OPT_CHARSET) return -1; if(opt->type == OPT_INT) { char *p; int i; i = strtol(value, &p, 10); if(*p != '\0') return -1; if(i == 0) return 0; opt->val.int_val += i; notify_option_update(opt, OP_MODIFIED, opt->val); } else if(opt->type == OPT_SET) { if(set_op(opt, value, SO_ADD)) { notify_option_update(opt, OP_MODIFIED, opt->val); } } else if(opt->type == OPT_CHARSET) { const size_t valid_len = strspn(value, *opt->vals); if(valid_len != strlen(value)) { text_buffer_addf("Illegal character: <%c>", value[valid_len]); return -1; } if(charset_add_all(opt, value)) { notify_option_update(opt, OP_MODIFIED, opt->val); } } else if(*value != '\0') { opt->val.str_val = str_add(opt->val.str_val, value); notify_option_update(opt, OP_MODIFIED, opt->val); } return 0; }
static void next_line(int step) { linepos += step; if (linepos>YMAX) { char s[3]; s[0] = 27; s[1] = END_PAGE; s[2] = 0; str_add(&all_text,s); linepos = 0; picture_len = -1; } last_skip = step; }
void str_addcEscaped(Str *str, char c) { switch(c) { case '\n': str_add(str, "\\n"); break; case '\r': str_add(str, "\\r"); break; case '"': str_add(str, "\\\""); break; case '\'': str_add(str, "\\'"); break; case '\\': str_add(str, "\\\\"); break; default: str_addc(str, c); break; } }
char *scan_get_regc( const char *reg_expr, char *buf ) { for( ; *reg_expr != 0; reg_expr ++ ) { char c = *reg_expr; if( c != '(' && c != ')' && c != '*' && c != '|' ) { str_add( buf, c ); } } return buf; }
/* * Gets configuration properties in the a|b|c|d format as a strlist. */ strlist_t * config_get_split_property(char *prop) { hashtable_t *cfg = get_config(); char *tmp; stringtokenizer st; strlist_t *l = 0; tmp = ht_get(cfg, prop); st_initialize(&st, tmp, "|"); while (st_hasnext(&st)) { tmp = st_next(&st); l = str_add(l, tmp); } return l; }
void load_book() { char *c; FILE *f; char tx[512]; if (all_text != NULL) release_list(all_text); all_text = NULL; concat(c,pathtable[SR_TEMP],BOOK_FILE); f = fopen(c,"r");if (f == NULL) return; all_text = create_list(256); while (fgets(tx,510,f) != NULL) { char *c; c = strchr(tx,0);c--;*c = 0; str_add(&all_text,tx); } fclose(f); }
static void insert_picture(char *filename,int align,int line,int lsize) { int x, y; short *psiz; char *c = write_buff; psiz = ablock(get_data_handle(filename,pcx_8bit_decomp)); switch (align) { case ANUM_CENTER: x = (XMAX-psiz[0])/2; y = linepos; linepos += psiz[1]; *c++= 27; *c++= END_LINE; c += insert_num(c,0,psiz[1]+last_skip); break; case ANUM_LEFT: x = 0; y = linepos; left_skip = psiz[0]+5; total_width = XMAX-left_skip; break; case ANUM_RIGHT: total_width = (x = XMAX-psiz[0])-5; left_skip = 0; y = linepos; break; } if (!lsize) lsize = psiz[1]-line; picture_len = lsize; *c++= 27; *c++= PICTURE; while (*filename) *c++= *filename++; *c++=':'; c += insert_num(c,0,x); c += insert_num(c,0,y); c += insert_num(c,0,line); c += insert_num(c,0,lsize); *c++= 0; str_add(&all_text,write_buff); }
/* * Returns the list of pre groups from config. * */ strlist_t * groups_find_all() { strlist_t * l = 0; char *tmp, buf[300], *grp; hashtable_t *cfg = get_config(); hashtable_t *env = get_context(); hashtable_item_t *htn; // check if we have made it already. if (ht_get(env, "ALLGROUPS")) return (strlist_t*)ht_get(env, "ALLGROUPS"); ht_reset(cfg); // look through all properties in config. while (htn = ht_next(cfg)) { tmp = htn->key; if (strcmp(tmp, "group.")) continue; grp = strdup(tmp + 6); tmp = strchr(grp, '.'); if (!tmp) { free(grp); continue; } *tmp = 0; if (!str_search(l, grp, 0)) { l = str_add(l, grp); } } ht_put_obj(env, "ALLGROUPS", l); return l; }
static int insert_end_line_and_save(int p,int ys) { int size; while (read_buff[buff_pos] ==' ' && buff_pos<buff_end) buff_pos++; size = buff_end-buff_pos; if (size)memcpy(read_buff,read_buff+buff_pos,size); write_buff[p++] = 27; write_buff[p++] = END_LINE; p = insert_num(write_buff,p,ys); write_buff[p++] = 0; str_add(&all_text,write_buff); buff_pos = size; buff_end = buff_pos; if (picture_len>0) picture_len -= ys; if (picture_len<= 0 && total_width != XMAX) { picture_len = 0; total_width = XMAX; left_skip = 0; } return p; }
/* * NAME: optimize->binop() * DESCRIPTION: optimize a binary operator expression */ static Uint opt_binop(node **m) { node *n, *t; Uint d1, d2, d; Float f1, f2; n = *m; if (n->type == N_ADD && n->r.right->type == N_ADD && n->l.left->mod == n->r.right->mod && (n->mod == T_STRING || (n->mod & T_REF) != 0)) { /* * a + (b + c) --> (a + b) + c * the order in which these are added won't affect the final result */ t = n->l.left; n->l.left = n->r.right; n->r.right = n->l.left->r.right; n->l.left->r.right = n->l.left->l.left; n->l.left->l.left = t; } d1 = opt_expr(&n->l.left, FALSE); d2 = opt_expr(&n->r.right, FALSE); if (n->type == N_SUM) { if (n->l.left->type == N_RANGE) { d1 = max2(d1, 3); } else if (n->l.left->type != N_SUM) { d1++; } if (n->r.right->type == N_RANGE) { d2 = max2(d2, 3); } else { d2++; } return d1 + d2; } if (n->type == N_ADD) { if (n->r.right->type == N_STR && (n->l.left->type == N_ADD || n->l.left->type == N_SUM) && n->l.left->r.right->type == N_STR) { /* (x + s1) + s2 */ node_tostr(n->r.right, str_add(n->l.left->r.right->l.string, n->r.right->l.string)); n->l.left = n->l.left->l.left; return d1; } if (n->l.left->mod == T_STRING || (n->l.left->mod & T_REF) != 0) { /* * see if the summand operator can be used */ switch (n->l.left->type) { case N_ADD: n->l.left->type = N_SUM; d1 += 2; /* SUM_SIMPLE on both sides */ if (n->l.left->l.left->type == N_RANGE) { d1++; } n->type = N_SUM; if (n->r.right->type == N_RANGE) { d2 = max2(d2, 3); /* at least 3 */ } else { d2++; /* add SUM_SIMPLE */ } return d1 + d2; case N_FUNC: if (n->l.left->r.number == kd_allocate || n->l.left->r.number == kd_allocate_int || n->l.left->r.number == kd_allocate_float) { t = n->l.left->l.left->r.right; if (t != (node *) NULL && t->type != N_PAIR && t->type != N_SPREAD && t->mod == T_INT) { d1++; /* add SUM_ALLOCATE */ n->type = N_SUM; if (n->r.right->type == N_RANGE) { d2 = max2(d2, 3); /* at least 3 */ } else { d2++; /* add SUM_SIMPLE */ } return d1 + d2; } } /* fall through */ default: if (n->r.right->type != N_RANGE && n->r.right->type != N_AGGR) { if (n->r.right->type != N_FUNC || (n->r.right->r.number != kd_allocate && n->r.right->r.number != kd_allocate_int && n->r.right->r.number != kd_allocate_float)) { break; } t = n->r.right->l.left->r.right; if (t == (node *) NULL || t->type == N_PAIR || t->type == N_SPREAD || t->mod != T_INT) { break; } } /* fall through */ case N_AGGR: d1++; /* add SUM_SIMPLE */ n->type = N_SUM; if (n->r.right->type == N_RANGE) { d2 = max2(d2, 3); /* at least 3 */ } else { d2++; /* add SUM_SIMPLE */ } return d1 + d2; case N_RANGE: d1 = max2(d1, 3); /* at least 3 */ /* fall through */ case N_SUM: n->type = N_SUM; if (n->r.right->type == N_RANGE) { d2 = max2(d2, 3); /* at least 3 */ } else { d2++; /* add SUM_SIMPLE */ } return d1 + d2; } } } if (n->l.left->flags & F_CONST) { if (n->r.right->flags & F_CONST) { /* c1 . c2 */ return opt_binconst(m); } switch (n->type) { case N_ADD: if (!T_ARITHMETIC(n->l.left->mod) || !T_ARITHMETIC(n->r.right->mod)) { break; } /* fall through */ case N_ADD_INT: case N_ADD_FLOAT: case N_AND: case N_AND_INT: case N_EQ: case N_EQ_INT: case N_EQ_FLOAT: case N_MULT: case N_MULT_INT: case N_MULT_FLOAT: case N_NE: case N_NE_INT: case N_NE_FLOAT: case N_OR: case N_OR_INT: case N_XOR: case N_XOR_INT: /* swap constant to the right */ t = n->l.left; n->l.left = n->r.right; n->r.right = t; d = d1; d1 = d2; d2 = d; break; } } d = max2(d1, d2 + 1); if ((n->r.right->type == N_INT && n->r.right->l.number == 0 && n->l.left->mod == T_INT) || (n->r.right->type == N_FLOAT && NFLT_ISZERO(n->r.right) && n->l.left->mod == T_FLOAT) || (n->r.right->type == nil_node && n->r.right->l.number == 0 && n->l.left->mod != T_MIXED && T_POINTER(n->l.left->mod))) { /* * int == 0, float == 0.0, ptr == nil */ switch (n->type) { case N_EQ: case N_EQ_INT: case N_EQ_FLOAT: *m = opt_not(n->l.left); return d1; case N_NE: case N_NE_INT: case N_NE_FLOAT: *m = opt_tst(n->l.left); return d1; } } if (T_ARITHMETIC(n->mod) && n->mod == n->l.left->mod && n->mod == n->r.right->mod) { if (n->r.right->flags & F_CONST) { /* x . c */ if ((n->type == n->l.left->type || (n->mod == T_INT && n->l.left->mod == T_INT && n->type == n->l.left->type + 1)) && (n->l.left->r.right->flags & F_CONST)) { /* (x . c1) . c2 */ switch (n->type) { case N_ADD_FLOAT: case N_SUB_FLOAT: NFLT_GET(n->l.left->r.right, f1); NFLT_GET(n->r.right, f2); f1.add(f2); NFLT_PUT(n->l.left->r.right, f1); *m = n->l.left; d = d1; break; case N_ADD_INT: case N_SUB_INT: case N_LSHIFT_INT: case N_RSHIFT_INT: n->l.left->r.right->l.number += n->r.right->l.number; *m = n->l.left; d = d1; break; case N_AND_INT: n->l.left->r.right->l.number &= n->r.right->l.number; *m = n->l.left; d = d1; break; case N_DIV_FLOAT: case N_MULT_FLOAT: NFLT_GET(n->l.left->r.right, f1); NFLT_GET(n->r.right, f2); f1.mult(f2); NFLT_PUT(n->l.left->r.right, f1); *m = n->l.left; d = d1; break; case N_DIV_INT: case N_MULT_INT: n->l.left->r.right->l.number *= n->r.right->l.number; *m = n->l.left; d = d1; break; case N_OR_INT: n->l.left->r.right->l.number |= n->r.right->l.number; *m = n->l.left; d = d1; break; case N_XOR_INT: n->l.left->r.right->l.number ^= n->r.right->l.number; *m = n->l.left; d = d1; break; } } else { switch (n->type) { case N_ADD_FLOAT: if (n->l.left->type == N_SUB_FLOAT) { if (n->l.left->l.left->type == N_FLOAT) { /* (c1 - x) + c2 */ NFLT_GET(n->l.left->l.left, f1); NFLT_GET(n->r.right, f2); f1.add(f2); NFLT_PUT(n->l.left->l.left, f1); *m = n->l.left; return d1; } if (n->l.left->r.right->type == N_FLOAT) { /* (x - c1) + c2 */ NFLT_GET(n->l.left->r.right, f1); NFLT_GET(n->r.right, f2); f1.sub(f2); NFLT_PUT(n->l.left->r.right, f1); *m = n->l.left; d = d1; } } break; case N_ADD_INT: if (n->l.left->type == N_SUB || n->l.left->type == N_SUB_INT) { if (n->l.left->l.left->type == N_INT) { /* (c1 - x) + c2 */ n->l.left->l.left->l.number += n->r.right->l.number; *m = n->l.left; return d1; } if (n->l.left->r.right->type == N_INT) { /* (x - c1) + c2 */ n->l.left->r.right->l.number -= n->r.right->l.number; *m = n->l.left; d = d1; } } break; case N_DIV_FLOAT: if (n->l.left->type == N_MULT_FLOAT && n->l.left->r.right->type == N_FLOAT && !NFLT_ISZERO(n->r.right)) { /* (x * c1) / c2 */ NFLT_GET(n->l.left->r.right, f1); NFLT_GET(n->r.right, f2); f1.div(f2); NFLT_PUT(n->l.left->r.right, f1); *m = n->l.left; d = d1; } break; case N_MULT_FLOAT: if (n->l.left->type == N_DIV_FLOAT) { if (n->l.left->l.left->type == N_FLOAT) { /* (c1 / x) * c2 */ NFLT_GET(n->l.left->l.left, f1); NFLT_GET(n->r.right, f2); f1.mult(f2); NFLT_PUT(n->l.left->l.left, f1); *m = n->l.left; return d1; } if (n->l.left->r.right->type == N_FLOAT && !NFLT_ISZERO(n->l.left->r.right)) { /* (x / c1) * c2 */ NFLT_GET(n->r.right, f1); NFLT_GET(n->l.left->r.right, f2); f1.div(f2); NFLT_PUT(n->r.right, f1); n->l.left = n->l.left->l.left; d = d1; } } break; case N_SUB_FLOAT: if (n->l.left->type == N_ADD_FLOAT && n->l.left->r.right->type == N_FLOAT) { /* (x + c1) - c2 */ NFLT_GET(n->l.left->r.right, f1); NFLT_GET(n->r.right, f2); f1.sub(f2); NFLT_PUT(n->l.left->r.right, f1); *m = n->l.left; d = d1; } break; case N_SUB_INT: if (n->l.left->type == N_ADD_INT && n->l.left->r.right->type == N_INT) { /* (x + c1) - c2 */ n->l.left->r.right->l.number -= n->r.right->l.number; *m = n->l.left; d = d1; } break; } } } else if (n->l.left->flags & F_CONST) { /* c . x */ switch (n->type) { case N_SUB_FLOAT: if (n->r.right->type == N_SUB_FLOAT) { if (n->r.right->l.left->type == N_FLOAT) { /* c1 - (c2 - x) */ NFLT_GET(n->l.left, f1); NFLT_GET(n->r.right->l.left, f2); f1.sub(f2); n->type = N_ADD; n->l.left = n->r.right->r.right; n->r.right = n->r.right->l.left; NFLT_PUT(n->r.right, f1); d = d2; } else if (n->r.right->r.right->type == N_FLOAT) { /* c1 - (x - c2) */ NFLT_GET(n->l.left, f1); NFLT_GET(n->r.right->r.right, f2); f1.add(f2); NFLT_PUT(n->l.left, f1); n->r.right = n->r.right->l.left; return d2 + 1; } } else if (n->r.right->type == N_ADD_FLOAT && n->r.right->r.right->type == N_FLOAT) { /* c1 - (x + c2) */ NFLT_GET(n->l.left, f1); NFLT_GET(n->r.right->r.right, f2); f1.sub(f2); NFLT_PUT(n->l.left, f1); n->r.right = n->r.right->l.left; return d2 + 1; } break; case N_SUB_INT: if ((n->r.right->type == N_SUB || n->r.right->type == N_SUB_INT)) { if (n->r.right->l.left->type == N_INT) { /* c1 - (c2 - x) */ n->r.right->l.left->l.number -= n->l.left->l.number; n->type = n->r.right->type; n->l.left = n->r.right->r.right; n->r.right = n->r.right->l.left; d = d2; } else if (n->r.right->r.right->type == N_INT) { /* c1 - (x - c2) */ n->l.left->l.number += n->r.right->r.right->l.number; n->r.right->r.right = n->r.right->l.left; n->r.right->l.left = n->l.left; *m = n->r.right; return d2 + 1; } } else if (n->r.right->type == N_ADD_INT && n->r.right->r.right->type == N_INT) { /* c1 - (x + c2) */ n->l.left->l.number -= n->r.right->r.right->l.number; n->r.right = n->r.right->l.left; return d2 + 1; } break; case N_DIV_FLOAT: if (n->r.right->type == N_DIV_FLOAT) { if (n->r.right->l.left->type == N_FLOAT && !NFLT_ISZERO(n->r.right->l.left)) { /* c1 / (c2 / x) */ NFLT_GET(n->l.left, f1); NFLT_GET(n->r.right->l.left, f2); f1.div(f2); n->type = N_MULT; n->l.left = n->r.right->r.right; n->r.right = n->r.right->l.left; NFLT_PUT(n->r.right, f1); d = d2; } else if (n->r.right->r.right->type == N_FLOAT) { /* c1 / (x / c2) */ NFLT_GET(n->l.left, f1); NFLT_GET(n->r.right->r.right, f2); f1.mult(f2); NFLT_PUT(n->l.left, f1); n->r.right = n->r.right->l.left; return d2 + 1; } } else if (n->r.right->type == N_MULT_FLOAT && n->r.right->r.right->type == N_FLOAT && !NFLT_ISZERO(n->r.right->r.right)) { /* c1 / (x * c2) */ NFLT_GET(n->l.left, f1); NFLT_GET(n->r.right->r.right, f2); f1.div(f2); NFLT_PUT(n->l.left, f1); n->r.right = n->r.right->l.left; return d2 + 1; } break; } } n = *m; if (T_ARITHMETIC(n->l.left->mod) && (n->r.right->flags & F_CONST)) { switch (n->type) { case N_ADD: case N_ADD_FLOAT: case N_SUB: case N_SUB_FLOAT: if (NFLT_ISZERO(n->r.right)) { *m = n->l.left; d = d1; } break; case N_ADD_INT: case N_SUB_INT: case N_LSHIFT_INT: case N_RSHIFT_INT: case N_XOR_INT: if (n->r.right->l.number == 0) { *m = n->l.left; d = d1; } break; case N_AND_INT: if (n->r.right->l.number == 0) { n->type = N_COMMA; return opt_expr(m, FALSE); } if (n->r.right->l.number == -1) { *m = n->l.left; d = d1; } break; case N_MULT: case N_MULT_FLOAT: if (NFLT_ISZERO(n->r.right)) { n->type = N_COMMA; return opt_expr(m, FALSE); } /* fall through */ case N_DIV: case N_DIV_FLOAT: if (NFLT_ISONE(n->r.right)) { *m = n->l.left; d = d1; } break; case N_MULT_INT: if (n->r.right->l.number == 0) { n->type = N_COMMA; return opt_expr(m, FALSE); } /* fall through */ case N_DIV_INT: if (n->r.right->l.number == 1) { *m = n->l.left; d = d1; } break; case N_MOD_INT: if (n->r.right->l.number == 1) { n->r.right->l.number = 0; n->type = N_COMMA; return opt_expr(m, FALSE); } break; case N_OR_INT: if (n->r.right->l.number == -1) { n->type = N_COMMA; return opt_expr(m, FALSE); } if (n->r.right->l.number == 0) { *m = n->l.left; d = d1; } break; } } } return d; }
/* * NAME: optimize->binconst() * DESCRIPTION: optimize a binary operator constant expression */ static Uint opt_binconst(node **m) { node *n; Float f1, f2; bool flag; n = *m; if (n->l.left->type != n->r.right->type) { if (n->type == N_EQ) { node_toint(n, (Int) FALSE); } else if (n->type == N_NE) { node_toint(n, (Int) TRUE); } else { return 2; /* runtime error expected */ } return 1; } switch (n->l.left->type) { case N_INT: switch (n->type) { case N_ADD_INT: n->l.left->l.number += n->r.right->l.number; break; case N_AND_INT: n->l.left->l.number &= n->r.right->l.number; break; case N_DIV_INT: if (n->r.right->l.number == 0) { return 2; /* runtime error: division by 0 */ } n->l.left->l.number /= n->r.right->l.number; break; case N_EQ_INT: n->l.left->l.number = (n->l.left->l.number == n->r.right->l.number); break; case N_GE_INT: n->l.left->l.number = (n->l.left->l.number >= n->r.right->l.number); break; case N_GT_INT: n->l.left->l.number = (n->l.left->l.number > n->r.right->l.number); break; case N_LE_INT: n->l.left->l.number = (n->l.left->l.number <= n->r.right->l.number); break; case N_LSHIFT_INT: n->l.left->l.number <<= n->r.right->l.number; break; case N_LT_INT: n->l.left->l.number = (n->l.left->l.number < n->r.right->l.number); break; case N_MOD_INT: if (n->r.right->l.number == 0) { return 2; /* runtime error: % 0 */ } n->l.left->l.number %= n->r.right->l.number; break; case N_MULT_INT: n->l.left->l.number *= n->r.right->l.number; break; case N_NE_INT: n->l.left->l.number = (n->l.left->l.number != n->r.right->l.number); break; case N_OR_INT: n->l.left->l.number |= n->r.right->l.number; break; case N_RSHIFT_INT: n->l.left->l.number >>= n->r.right->l.number; break; case N_SUB_INT: n->l.left->l.number -= n->r.right->l.number; break; case N_XOR_INT: n->l.left->l.number ^= n->r.right->l.number; break; default: return 2; /* runtime error expected */ } *m = n->l.left; (*m)->line = n->line; return 1; case N_FLOAT: NFLT_GET(n->l.left, f1); NFLT_GET(n->r.right, f2); switch (n->type) { case N_ADD: case N_ADD_FLOAT: f1.add(f2); break; case N_DIV: case N_DIV_FLOAT: if (NFLT_ISZERO(n->r.right)) { return 2; /* runtime error: division by 0.0 */ } f1.div(f2); break; case N_EQ: case N_EQ_FLOAT: node_toint(n->l.left, (Int) (f1.cmp(f2) == 0)); break; case N_GE: case N_GE_FLOAT: node_toint(n->l.left, (Int) (f1.cmp(f2) >= 0)); break; case N_GT: case N_GT_FLOAT: node_toint(n->l.left, (Int) (f1.cmp(f2) > 0)); break; case N_LE: case N_LE_FLOAT: node_toint(n->l.left, (Int) (f1.cmp(f2) <= 0)); break; case N_LT: case N_LT_FLOAT: node_toint(n->l.left, (Int) (f1.cmp(f2) < 0)); break; case N_MULT: case N_MULT_FLOAT: f1.mult(f2); break; case N_NE: case N_NE_FLOAT: node_toint(n->l.left, (Int) (f1.cmp(f2) != 0)); break; case N_SUB: case N_SUB_FLOAT: f1.sub(f2); break; default: return 2; /* runtime error expected */ } NFLT_PUT(n->l.left, f1); *m = n->l.left; (*m)->line = n->line; return 1; case N_STR: switch (n->type) { case N_ADD: node_tostr(n, str_add(n->l.left->l.string, n->r.right->l.string)); return 1; case N_EQ: flag = (str_cmp(n->l.left->l.string, n->r.right->l.string) == 0); break; case N_GE: flag = (str_cmp(n->l.left->l.string, n->r.right->l.string) >= 0); break; case N_GT: flag = (str_cmp(n->l.left->l.string, n->r.right->l.string) > 0); break; case N_LE: flag = (str_cmp(n->l.left->l.string, n->r.right->l.string) <= 0); break; case N_LT: flag = (str_cmp(n->l.left->l.string, n->r.right->l.string) < 0); break; case N_NE: flag = (str_cmp(n->l.left->l.string, n->r.right->l.string) != 0); break; default: return 2; /* runtime error expected */ } node_toint(n, (Int) flag); return 1; case N_NIL: switch (n->type) { case N_EQ: flag = TRUE; break; case N_NE: flag = FALSE; break; default: return 2; /* runtime error expected */ } node_toint(n, (Int) flag); return 1; } return 2; }