コード例 #1
0
ファイル: file.c プロジェクト: lazygunner/transfer
file_desc *init_file_desc()
{
    file_desc *f_desc = NULL;
    t_lock *block_list_lock = NULL;

    if(NULL == (f_desc = (file_desc *)t_malloc(sizeof(file_desc))))
    {
        t_log("malloc login_buf frame error!");
        return NULL;
    }

    if(NULL == (f_desc->block_head =\
        (file_block_desc *)t_malloc(sizeof(file_block_desc))))
        return NULL;
    f_desc->block_head->next = NULL;
    f_desc->block_tail = f_desc->block_head;

    block_list_lock = (t_lock *)t_malloc(sizeof(t_lock));
    init_lock(block_list_lock);
    f_desc->block_list_lock = block_list_lock;

    f_desc->file_size = 0;
    f_desc->file_id = 0;
    f_desc->block_count = 0;
    f_desc->last_frame_count = 0;
    f_desc->frame_remain = NULL;

    return f_desc;
    
}
コード例 #2
0
ファイル: test-data-stack.c プロジェクト: Raffprta/core
static void test_ds_buffers(void)
{
	test_begin("data-stack buffer growth");
	T_BEGIN {
		size_t i;
		unsigned char *p;
		size_t left = t_get_bytes_available();
		while (left < 10000) {
			t_malloc(left); /* force a new block */
			left = t_get_bytes_available();
		}
		left -= 64; /* make room for the sentry if DEBUG */
		p = t_buffer_get(1);
		p[0] = 1;
		for (i = 2; i <= left; i++) {
			/* grow it */
			unsigned char *p2 = t_buffer_get(i);
			test_assert_idx(p == p2, i);
			p[i-1] = i;
			test_assert_idx(p[i-2] == (unsigned char)(i-1), i);
		}
		/* now fix it permanently */
		t_buffer_alloc_last_full();
		test_assert(t_get_bytes_available() < 64 + MEM_ALIGN(1));
	} T_END;
	test_end();

	test_begin("data-stack buffer interruption");
	T_BEGIN {
		void *b = t_buffer_get(1000);
		void *a = t_malloc(1);
		void *b2 = t_buffer_get(1001);
		test_assert(a == b); /* expected, not guaranteed */
		test_assert(b2 != b);
	} T_END;
	test_end();

	test_begin("data-stack buffer with reallocs");
	T_BEGIN {
		size_t bigleft = t_get_bytes_available();
		size_t i;
		for (i = 1; i < bigleft-64; i += rand()%32) T_BEGIN {
			unsigned char *p, *p2;
			size_t left;
			t_malloc(i);
			left = t_get_bytes_available();
			/* The most useful idx for the assert is 'left' */
			test_assert_idx(left <= bigleft-i, left);
			p = t_buffer_get(left/2);
			p[0] = 'Z'; p[left/2 - 1] = 'Z';
			p2 = t_buffer_get(left + left/2);
			test_assert_idx(p != p2, left);
			test_assert_idx(p[0] == 'Z', left);
			test_assert_idx(p[left/2 -1] == 'Z', left);
		} T_END;
	} T_END;
	test_end();
}
コード例 #3
0
ファイル: dip-obj.c プロジェクト: kadych/iscan
/*! \brief  Creates a LUT for brightness/contrast manipulations
 *
 *  Algorithm indirectly taken from the GIMP.
 *
 *  \sa http://en.wikipedia.org/wiki/Image_editing#Contrast_change_and_brightening
 */
