Beispiel #1
0
/**
 * 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);
}
Beispiel #2
0
/**
 * 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));
}
Beispiel #3
0
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;
}
Beispiel #4
0
/** 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);
}
Beispiel #5
0
/** 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);
}
Beispiel #6
0
/** 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);
}
Beispiel #7
0
/*
 * 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++;
  }
  
}
Beispiel #9
0
/**
 * 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);
}
Beispiel #10
0
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;
  }
Beispiel #11
0
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);
}
Beispiel #13
0
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;
}
Beispiel #14
0
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);
}
Beispiel #15
0
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;
}
Beispiel #16
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);
  }
}
Beispiel #17
0
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;
}
Beispiel #18
0
/** 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);
}
Beispiel #19
0
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);
  }
Beispiel #20
0
/* 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;
}
Beispiel #21
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;
  }
Beispiel #22
0
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;
	}
}
Beispiel #23
0
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;
}
Beispiel #24
0
/*
 * 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;
}
Beispiel #25
0
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);
  }
Beispiel #26
0
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);
  }
Beispiel #27
0
/*
 * 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;
}
Beispiel #28
0
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;
  }
Beispiel #29
0
/*
 * 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;
}
Beispiel #30
0
/*
 * 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;
}