static char rcsid[] = "$Id: F-data.c,v 1.46 2003/03/26 18:54:20 msato 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.
 *  
 *  
 *  $
 */
#include "F-front.h"


static char *varInitTypeStr[] = {
    "never",
    "whole array",
    "substring",
    "array elements",
    "equivalence",
    NULL
};

static expv
serializeInitialValue(x, new)
     expr x;
     expv new;
{
    if (new == NULL) {
	new = list0(LIST);
    }
    switch (EXPR_CODE(x)) {
	case LIST: {
	    list lp;
	    expr xL;
	    
	    FOR_ITEMS_IN_LIST(lp, x) {
		xL = LIST_ITEM(lp);
		new = serializeInitialValue(xL, new);
		if (new == NULL) {
		    return NULL;
		}
	    }
	    break;
	}

	case F_DUP_DECL: {
	    expv numV = expr_constant_value(EXPR_ARG1(x), TRUE);
	    expv valV = expr_constant_value(EXPR_ARG2(x), FALSE);
	    int num = 0;
	    int i;

	    if (numV == NULL ||
		valV == NULL) {
		error("not constant.");
		return NULL;
	    }

	    if (!BASIC_IS_INT(getBasicType(EXPV_TYPE(numV)))) {
		error("multiplier is not an integer value.");
		return NULL;
	    }
#ifdef HAS_INT64
	    if (getBasicType(EXPV_TYPE(numV)) == TYPE_LONGLONG) {
		num = (int)EXPV_INT64_VALUE(numV);
	    } else {
		num = EXPV_INT_VALUE(numV);
	    }		
#else
	    num = EXPV_INT_VALUE(numV);
#endif /* HAS_INT64 */
	    if (num == 0) {
		error("illegal initialize value list number, zero.");
		return NULL;
	    }
	    
	    for (i = 0; i < num; i++) {
		new = list_put_last(new, valV);
	    }
	    break;
	}

	default: {
	    expv valV = expr_constant_value(x, FALSE);
	    if (valV == NULL) {
		error("not constant.");
		return NULL;
	    }
	    new = list_put_last(new, valV);
	    break;
	}
    }

    return new;
}


static expv
findArrayRef(spec, new)
     expv spec;
     expv new;
{
    list lp;
    expv v;

    if (new == NULL) {
	new = list0(LIST);
    }

    FOR_ITEMS_IN_LIST(lp, spec) {
	v = LIST_ITEM(lp);
	if (v == NULL) {
	    continue;
	}

	switch (EXPR_CODE(v)) {
	    
	    case F_ARRAY_REF: {
		new = list_put_last(new, v);
		break;
	    }

	    default: {
		if (EXPR_CODE_IS_TERMINAL(EXPR_CODE(v)) != TRUE) {
		    new = findArrayRef(v, new);
		}
		break;
	    }
	}
    }
    
    return new;
}


static expv
getVariableSpec(v, idPtr)
     expv v;
     ID *idPtr;
{
    ID id;
    expv ret = NULL;
    expv iList = NULL;
    expv aList = NULL;

    if (idPtr != NULL) {
	*idPtr = NULL;
    }

    if (expr_is_variable(v, TRUE, &id) != TRUE) {
	if (id != NULL) {
	    if (ID_CLASS(id) == CL_PROC) {
		if (PROC_CLASS(id) == P_THISPROC) {
		    error("can't give data to '%s'.", ID_NAME(id));
		    return NULL;
		}
	    }
	    error("'%s' is not a variable.", ID_NAME(id));
	} else {
	    error("not a variable.");
	}
	return NULL;
    }
    ret = expr_array_spec_list(v, &id);

    if (idPtr != NULL) {
	*idPtr = id;
    }

    if (VAR_INIT_LIST(id) == NULL) {
	if (IS_ARRAY_TYPE(ID_TYPE(id))) {
	    list lp;
	    int numElem = 1;
	    int i;

	    if (ret == NULL) {
		fatal("'%s' is array but can't determine array spec??", ID_NAME(id));
	    }
	    FOR_ITEMS_IN_LIST(lp, EXPR_ARG2(ret)) {
		numElem *= EXPV_INT_VALUE(EXPR_ARG1(LIST_ITEM(lp)));
	    }

	    iList = list1(LIST, expv_int_term(INT_CONSTANT, type_INT, numElem));
	    aList = list0(LIST);
	    for (i = 0; i < numElem; i++) {
		list_put_last(aList, NULL);
	    }
	    list_put_last(iList, aList);
	} else {
	    iList = list1(LIST, expv_int_term(INT_CONSTANT, type_INT, 1));
	    aList = list0(LIST);
	    list_put_last(aList, NULL);
	    list_put_last(iList, aList);
	}
	VAR_INIT_LIST(id) = iList;
    } else {
	ret = VAR_ARRAY_INFO(id);
    }
    
    return ret;
}