LUT *
dip_gimp_BC_LUT (const void *self, int depth,
                 double brightness, double contrast)
{
  SANE_Byte *lut;
  LUT       *m;

  size_t i;
  double max;

  require (dip == self);
  require (-1 <= brightness && brightness <= 1);
  require (-1 <= contrast   && contrast   <= 1);
  require (8 == depth || 16 == depth);

  lut = t_malloc ((1 << depth) * (depth / 8), SANE_Byte);
  m   = t_malloc (1, LUT);

  if (!lut || !m)
    {
      delete (lut);
      delete (m);
      return m;
    }

  m->lut   = lut;
  m->depth = depth;

  max = (1 << depth) - 1;

  for (i = 0; i < (1 << depth); ++i)
    {
      double value = i / max;

      if (brightness < 0.0)
        value *= 1.0 + brightness;
      else
        value += (1 - value) * brightness;

      value = (value - 0.5) * tan ((contrast + 1) * M_PI / 4) + 0.5;
      value *= max;

      if (16 == depth)
        {
          uint16_t *p  = (uint16_t *) lut;

          p[i] = clamp (value, 0, max);
        }
      else
        {
          lut[i] = clamp (value, 0, max);
        }
    }

  return m;
}
コード例 #4
0
ファイル: file.c プロジェクト: lazygunner/transfer
int init_send_list(file_desc *f_desc)
{
    int block_count = 0, i = 0;
    file_block_desc *block_desc = NULL;
    frame_index *f_index = NULL;


    while(block_count * FILE_BLOCK_SIZE < f_desc->file_size)
    {
        /* will be free in read thread */
        if(NULL == (block_desc =\
            (file_block_desc *)t_malloc(sizeof(file_block_desc))))
        {
            t_free(f_desc->block_head);
            return ERR_MALLOC;
        }
        
        if(NULL == (f_index = (frame_index *)t_malloc(sizeof(f_index))))
        {
            t_free(f_desc->block_head);
            t_free(block_desc);
            return ERR_MALLOC;
        }
        
        /* init current block index, all block frame index is 0xFF*/
        f_index->block_index = block_count + 1;
        f_index->frame_index = 0xFFFF;
        f_index->next = NULL;

        block_desc->index = f_index;
        block_desc->retry_flag = ORIGIN_FRAME;
        block_desc->next = NULL;

        /* append blocks to the list tail */
        f_desc->block_tail->next = block_desc;
        f_desc->block_tail = block_desc;
        block_count++;
    }


    for(i = 0; i < f_desc->block_count - 1; i++)
    {
        f_desc->frame_remain[i] = MAX_FRAME_COUNT;
    }
    /* last frame count = 512 or remain */
    f_desc->frame_remain[i] = f_desc->last_frame_count ? f_desc->last_frame_count : MAX_FRAME_COUNT;

    return RET_SUCCESS;

}
コード例 #5
0
ファイル: mtrack.c プロジェクト: vivounicorn/eaburns.tc
/*
 * Allocates `bytes' bytes of memory, and returns a pointer to the
 * beginning of the memory.  A pointer to the allocated memory is kept in
 * the default memory association. 
 */
void *
t_mallocd(size_t bytes)
{
  if (mdefault == NULL)
    init_default();
  return t_malloc(mdefault, bytes);
}
コード例 #6
0
ファイル: file.c プロジェクト: lazygunner/transfer
int set_file_desc(file_desc *f_desc, unsigned short file_id, unsigned char *file_name)
{
    int mod = 0, remain = 0, block_count = 0;
    FILE *fp;

    f_desc->file_id = file_id;
    f_desc->file_name = file_name;
    /* init send msg queue */
    //f_desc->qid = create_msg_q(MSG_Q_KEY_ID_DATA);
    
    if(NULL == f_desc->file_name)
        return ERR_FILE_NAME_NULL;
    if(NULL == (fp = fopen(f_desc->file_name, "rb")))
        return ERR_FILE_NOT_EXIST;
    if(0 == (f_desc->file_size = get_file_size(fp)))
    {
        fclose(fp);
        return ERR_FILE_SIZE_ZERO;
    }
    fclose(fp);

    mod = f_desc->file_size % FILE_BLOCK_SIZE;
    block_count = f_desc->file_size / FILE_BLOCK_SIZE;
    f_desc->block_count = mod ? block_count + 1 : block_count;
    mod = 0;
    remain = f_desc->file_size - block_count * FILE_BLOCK_SIZE;
    mod = remain % FILE_FRAME_SIZE;
    f_desc->last_frame_count = mod ? remain / FILE_FRAME_SIZE + 1 : remain / FILE_FRAME_SIZE;
    
    /* will be free at STATE_TRANSFER_FIN */
    f_desc->frame_remain = (unsigned short *)t_malloc(\
        sizeof(unsigned short) * f_desc->block_count);
    memset(f_desc->frame_remain, 0, sizeof(unsigned short) * f_desc->block_count);
    return RET_SUCCESS;
}
コード例 #7
0
ファイル: iostream-openssl.c プロジェクト: bdraco/dovecot
static const char *
openssl_iostream_get_peer_name(struct ssl_iostream *ssl_io)
{
    X509 *x509;
    char *name;
    int len;

    if (!ssl_iostream_has_valid_client_cert(ssl_io))
        return NULL;

    x509 = SSL_get_peer_certificate(ssl_io->ssl);
    i_assert(x509 != NULL);

    len = X509_NAME_get_text_by_NID(X509_get_subject_name(x509),
                                    ssl_io->username_nid, NULL, 0);
    if (len < 0)
        name = "";
    else {
        name = t_malloc(len + 1);
        if (X509_NAME_get_text_by_NID(X509_get_subject_name(x509),
                                      ssl_io->username_nid,
                                      name, len + 1) < 0)
            name = "";
        else if (strlen(name) != (size_t)len) {
            /* NUL characters in name. Someone's trying to fake
               being another user? Don't allow it. */
            name = "";
        }
    }
    X509_free(x509);

    return *name == '\0' ? NULL : name;
}
コード例 #8
0
static const struct var_expand_table *
get_var_expand_table(struct mail *mail, const char *reason,
		     const char *recipient)
{
	static struct var_expand_table static_tab[] = {
		{ 'n', NULL, "crlf" },
		{ 'r', NULL, "reason" },
		{ 's', NULL, "subject" },
		{ 't', NULL, "to" },
		{ '\0', NULL, NULL }
	};
	struct var_expand_table *tab;
	const char *subject;

	tab = t_malloc(sizeof(static_tab));
	memcpy(tab, static_tab, sizeof(static_tab));

	tab[0].value = "\r\n";
	tab[1].value = reason;
	if (mail_get_first_header(mail, "Subject", &subject) <= 0)
		subject = "";
	tab[2].value = str_sanitize(subject, 80);
	tab[3].value = recipient;

	return tab;
}
コード例 #9
0
ファイル: ast.c プロジェクト: vivounicorn/eaburns.tc
/*
 * Makes a class declaration node. 
 */
