static char rcsid[] = "$Id: C-expr-mem.c,v 1.8 2000/06/29 23:20:12 m-hirano Exp $";
/* 
 * $RWC_Release: Omni-1.6 $
 * $RWC_Copyright:
 *  Omni Compiler Software Version 1.5-1.6
 *  Copyright (C) 2002 PC Cluster Consortium
 *  
 *  This software is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License version
 *  2.1 published by the Free Software Foundation.
 *  
 *  Omni Compiler Software Version 1.0-1.4
 *  Copyright (C) 1999, 2000, 2001.
 *   Tsukuba Research Center, Real World Computing Partnership, Japan.
 *  
 *  Please check the Copyright and License information in the files named
 *  COPYRIGHT and LICENSE under the top  directory of the Omni Compiler
 *  Software release kit.
 *  
 *  
 *  $
 */
/* C-front memory management */
#include "C-front.h"

/* no garbage collector, sorry. */
#define XMALLOC(t,size)	((t)xmalloc(size))

/* allocate memory and initialize 0 */
char   * xmalloc(int size)
{
    char   *p;
    p = (char *) malloc(size);
    if ( p == NULL )
	fatal("no memory");
    bzero(p, size);
    return (p);
}

#ifndef HAVE_STRDUP
char *
strdup(s)
     char *s;
{
    char *p;
    int len = strlen(s);
    
    p = XMALLOC(char *, len + 1);
    memcpy(p, s, len);
    p[len] = '\0';
    return p;
}
#endif /* !HAVE_STRDUP */

/* hash table size for symbol name */
#define SYMBOL_HASH_SIZE	0x400
#define SYMBOL_HASH_MASK	(SYMBOL_HASH_SIZE - 1)
SYMBOL  symbol_hash_table[SYMBOL_HASH_SIZE];

/*
 * search hash table for 'name'
 * if not, create and link it to hash entry(not set type, s_value)
 */
SYMBOL  find_symbol(name)
    char   *name;
{
    SYMBOL  sp;
    int     hcode;
    char   *cp;

    /* hash code, bad ?? */
    hcode = 0;
    for( cp = name ; *cp != 0 ; cp++ )
	hcode = (hcode << 1) + *cp;
    hcode &= SYMBOL_HASH_MASK;

    for (sp = symbol_hash_table[hcode] ; sp != NULL ; sp = sp->s_next)
	if (strcmp(name, sp->s_name) == 0)
	    return (sp);

	/* not found, allocate symbol structure */
    sp = XMALLOC(SYMBOL, sizeof(*sp));
    sp->s_name = strdup(name);

    /* link it(as top of the hash list) */
    sp->s_next = symbol_hash_table[hcode];
    symbol_hash_table[hcode] = sp;
    return (sp);
}

/* lineno */
lineno_info *new_line_info(fid,ln)
     int fid,ln;
{
    lineno_info *l;
    l = XMALLOC(lineno_info *, sizeof(*l));
    l->file_id = fid;
    l->ln_no = ln;
    return l;
}

/* allocate expression_node and init as arg (for int,etc) */
expr
make_enode(code, v)
     enum expr_code code;
     void *v;
{
    expr    ep;

    ep = XMALLOC(expr, sizeof(*ep));
    ep->e_code = code;
    ep->e_line = current_line;
    ep->v.e_gen = v;
    return (ep);
}

/* for char constant def */
expr make_char_enode(code, v)
     enum expr_code code;
     int     v;
{
    expr  ep;

    ep = make_enode(code, (void *)((_omAddrInt_t)v));
    ep->e_type = basic_type_desc[CHAR];
    return (ep);
}

/* allocate expression_node and init as arg(for double) */
expr    make_float_enode(d)
    double  d;
{
    expr    ep;

    ep = XMALLOC(expr, sizeof(*ep));
    ep->e_code = FLOAT_CONSTANT;
    ep->e_line = current_line;
    ep->v.e_fval = d;
    return (ep);
}