static int
checkSubstrOverlap(rngList, rng, varName)
     expv rngList;
     expv rng;
     char *varName;
{
    list lp;
    int sStart;
    int sEnd;
    int dStart;
    int dEnd;

    sStart = EXPV_INT_VALUE(EXPR_ARG1(rng));
    sEnd = EXPV_INT_VALUE(EXPR_ARG2(rng));
    FOR_ITEMS_IN_LIST(lp, rngList) {
	dStart = EXPV_INT_VALUE(EXPR_ARG1(LIST_ITEM(lp)));
	dEnd = EXPV_INT_VALUE(EXPR_ARG2(LIST_ITEM(lp)));

	if (sStart >= dStart &&
	    sEnd <= dEnd) {
	    goto overLap;
	}
	if (dStart >= sStart &&
	    dStart <= dEnd) {
	    goto overLap;
	}
	if (sStart >= dStart &&
	    sStart <= dEnd) {
	    goto overLap;
	}
	if (sEnd >= dStart &&
	    sEnd <= dEnd) {
	    goto overLap;
	}
	continue;

	overLap:
	error("substring range overlapping initialization in \"%s\", %d:%d and %d:%d.",
	      varName,
	      dStart, dEnd,
	      sStart, sEnd);
	return FALSE;
    }
    return TRUE;
}


static expv
genImpliedDo(loopSpec, dim, lvl, refSpec)
     expv loopSpec;
     int dim;
     int lvl;
     expv refSpec;
{
    expv new = NULL;

    if (lvl < dim) {
	expv cV;
	new = list0(F_IMPLIED_DO);
	new = list_put_last(new, expr_list_get_n(loopSpec, lvl));
	cV = genImpliedDo(loopSpec, dim, lvl + 1, refSpec);
	if (cV != NULL) {
	    new = list_put_last(new, list1(LIST, cV));
	}
    } else {
	new = refSpec;
    }
    return new;
}