AstNode *
makeClass(AstNode * ident, AstNode * parent, AstNode * body,
          unsigned int line)
{
  NameId *nameid;
  Class *p;

  p = t_malloc(memory, sizeof(Class));
  initAstNode(NODE(p), CLASS_NODE, line);

  assert(ident->type == NAMEID_NODE);
  nameid = (NameId *) ident;
  p->name = nameid->name;

  if (parent != NULL) {
    assert(parent->type == NAMEID_NODE);
    nameid = (NameId *) parent;
    p->pname = nameid->name;
  } else {
    p->pname = NULL;
  }

  p->body = body;

  return NODE(p);
}
コード例 #10
0
ファイル: client-common.c プロジェクト: aclindsa/dovecot_core
static const struct var_expand_table *
get_var_expand_table(struct client *client)
{
	struct var_expand_table *tab;

	tab = t_malloc(sizeof(login_var_expand_empty_tab));
	memcpy(tab, login_var_expand_empty_tab,
	       sizeof(login_var_expand_empty_tab));

	if (client->virtual_user != NULL)
		get_var_expand_users(tab, client->virtual_user);
	tab[3].value = login_binary->protocol;
	tab[4].value = getenv("HOME");
	tab[5].value = net_ip2addr(&client->local_ip);
	tab[6].value = net_ip2addr(&client->ip);
	tab[7].value = my_pid;
	tab[8].value = client->auth_mech_name == NULL ? NULL :
		str_sanitize(client->auth_mech_name, MAX_MECH_NAME);
	tab[9].value = dec2str(client->local_port);
	tab[10].value = dec2str(client->remote_port);
	if (!client->tls) {
		tab[11].value = client->secured ? "secured" : NULL;
		tab[12].value = "";
	} else {
		const char *ssl_state =
			ssl_proxy_is_handshaked(client->ssl_proxy) ?
			"TLS" : "TLS handshaking";
		const char *ssl_error =
			ssl_proxy_get_last_error(client->ssl_proxy);

		tab[11].value = ssl_error == NULL ? ssl_state :
			t_strdup_printf("%s: %s", ssl_state, ssl_error);
		tab[12].value =
			ssl_proxy_get_security_string(client->ssl_proxy);
	}
	tab[13].value = client->mail_pid == 0 ? "" :
		dec2str(client->mail_pid);
	tab[14].value = client_get_session_id(client);
	tab[15].value = net_ip2addr(&client->real_local_ip);
	tab[16].value = net_ip2addr(&client->real_remote_ip);
	tab[17].value = dec2str(client->real_local_port);
	tab[18].value = dec2str(client->real_remote_port);
	if (client->virtual_user_orig != NULL)
		get_var_expand_users(tab+19, client->virtual_user_orig);
	else {
		tab[19].value = tab[0].value;
		tab[20].value = tab[1].value;
		tab[21].value = tab[2].value;
	}
	if (client->virtual_auth_user != NULL)
		get_var_expand_users(tab+22, client->virtual_auth_user);
	else {
		tab[22].value = tab[19].value;
		tab[23].value = tab[20].value;
		tab[24].value = tab[21].value;
	}
	tab[25].value = client->listener_name;
	return tab;
}
コード例 #11
0
ファイル: hex-binary.c プロジェクト: aosm/dovecot
const char *binary_to_hex_ucase(const unsigned char *data, size_t size)
{
	unsigned char *dest = t_malloc(size * 2 + 1);

	binary_to_hex_case(dest, data, size, TRUE);
	dest[size*2] = '\0';
	return (char *)dest;
}
コード例 #12
0
ファイル: dip-obj.c プロジェクト: kadych/iscan
/*! \brief  Creates a LUT with an encoding \a gamma
 *
 *  \sa http://en.wikipedia.org/wiki/Gamma_correction
 */