/* allocate expression_node and init as arg(for longlong) */
expr    make_longlong_enode(l, h)
    int     l, h;
{
    expr    ep;

    ep = XMALLOC(expr, sizeof(*ep));
    ep->e_code = LONGLONG_CONSTANT;
    ep->e_line = current_line;
    ep->v.e_llval.l = l;
    ep->v.e_llval.h = h;
    return (ep);
}

/* add expr 'x' to the list 'l' as list head */
struct list_node *cons_list(x, l)
    expr    x;
    struct list_node *l;
{
    struct list_node *lp;

    lp = XMALLOC(struct list_node *, sizeof(struct list_node));
    lp->l_next = l;
    lp->l_item = x;
    return (lp);
}


/* expression list */
/* only 1 level for union(e_lp) link, others(last #) are next list link */

/* return alloced EXPR */
expr    list0(code)
    enum expr_code code;
{
    expr    ep;

    ep = XMALLOC(expr, sizeof(*ep));
    ep->e_code = code;
    return (ep);
}

/* return alloced EXPR, with link to 'x1' for its union elm */
expr    list1(code, x1)
    enum expr_code code;
    expr    x1;
{
    expr    ep;

    ep = XMALLOC(expr, sizeof(*ep));
    ep->e_code = code;
    ep->v.e_lp = cons_list(x1, (struct list_node *)NULL);
    return (ep);
}

expr    list2(code, x1, x2)
    enum expr_code code;
    expr    x1, x2;
{
    expr    ep;

    ep = XMALLOC(expr, sizeof(*ep));
    ep->e_code = code;
    ep->v.e_lp = cons_list(x1, cons_list(x2, (struct list_node *)NULL));
    return (ep);
}

expr    list3(code, x1, x2, x3)
    enum expr_code code;
    expr    x1, x2, x3;
{
    expr    ep;

    ep = XMALLOC(expr, sizeof(*ep));
    ep->e_code = code;
    ep->v.e_lp = cons_list(x1, cons_list(x2, cons_list(x3, (struct list_node *)NULL)));
    return (ep);
}

expr    list4(code, x1, x2, x3, x4)
    enum expr_code code;
    expr    x1, x2, x3, x4;
{
    expr    ep;

    ep = XMALLOC(expr, sizeof(*ep));
    ep->e_code = code;
    ep->v.e_lp = cons_list(x1, cons_list(x2, cons_list(x3, cons_list(x4, (struct list_node *)NULL))));
    return (ep);
}

/*
 * make expression node for yacc interface
 */
expr    elist0(lineno, code)
     lineno_info *lineno;
     enum expr_code code;
{
    expr ep;
    ep = list0(code);
    ep->e_line = lineno;
    return ep;
}

expr    elist1(lineno, code, x1)
     lineno_info *lineno;
    enum expr_code code;
    expr    x1;
{
    expr ep;
    ep = list1(code,x1);
    ep->e_line = lineno;
    return ep;
}

expr    elist2(lineno, code, x1, x2)
     lineno_info *lineno;
    enum expr_code code;
    expr    x1, x2;
{
    expr ep;
    ep = list2(code,x1,x2);
    ep->e_line = lineno;
    return ep;
}

expr    elist3(lineno, code, x1, x2, x3)
     lineno_info *lineno;
    enum expr_code code;
    expr    x1, x2, x3;
{
    expr ep;
    ep = list3(code,x1,x2,x3);
    ep->e_line = lineno;
    return ep;
}

expr    elist4(lineno, code, x1, x2, x3, x4)
     lineno_info *lineno;
    enum expr_code code;
    expr    x1, x2, x3, x4;
{
    expr ep;
    ep = list4(code,x1,x2,x3,x4);
    ep->e_line = lineno;
    return ep;
}

/* add expr 'x' as last node of list 'ex' */
expr    list_put_last(lx, x)
    expr    lx;
    expr    x;
{
    struct list_node *lp;

    if (lx == NULL)
	return (lx);		/* error recovery in C-parser.y */

    lp = lx->v.e_lp;
    if ( lp == NULL )
	lx->v.e_lp = cons_list(x, (struct list_node *)NULL);
    else {
	for ( ; lp->l_next != NULL ; lp = lp->l_next)
	    ;
	lp->l_next = cons_list(x, (struct list_node *)NULL);
    }
    return (lx);
}