static expv
serializeVariable(v, new)
     expv v;
     expv new;
{
    ID id;

    if (new == NULL) {
	new = list0(LIST);
    }
    switch (EXPR_CODE(v)) {
	case F_IMPLIED_DO: {
	    list lp;
	    expr x;
	    expv refList = findArrayRef(v, (expv)NULL);
	    
	    FOR_ITEMS_IN_LIST(lp, refList) {
		x = LIST_ITEM(lp);

		getVariableSpec(x, &id);
		if (id == NULL) {
		    return NULL;
		}
		if (VAR_INIT_TYPE(id) != VAR_INIT_NEVER &&
		    VAR_INIT_TYPE(id) != VAR_INIT_PARTIAL) {
		    error("\"%s\" is already initialized as %s.",
			  SYM_NAME(ID_SYM(id)),
			  varInitTypeStr[VAR_INIT_TYPE(id)]);
		    return NULL;
		}
		VAR_INIT_TYPE(id) = VAR_INIT_PARTIAL;
	    }

	    new = ExpandImpliedDoInDATA(v, new);
	    break;
	}

	case LIST: {
	    list lp;
	    expr x;

	    FOR_ITEMS_IN_LIST(lp, v) {
		x = LIST_ITEM(lp);
		new = serializeVariable(x, new);
		if (new == NULL) {
		    return NULL;
		}
	    }
	    break;
	}

	case IDENT: {
	    expv asV = getVariableSpec(v, &id);
	    if (id == NULL) {
		return NULL;
	    }
	    if (VAR_INIT_TYPE(id) != VAR_INIT_NEVER) {
		error("\"%s\" is already initialized as %s.",
		      SYM_NAME(ID_SYM(id)),
		      varInitTypeStr[VAR_INIT_TYPE(id)]);
		return NULL;
	    }
	    VAR_INIT_TYPE(id) = VAR_INIT_WHOLE;

	    if (asV != NULL) {
		/*
		 * Initialize whole array.
		 */
		int nDim = EXPV_INT_VALUE(EXPR_ARG1(asV));
		int i;
		expv ll;
		SYMBOL sp;
		char varName[64];
		expv var;
		expv vL;
		expv refSpec;
		expv loopSpec = list0(LIST);
		expv doSpec;
		ID dumId;

		for (i = 0; i < nDim; i++) {
		    ll = expr_list_get_n(EXPR_ARG2(asV), nDim - i -1);
		    if (ll == NULL) {
			error("can't initialize %s.", SYM_NAME(ID_SYM(id)));
			return NULL;
		    }
		    sprintf(varName, "__ImpDoIdx_%c", 'i' + nDim - i -1);
		    sp = f_find_symbol(varName);
		    dumId = declare_ident(sp, CL_VAR);
		    declare_id_type(dumId, type_INT);
		    declare_variable(dumId);
		    VAR_IS_IMPLIED_DO_DUMMY(dumId) = TRUE;
		    var = list0(LIST);
		    var = list_put_last(var, make_enode(IDENT, (void *)sp));
		    var = list_put_last(var, EXPR_ARG2(ll));
		    var = list_put_last(var, EXPR_ARG3(ll));
		    var = list_put_last(var, NULL);
		    loopSpec = list_put_last(loopSpec, var);
		}
		vL = list0(LIST);

		for (i = 0; i < nDim; i++) {
		    ll = expr_list_get_n(loopSpec, nDim - i - 1);
		    vL = list_put_last(vL, EXPR_ARG1(ll));
		}
		refSpec = list2(F_ARRAY_REF, v, vL);

		doSpec = genImpliedDo(loopSpec, nDim, 0, refSpec);
		new = ExpandImpliedDoInDATA(doSpec, new);
	    } else {
		new = list_put_last(new, v);
	    }
	    break;
	}

	case F_ARRAY_REF: {
	    expv idxV = NULL;
	    expv newV;
	    expv asV = getVariableSpec(v, &id);
	    if (id == NULL) {
		return NULL;
	    }
	    if (asV == NULL) {
		error("'%s' is not an array.", ID_NAME(id));
	    }
	    if (VAR_INIT_TYPE(id) != VAR_INIT_NEVER &&
		VAR_INIT_TYPE(id) != VAR_INIT_PARTIAL) {
		error("\"%s\" is already initialized as %s.",
		      SYM_NAME(ID_SYM(id)),
		      varInitTypeStr[VAR_INIT_TYPE(id)]);
		return NULL;
	    }
	    VAR_INIT_TYPE(id) = VAR_INIT_PARTIAL;
	    idxV = expr_array_index(v);
	    if (idxV == NULL) {
		return NULL;
	    }
	    newV = list2(F_ARRAY_REF, EXPR_ARG1(v), idxV);
	    new = list_put_last(new, newV);
	    break;
	}

	case F_SUBSTR_REF: {
	    expv vTmp = compile_expression(v);
	    ID id;
	    expv vList;
	    expv newV;
	    expv rng;
	    int rStart;
	    int rEnd;
	    int maxLen;

	    if (vTmp == NULL ||
		!IS_CHAR(EXPV_TYPE(vTmp))) {
		fatal("sub string not char???");
	    }

	    getVariableSpec(EXPR_ARG1(v), &id);
	    if (id == NULL) {
		return NULL;
	    }
	    if (VAR_INIT_TYPE(id) != VAR_INIT_NEVER &&
		VAR_INIT_TYPE(id) != VAR_INIT_SUBSTR) {
		error("\"%s\" is already initialized as %s.",
		      SYM_NAME(ID_SYM(id)),
		      varInitTypeStr[VAR_INIT_TYPE(id)]);
		return NULL;
	    }
	    VAR_INIT_TYPE(id) = VAR_INIT_SUBSTR;
	    
	    maxLen = type_length(ID_TYPE(id)); 
	    vList = EXPR_ARG2(VAR_INIT_LIST(id));

	    if (EXPR_ARG1(EXPR_ARG2(v)) == NULL) {
		rStart = 1;
	    } else {
		rStart = EXPV_INT_VALUE(EXPR_ARG1(EXPR_ARG2(v)));
	    }
	    if (EXPR_ARG2(EXPR_ARG2(v)) == NULL) {
		rEnd = maxLen;
	    } else {
		rEnd = EXPV_INT_VALUE(EXPR_ARG2(EXPR_ARG2(v)));
	    }
	    if (rStart > rEnd) {
		error("invalid substring range.");
		return NULL;
	    }
	    if (rStart < 1 || rEnd < 1) {
		error("substring range less than one.");
		return NULL;
	    }
	    if (rEnd > maxLen || rStart > maxLen) {
		error("substring range greater than %d.", maxLen);
		return NULL;
	    }

	    rng = list2(LIST,
			expv_int_term(INT_CONSTANT, type_INT, rStart - 1),
			expv_int_term(INT_CONSTANT, type_INT, rEnd - 1));

	    if (EXPR_ARG1(vList) != NULL) {
		if (checkSubstrOverlap(vList, rng, SYM_NAME(ID_SYM(id))) == FALSE) {
		    return NULL;
		}
		vList = list_put_last(vList, rng);
	    } else {
		EXPR_ARG1(vList) = rng;
		EXPR_ARG1(VAR_INIT_LIST(id)) = expv_int_term(INT_CONSTANT,
							     type_INT,
							     maxLen);
	    }
	    EXPR_ARG2(VAR_INIT_LIST(id)) = vList;

	    newV = expv_sym_term(IDENT, ID_TYPE(id), EXPR_SYM(EXPR_ARG1(v)));
	    new = list_put_last(new, newV);
	    break;
	}

	default: {
	    error("invalid type in DATA statement.");
	    return NULL;
	}
    }

    return new;
}