LUT *
dip_gamma_LUT (const void *self, int depth,
               double gamma)
{
  SANE_Byte *lut;
  LUT       *m;

  size_t i;
  double max;

  require (dip == self);
  require (8 == depth || 16 == depth);

  lut = t_malloc ((1 << depth) * (depth / 8), SANE_Byte);
  m   = t_malloc (1, LUT);

  if (!lut || !m)
    {
      delete (lut);
      delete (m);
      return m;
    }

  m->lut   = lut;
  m->depth = depth;

  max = (1 << depth) - 1;

  for (i = 0; i < (1 << depth); ++i)
    {
      double value = max * pow (i / max, 1 / gamma);

      if (16 == depth)
        {
          uint16_t *p  = (uint16_t *) lut;

          p[i] = clamp (value, 0, max);
        }
      else
        {
          lut[i] = clamp (value, 0, max);
        }
    }

  return m;
}
コード例 #13
0
ファイル: ast.c プロジェクト: vivounicorn/eaburns.tc
/*
 * Makes an integer type node. 
 */
AstNode *
makeInt(unsigned int line)
{
  AstNode *p;

  p = t_malloc(memory, sizeof(AstNode));
  initAstNode(p, INT_NODE, line);

  return p;
}
コード例 #14
0
ファイル: client-common.c プロジェクト: aclindsa/dovecot_core
static const char *
client_get_log_str(struct client *client, const char *msg)
{
	static const struct var_expand_table static_tab[3] = {
		{ 's', NULL, NULL },
		{ '$', NULL, NULL },
		{ '\0', NULL, NULL }
	};
	static const struct var_expand_func_table func_table[] = {
		{ "passdb", client_var_expand_func_passdb },
		{ NULL, NULL }
	};
	const struct var_expand_table *var_expand_table;
	struct var_expand_table *tab;
	char *const *e;
	string_t *str, *str2;
	unsigned int pos;

	var_expand_table = get_var_expand_table(client);

	tab = t_malloc(sizeof(static_tab));
	memcpy(tab, static_tab, sizeof(static_tab));

	str = t_str_new(256);
	str2 = t_str_new(128);
	for (e = client->set->log_format_elements_split; *e != NULL; e++) {
		pos = str_len(str);
		var_expand_with_funcs(str, *e, var_expand_table,
				      func_table, client);
		if (have_username_key(*e)) {
			/* username is added even if it's empty */
		} else {
			str_truncate(str2, 0);
			var_expand(str2, *e, login_var_expand_empty_tab);
			if (strcmp(str_c(str)+pos, str_c(str2)) == 0) {
				/* empty %variables, don't add */
				str_truncate(str, pos);
				continue;
			}
		}

		if (str_len(str) > 0)
			str_append(str, ", ");
	}

	if (str_len(str) > 0)
		str_truncate(str, str_len(str)-2);

	tab[0].value = t_strdup(str_c(str));
	tab[1].value = msg;
	str_truncate(str, 0);

	var_expand(str, client->set->login_log_format, tab);
	return str_c(str);
}
コード例 #15
0
ファイル: ast.c プロジェクト: vivounicorn/eaburns.tc
/*
 * Makes a this (keyword) node. 
 */
AstNode *
makeThis(unsigned int line)
{
  Expr *p;

  p = t_malloc(memory, sizeof(Expr));
  initAstNode(NODE(p), THIS_NODE, line);
  initExpr(EXPR(p));

  return NODE(p);
}
コード例 #16
0
ファイル: doveadm-dump-log.c プロジェクト: Raffprta/core
static int dump_record(int fd, uint64_t *modseq)
{
	off_t offset;
	ssize_t ret;
	struct mail_transaction_header hdr;
	unsigned int orig_size;

	offset = lseek(fd, 0, SEEK_CUR);
	if (offset == -1)
		i_fatal("lseek() failed: %m");

	ret = read(fd, &hdr, sizeof(hdr));
	if (ret == 0)
		return 0;

	if (ret != sizeof(hdr)) {
		i_fatal("rec hdr read() %"PRIuSIZE_T" != %"PRIuSIZE_T,
			ret, sizeof(hdr));
	}

	orig_size = hdr.size;
	hdr.size = mail_index_offset_to_uint32(hdr.size);
	if (hdr.size == 0) {
		printf("record: offset=%"PRIuUOFF_T", "
		       "type=%s, size=broken (%x)\n",
		       offset, log_record_type(hdr.type), orig_size);
		return 0;
	}

	printf("record: offset=%"PRIuUOFF_T", type=%s, size=%u",
	       offset, log_record_type(hdr.type), hdr.size);
	if (*modseq > 0 && mail_transaction_header_has_modseq(&hdr)) {
		*modseq += 1;
		printf(", modseq=%llu", (unsigned long long)*modseq);
	}
	printf("\n");

	if (hdr.size < sizeof(hdr)) {
		i_fatal("Invalid header size %u", hdr.size);
	} else if (hdr.size < 1024*1024) {
		unsigned char *buf = t_malloc(hdr.size);

		ret = read(fd, buf, hdr.size - sizeof(hdr));
		if (ret != (ssize_t)(hdr.size - sizeof(hdr))) {
			i_fatal("rec data read() %"PRIuSIZE_T" != %"PRIuSIZE_T,
				ret, hdr.size - sizeof(hdr));
		}
		log_record_print(&hdr, buf, (size_t)ret, modseq);
	} else {
		if (lseek(fd, hdr.size - sizeof(hdr), SEEK_CUR) < 0)
			i_fatal("lseek() failed: %m");
	}
	return 1;
}
コード例 #17
0
ファイル: ast.c プロジェクト: vivounicorn/eaburns.tc
/*
 * Creates a null literal node. 
 */
AstNode *
makeNullLit(unsigned int line)
{
  Expr *p;

  p = t_malloc(memory, sizeof(Expr));
  initAstNode(NODE(p), NULLLIT_NODE, line);
  initExpr(EXPR(p));

  return NODE(p);
}
コード例 #18
0
ファイル: ast.c プロジェクト: vivounicorn/eaburns.tc
/*
 * Makes a super (keyword) node. 
 */
AstNode *
makeSuper(unsigned int line)
{
  Expr *p;

  p = t_malloc(memory, sizeof(Expr));
  initAstNode(NODE(p), SUPER_NODE, line);
  initExpr(EXPR(p));

  return NODE(p);
}
コード例 #19
0
static const void *_file_lazy_load_data
(struct sieve_binary_file *file, off_t *offset, size_t size)
{
	void *data = t_malloc(size);

	if ( _file_lazy_read(file, offset, data, size) ) {
		return data;
	}

	return NULL;
}
コード例 #20
0
ファイル: ast.c プロジェクト: vivounicorn/eaburns.tc
AstNode *
makeExprSt(AstNode *expr)
{
  ExprSt *p;

  p = t_malloc(memory, sizeof(ExprSt));
  initAstNode(NODE(p), EXPRST_NODE, expr->line);

  p->expr = expr;

  return NODE(p);
}
コード例 #21
0
ファイル: ast.c プロジェクト: vivounicorn/eaburns.tc
/*
 * Makes an array node. 
 */