static char idxStrBuf[4096];
static char *
idxToStr(v)
     expr v;
{
    list lp;
    char buf[4096];
    int len;
    memset(idxStrBuf, 0, 4096);

    FOR_ITEMS_IN_LIST(lp, v) {
	sprintf(buf, "%d,", EXPV_INT_VALUE(LIST_ITEM(lp)));
	strcat(idxStrBuf, buf);
    }
    len = strlen(idxStrBuf);
    idxStrBuf[len - 1] = '\0';

    return idxStrBuf;
}

char *
adjustString(str, strLen, maxLen)
     char *str;
     int strLen;
     int maxLen;
{
#define Min(a, b) (((a) > (b)) ? (b) : (a))
    int cpLen = Min(strLen, maxLen);
    char *newStr = (char *)malloc(sizeof(char) * (maxLen + 1));
    memset(newStr, DEFAULT_UNINITED_CHAR, maxLen);
    if (strLen > 0) {
	memcpy(newStr, str, cpLen);
    }
    newStr[maxLen] = '\0';
    return newStr;
#undef Min
}


static void
setInitialValue(vrV, vlV)
     expv vrV;	/* variable expression */
     expv vlV;	/* value expresssion */
{
    ID id;
    expv aSpec = getVariableSpec(vrV, &id);
    expv tryAssign = NULL;
    BASIC_DATA_TYPE rHTyp;
    BASIC_DATA_TYPE lHTyp;
    expv rHV = NULL;
    expv lHV = NULL;

    if (id == NULL) {
	return;
    }
    if (ID_CLASS(id) == CL_PROC) {
	if (PROC_CLASS(id) == P_THISPROC) {
	    error("can't give data to '%s'.", ID_NAME(id));
	    return;
	}
    }

    if (ID_STORAGE(id) != STG_BSS &&
	ID_STORAGE(id) != STG_COMMON &&
	ID_STORAGE(id) != STG_COMEQ &&
	ID_STORAGE(id) != STG_EQBLK) {
	ID_STORAGE(id) = STG_BSS;
	VAR_IS_SAVE(id) = TRUE;
	ID_IS_DECLARED(id) = FALSE;
	declare_variable(id);
    }

    if (VAR_INIT_TYPE(id) == VAR_INIT_SUBSTR) {
	list lp;
	expv last = NULL;
	int rLen;
	int vLen;
	expv vExp;

	if (!BASIC_IS_CHAR(getBasicType(EXPV_TYPE(vlV)))) {
	    error("initializer type is not a character.");
	    return;
	}
	FOR_ITEMS_IN_LIST(lp, EXPR_ARG2(VAR_INIT_LIST(id))) {
	    last = LIST_ITEM(lp);
	}

	rLen = EXPV_INT_VALUE(EXPR_ARG2(last)) - EXPV_INT_VALUE(EXPR_ARG1(last)) + 1;
	vLen = strlen(EXPV_STR(vlV));
	
	if (rLen != vLen) {
	    warning("length of substring range (%d) and length of \"%s\" (%d) is not match.",
		    rLen, EXPV_STR(vlV), vLen);
	}

	vExp = list3(LIST,
		     expv_int_term(INT_CONSTANT, type_INT, rLen),
		     expv_int_term(INT_CONSTANT, type_INT, vLen),
		     vlV);
	list_put_last(last, vExp);
	
	return;
    }

    rHV = compile_expression(vlV);
    if (rHV == NULL) {
	return;
    }
    /*
     * Special case. If the right hand value is numerical zero, do nothing.
     */
    if (expr_is_constant_zero(rHV)) {
	if (aSpec != NULL) {
	    return;
	}
    }

    lHV = compile_expression(vrV);
    if (lHV == NULL) {
	return;
    }
    rHTyp = getBasicType(EXPV_TYPE(rHV));
    lHTyp = getBasicType(EXPV_TYPE(lHV));

    if (EXPR_CODE(vlV) == COMPLEX_CONSTANT) {
	if (lHTyp == TYPE_COMPLEX || lHTyp == TYPE_DCOMPLEX) {
	    expv nV = list2(LIST, EXPR_ARG1(vlV), EXPR_ARG2(vlV));
	    EXPV_TYPE(nV) = EXPV_TYPE(vlV);
	    vlV = nV;
	} else {
	    vlV = EXPR_ARG1(vlV);
	}
	goto doSet;
    }

    if (lHTyp == TYPE_COMPLEX || lHTyp == TYPE_DCOMPLEX) {
	expv nV;
	if (BASIC_IS_COMPLEX(lHTyp) && BASIC_IS_CHAR(rHTyp)) {
	    goto doStr2Num;
	}
	if (EXPR_CODE(vlV) == COMPLEX_CONSTANT) {
	    nV = list2(LIST, EXPR_ARG1(vlV), EXPR_ARG2(vlV));
	    EXPV_TYPE(nV) = EXPV_TYPE(vlV);
	} else {
	    nV = list2(LIST, vlV,
		       expv_int_term(INT_CONSTANT, type_INT, 0));
	    EXPV_TYPE(nV) = EXPV_TYPE(lHV);
	}
	vlV = nV;
	goto doSet;
    }

#ifdef ENABLE_QREAL
    if (lHTyp == TYPE_QREAL) {
	if (BASIC_IS_CHAR(rHTyp)) {
	    goto doStr2Num;
	}
	goto doSet;
    }
#endif /* ENABLE_QREAL */

    tryAssign = expv_assignment(lHV, vlV);
    if (tryAssign == NULL) {
	if (doPedanticDataType == TRUE) {
	    error("incompatible types in initialization, '%s'(%s) <- (%s).",
		  ID_NAME(id), basic_type_name(lHTyp), basic_type_name(rHTyp));
	    return;
	} else {
	    if ((BASIC_IS_CHAR(lHTyp)) && !(BASIC_IS_CHAR(rHTyp))) {
		/*
		 * String <- numeric assignment. Error no doubt.
		 */
		error("incompatible types in initialization, '%s'(%s) <- (%s).",
			ID_NAME(id),
			basic_type_name(lHTyp),
			basic_type_name(rHTyp));
		return;
	    } else if(lHTyp == TYPE_INT && EXPR_CODE(vlV) == STRING_CONSTANT){
		/* convert string constant(may be hollerith) to int */
		union { char c[4]; int i; } ci;
		char *cp = EXPR_STR(vlV);
		int i;
		if(strlen(cp) > 4){
		    error("string too long for initializing integer");
		    return;
		}
		for(i = 0; i < 4; i++){
		    if(*cp == '\0') ci.c[i] = ' ';
		    else ci.c[i] = *cp++;
		}
		setInitialValue(vrV, 
				expv_int_term(INT_CONSTANT,type_INT,ci.i));
		return;
	    } else if (!(BASIC_IS_CHAR(lHTyp)) && (BASIC_IS_CHAR(rHTyp))) {
		doStr2Num:
		if (ID_STORAGE(id) != STG_EQUIV &&
		    ID_STORAGE(id) != STG_COMEQ &&
		    ID_STORAGE(id) != STG_COMMON &&
		    VAR_EQUIV_BY_DATA(id) != TRUE) {
		    /*
		     * Generate an equivalence.
		     */
		    char fakeName[4096];
		    static int fakeIdNum = 0;
		    int fakeSize = type_length(ID_TYPE(id));
		    TYPE_DESC fakeTp = type_char(fakeSize);
		    ID newId = NULL;
		    expr equivStatement = NULL;

		    sprintf(fakeName, "__NumStrInit_%d", fakeIdNum++);
		    newId = declare_ident(c_find_symbol(fakeName), CL_VAR);
		    if (newId == NULL) {
			fatal("can't create fake id for numeric-string equivalence??");
		    }
		    ID_TYPE(newId) = fakeTp;
		    
		    equivStatement = list1(LIST,
					   list2(LIST,
						 expv_sym_term(IDENT, NULL, ID_SYM(newId)),
						 expv_sym_term(IDENT, NULL, ID_SYM(id))));
		    compile_EQUIVALENCE_decl(equivStatement, TRUE);
		    if (ID_STORAGE(id) != STG_COMEQ &&
			ID_STORAGE(id) != STG_EQUIV) {
			if(ID_STORAGE(id) == STG_BSS) 
			    VAR_IS_SAVE(id) = TRUE;
			ID_STORAGE(id) = STG_EQUIV;
			ID_STORAGE(newId) = STG_EQUIV;
		    }
		}
		goto doStr;
	    }
	}
    }

    doStr:
    if (IS_CHAR(EXPV_TYPE(rHV))) {
	int cLen = type_length(EXPV_TYPE(lHV));
	int oLen = strlen(EXPV_STR(vlV));
	vlV = expv_str_term(STRING_CONSTANT, type_char(cLen),
			    adjustString(EXPV_STR(vlV), oLen, cLen));
    }

    doSet:
    if (aSpec != NULL) {
	int off = compute_element_offset(aSpec, EXPR_ARG2(vrV));
	if (off < 0) {
	    return;
	}
	if (off >= EXPV_INT_VALUE(EXPR_ARG1(VAR_INIT_LIST(id)))) {
	    error("element index range error, %s(%s) -> %d >= %d.",
		  ID_NAME(id), idxToStr(EXPR_ARG2(vrV)),
		  off, EXPV_INT_VALUE(EXPR_ARG1(VAR_INIT_LIST(id))));
	    return;
	}
	if (expr_list_set_n(EXPR_ARG2(VAR_INIT_LIST(id)), off, vlV, FALSE) != TRUE) {
	    error("%s(%s) is already initialized.",
		  ID_NAME(id), idxToStr(EXPR_ARG2(vrV)));
	    return;
	}
    } else {
	if (LIST_ITEM(EXPV_LIST(EXPR_ARG2(VAR_INIT_LIST(id)))) != NULL) {
	    error("%s is already initialized.", ID_NAME(id));
	    return;
	}
	LIST_ITEM(EXPV_LIST(EXPR_ARG2(VAR_INIT_LIST(id)))) = vlV;
    }
}


static void
genDataStatement(x)
     expr x;
{
    int valNum = 0;
    int varNum = 0;
    int num = 0;
    list lp;
    int i;
    expv vrV;
    expv vlV;
    list vrLp;
    list vlLp;

    expv varList = serializeVariable(EXPR_ARG1(x), (expv)NULL);
    expv valList = serializeInitialValue(EXPR_ARG2(x), (expv)NULL);
    if (varList == NULL ||
	valList == NULL) {
	return;
    }
    FOR_ITEMS_IN_LIST(lp, varList) {
	varNum++;
    }
    FOR_ITEMS_IN_LIST(lp, valList) {
	valNum++;
    }

    num = (valNum > varNum) ? varNum : valNum;

    if (varNum != valNum) {
	warning("variable number (%d) is differ to initializer number (%d).",
		varNum, valNum);
    }

    for (i = 0, vrLp = EXPR_LIST(varList), vlLp = EXPR_LIST(valList);
	 i < num;
	 i++, vrLp = LIST_NEXT(vrLp), vlLp = LIST_NEXT(vlLp)) {
	vrV = LIST_ITEM(vrLp);
	vlV = LIST_ITEM(vlLp);
	setInitialValue(vrV, vlV);
    }
}


void
compile_DATA_decl(x)
     expr x;
{
    list lp;
    FOR_ITEMS_IN_LIST(lp, x) {
	genDataStatement(LIST_ITEM(lp));
    }
}