AstNode *
makeArray(AstNode * child, unsigned int line)
{
  Array *p;

  p = t_malloc(memory, sizeof(Array));
  initAstNode(NODE(p), ARRAY_NODE, line);

  p->child = child;

  return NODE(p);
}
コード例 #22
0
ファイル: ast.c プロジェクト: vivounicorn/eaburns.tc
/*
 * Make an out statement node. 
 */
AstNode *
makeOutSt(AstNode * expr, unsigned int line)
{
  OutSt *p;

  p = t_malloc(memory, sizeof(OutSt));
  initAstNode(NODE(p), OUT_NODE, line);

  p->expr = expr;

  return NODE(p);
}
コード例 #23
0
ファイル: ast.c プロジェクト: vivounicorn/eaburns.tc
/*
 * Makes a main function declaration node. 
 */
AstNode *
makeMainFunc(AstNode * body, unsigned int line)
{
  MainFunc *p;

  p = t_malloc(memory, sizeof(MainFunc));
  initAstNode(NODE(p), MAINFUNC_NODE, line);

  p->body = body;

  return NODE(p);
}
コード例 #24
0
ファイル: ast.c プロジェクト: vivounicorn/eaburns.tc
/*
 * Makes a name identifier node. 
 */
AstNode *
makeNameId(Literal * name)
{
  NameId *p;

  p = t_malloc(memory, sizeof(NameId));
  initAstNode(NODE(p), NAMEID_NODE, name->line);

  p->name = name->str;

  return NODE(p);
}
コード例 #25
0
ファイル: ast.c プロジェクト: vivounicorn/eaburns.tc
/*
 * Makes a return node. 
 */
AstNode *
makeReturnSt(AstNode * expr, unsigned int line)
{
  ReturnSt *p;

  p = t_malloc(memory, sizeof(ReturnSt));
  initAstNode(NODE(p), RETURN_NODE, line);

  p->expr = expr;

  return NODE(p);
}
コード例 #26
0
ファイル: ast.c プロジェクト: vivounicorn/eaburns.tc
/*
 * Makes a delete node. 
 */
AstNode *
makeDeleteSt(AstNode * expr, unsigned int line)
{
  DeleteSt *p;

  p = t_malloc(memory, sizeof(DeleteSt));
  initAstNode(NODE(p), DELETE_NODE, line);

  p->expr = expr;

  return NODE(p);
}
コード例 #27
0
ファイル: trapeze_orb_boa.c プロジェクト: berkus/flick
CORBA_ReferenceData *CORBA_BOA_get_id(CORBA_BOA ths, FLICK_TARGET obj,
				      CORBA_Environment *ev)
{
	CORBA_ReferenceData *res = t_malloc(CORBA_ReferenceData, 1);
	
	if (!res) {
		flick_set_exception(ths, ev, ex_CORBA_NO_MEMORY,
				    0, CORBA_COMPLETED_NO);
		return 0;
	}
	*res = obj->u.info.key;
	return res;
}
コード例 #28
0
ファイル: ast.c プロジェクト: vivounicorn/eaburns.tc
/*
 * Creates an integer literal node with the given value. 
 */
AstNode *
makeIntLit(Literal * value)
{
  IntLit *p;

  p = t_malloc(memory, sizeof(IntLit));
  initAstNode(NODE(p), INTLIT_NODE, value->line);
  initExpr(EXPR(p));

  p->str = value->str;

  return NODE(p);
}
コード例 #29
0
ファイル: ast.c プロジェクト: vivounicorn/eaburns.tc
/*
 * Makes an expression identifier node. 
 */
AstNode *
makeExprId(Literal * name)
{
  ExprId *p;

  p = t_malloc(memory, sizeof(ExprId));
  initAstNode(NODE(p), EXPRID_NODE, name->line);
  initExpr(EXPR(p));

  p->name = name->str;

  return NODE(p);
}
コード例 #30
0
ファイル: ast.c プロジェクト: vivounicorn/eaburns.tc
/*
 * Makes a while statement node. 
 */
AstNode *
makeWhileSt(AstNode * expr, AstNode * stats, unsigned int line)
{
  WhileSt *p;

  p = t_malloc(memory, sizeof(WhileSt));
  initAstNode(NODE(p), WHILE_NODE, line);

  p->expr = expr;
  p->stats = stats;

  return NODE(p);
}