/**CFile*********************************************************************** FileName [ioTable.c] PackageName [io] Synopsis [Routines for generating the table data structure from textual information. Used in the parser.] Description [] SeeAlso [] Author [Yuji Kukimoto, Rajeev Ranjan, Huey-Yih Wang] Copyright [Copyright (c) 1994-1996 The Regents of the Univ. of California. All rights reserved. Permission is hereby granted, without written agreement and without license or royalty fees, to use, copy, modify, and distribute this software and its documentation for any purpose, provided that the above copyright notice and the following two paragraphs appear in all copies of this software. IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.] ******************************************************************************/ #include "ioInt.h" static char rcsid[] UNUSED = "$Id: ioTable.c,v 1.8 2002/09/08 23:40:00 fabio Exp $"; /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static void _IoSymValueFree(IoSymValue_t *value); static int _IoSymCubeInsertInTable(Tbl_Table_t *table, array_t *symCube, int numIp, int numOp); static int _IoDefaultSymCubeInsertInTable(Tbl_Table_t *table, array_t *symCube, int numOp); static Tbl_Entry_t * _IoSymValueTransformToEntry(IoSymValue_t *value, Var_Variable_t *var, Tbl_Table_t *table); static int VariableReadIndex(Var_Variable_t *var, char *value); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Transforms table information stored in a special data structure IoPTable_t used by the parser to the table data structure.] Description [Transforms table information stored in a special data structure IoPTable_t used by the parser to the table data structure. The second and the third arguments and the model and the corresponding master hnode being parsed.] SideEffects [] SeeAlso [] ******************************************************************************/ Tbl_Table_t * IoPTableTransformToTable( Hrc_Model_t *model, Hrc_Node_t *hnode, IoPTable_t *pTable) { int i, numIo, numIp, numOp; char *input, *output; array_t *symCubes, *symCube; Tbl_Table_t *table; Var_Variable_t *var; symCubes = pTable->cubes; /* if neither symCubes nor default is set, the table is illegal */ if (symCubes == NIL(array_t) && pTable->defaultOutput == NIL(array_t)){ error_append("Error: Table "); error_append(array_fetch(char *,pTable->outputs,0)); error_append(" has neither relation nor default.\n"); return NIL(Tbl_Table_t); } /* partial check to see if symCubes is properly set up */ numIp = array_n(pTable->inputs); numOp = array_n(pTable->outputs); numIo = numIp + numOp; if (symCubes != NIL(array_t)){ for (i=0; i < array_n(symCubes); i++){ symCube = array_fetch(array_t *,symCubes,i); if (numIo != array_n(symCube)){ error_append("Error: The number of columns in the table where output "); error_append(array_fetch(char *,pTable->outputs,0)); error_append(" is defined is not equal to the number of input/output variables.\n"); return NIL(Tbl_Table_t); } } } table = Tbl_TableAlloc(); /* add input columns to the table */ for (i=0; i < array_n(pTable->inputs); i++){ input = array_fetch(char *,pTable->inputs,i); /* the following if should not fail due to the spec of IoVariableFindOrAllocByName() -- To be fixed */ if ((var = IoVariableFindOrAllocByName(hnode,input)) == NIL(Var_Variable_t)){ return NIL(Tbl_Table_t); } /* the following if should not fail due to the spec of Tbl_TableAddColumn() -- To be fixed */ if (Tbl_TableAddColumn(table,var,0) == 0){ return NIL(Tbl_Table_t); } } /* add output columns to the table */ for (i=0; i < array_n(pTable->outputs); i++){ output = array_fetch(char *,pTable->outputs,i); /* the following if should not fail due to the spec of IoVariableFindOrAllocByName() -- To be fixed */ if ((var = IoVariableFindOrAllocByName(hnode,output)) == NIL(Var_Variable_t)){ return NIL(Tbl_Table_t); } /* the following if should not fail due to the spec of Tbl_TableAddColumn() -- To be fixed */ if (Tbl_TableAddColumn(table,var,1) == 0){ return NIL(Tbl_Table_t); } } /* insert a cube one by one to the table */ if (symCubes != NIL(array_t)){ for (i=0; i < array_n(symCubes); i++){ symCube = array_fetch(array_t *,symCubes,i); if (_IoSymCubeInsertInTable(table, symCube, numIp, numOp) == 0){ Tbl_TableFree(table); return NIL(Tbl_Table_t); } } } /* check if the default and the output has the same number of variables */ if (pTable->defaultOutput != NIL(array_t) && array_n(pTable->outputs) != array_n(pTable->defaultOutput)){ error_append("Error: Default is not compatible with the number of outputs in output of "); error_append(array_fetch(char *,pTable->outputs,0)); error_append("\n"); Tbl_TableFree(table); return NIL(Tbl_Table_t); } /* insert the default cube to the table */ if (_IoDefaultSymCubeInsertInTable(table, pTable->defaultOutput, numOp) == 0) { Tbl_TableFree(table); return NIL(Tbl_Table_t); } return table; } /**Function******************************************************************** Synopsis [Allocates a IoSymValue_t.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ IoSymValue_t * IoSymValueAlloc(void) { return ALLOC(IoSymValue_t,1); } /**Function******************************************************************** Synopsis [Frees an array of the IoSymValue_t data structure.] Description [Frees an array of the IoSymValue_t data structure. All the elements of the array are also freed.] SideEffects [] SeeAlso [] ******************************************************************************/ void IoSymValueArrayFree(array_t *valueArray) { int i; for (i=0; i < array_n(valueArray); i++){ _IoSymValueFree(array_fetch(IoSymValue_t *,valueArray,i)); } array_free(valueArray); } /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Frees the IoSymValue_t data structure.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ static void _IoSymValueFree(IoSymValue_t *value) { IoSymValueType flag; /* if flag == IoUniverse_c, we have no extra work to do */ if ((flag = value->flag) == IoLeaf_c ){ FREE(value->left); } if (flag == IoRange_c){ FREE(value->left); FREE(value->right); } if (flag == IoComplement_c){ _IoSymValueFree(value->left); } if (flag == IoList_c){ int i; IoSymValue_t *valueTmp; for (i=0; i < array_n(value->elements); i++){ valueTmp = array_fetch(IoSymValue_t *,value->elements,i); _IoSymValueFree(valueTmp); } array_free(value->elements); } if (flag == IoAssign_c){ FREE(value->left); } FREE(value); } /**Function******************************************************************** Synopsis [Given a symbolic cube in textual format and a table, updates the table by adding the cube.] Description [Given a symbolic cube in textual format and a table, updates the table by adding the cube. The arguments are a pointer to the working table, a cube to be inserted in textual format, the number of inputs of the table, and the number of outputs of the table.] SideEffects [The new cube represented in symCube is inserted in the table.] SeeAlso [] ******************************************************************************/ static int _IoSymCubeInsertInTable( Tbl_Table_t *table, array_t *symCube, int numIp, int numOp) { int index, i; IoSymValue_t *symValue; Tbl_Entry_t *entry; /* get a new row for the cube */ index = Tbl_TableAddRow(table); for (i=0; i < numIp; i++){ symValue = array_fetch(IoSymValue_t *,symCube,i); entry = _IoSymValueTransformToEntry(symValue,Tbl_TableReadIndexVar(table,i,0),table); if (entry == NIL(Tbl_Entry_t)) return 0; Tbl_TableSetEntry(table,entry,index,i,0); } for (i=0; i < numOp; i++){ symValue = array_fetch(IoSymValue_t *,symCube, numIp+i); entry = _IoSymValueTransformToEntry(symValue,Tbl_TableReadIndexVar(table,i,1),table); if (entry == NIL(Tbl_Entry_t)) return 0; Tbl_TableSetEntry(table,entry,index,i,1); } return 1; } /**Function******************************************************************** Synopsis [Given a default symbolic cube in textual format and a table, updates the table by adding the cube.] Description [] SideEffects [The default cube is added to the table.] SeeAlso [] ******************************************************************************/ static int _IoDefaultSymCubeInsertInTable( Tbl_Table_t *table, array_t *symCube, int numOp) { int i; IoSymValue_t *symValue; Tbl_Entry_t *entry; /* no defaults is asserted. */ if (symCube == NIL(array_t)){ return 1; } for (i=0; i < array_n(symCube); i++){ symValue = array_fetch(IoSymValue_t *,symCube, i); entry = _IoSymValueTransformToEntry(symValue,Tbl_TableReadIndexVar(table,i,1),table); if (entry == NIL(Tbl_Entry_t)) return 0; Tbl_TableDefaultSetEntry(table,entry,i); } return 1; } /**Function******************************************************************** Synopsis [Generates a set of ranges used in the table data structure from textual representation of symbolic values.] Description [Generates a set of ranges used in the table data structure from textual representation of symbolic values. Symbolic values are representations which can be put into an entry of a table, i.e. a symbolic element in a row. The arguments of the function are a symbolic value in IoSymValue_t *, a pointer to the corresponding variable, and the table we are working on. The last argument is needed to resolve = constructs.] SideEffects [] SeeAlso [] ******************************************************************************/ static Tbl_Entry_t * _IoSymValueTransformToEntry( IoSymValue_t *value, Var_Variable_t *var, Tbl_Table_t *table) { IoSymValueType flag; Tbl_Entry_t *entry; if ((flag = value->flag) == IoLeaf_c){ int index; index = VariableReadIndex(var,(char *)(value->left)); if (index == -1){ return NIL(Tbl_Entry_t); } entry = Tbl_EntryAlloc(Tbl_EntryNormal_c); Tbl_EntrySetValue(entry,index,index); return entry; } if (flag == IoUniverse_c){ int range; range = Var_VariableReadNumValues(var); entry = Tbl_EntryAlloc(Tbl_EntryNormal_c); Tbl_EntrySetValue(entry,0,range-1); return entry; } if (flag == IoRange_c){ int indexFrom, indexTo; indexFrom = VariableReadIndex(var,(char *)(value->left)); indexTo = VariableReadIndex(var,(char *)(value->right)); if (indexFrom == -1 || indexTo == -1){ return NIL(Tbl_Entry_t); } entry = Tbl_EntryAlloc(Tbl_EntryNormal_c); Tbl_EntrySetValue(entry,indexFrom,indexTo); return entry; } if (flag == IoComplement_c){ entry = _IoSymValueTransformToEntry(value->left,var,table); if (entry == NIL(Tbl_Entry_t)){ return NIL(Tbl_Entry_t); } Tbl_EntryComplement(entry,0,Var_VariableReadNumValues(var)-1); return entry; } if (flag == IoList_c){ int i; IoSymValue_t *valueTmp; Tbl_Entry_t *entryTmp, *entryUnion; entry = Tbl_EntryAlloc(Tbl_EntryNormal_c); for (i=0; i < array_n(value->elements); i++){ valueTmp = array_fetch(IoSymValue_t *,value->elements,i); entryTmp = _IoSymValueTransformToEntry(valueTmp,var,table); if (entryTmp == NIL(Tbl_Entry_t)){ Tbl_EntryFree(entry); return NIL(Tbl_Entry_t); } entryUnion = Tbl_EntryMerge(entry,entryTmp); Tbl_EntryFree(entry); Tbl_EntryFree(entryTmp); entry = entryUnion; } return entry; } if (flag == IoAssign_c){ int i; Var_Variable_t *varCandidate = NIL(Var_Variable_t); entry = Tbl_EntryAlloc(Tbl_EntryEqual_c); for (i=0; i < Tbl_TableReadNumInputs(table); i++){ varCandidate = Tbl_TableReadIndexVar(table,i,0); if (strcmp(Var_VariableReadName(varCandidate),(char *)value->left) == 0){ /* found the variable referred in = construct as an input of the table */ break; } } /* the following if-clause is only true when the above for-loop cannot find the variable referred in = construct */ if (i == Tbl_TableReadNumInputs(table)){ error_append("Variable "); error_append((char *)value->left); error_append(" is not an input of the table where "); error_append(Var_VariableReadName(var)); error_append(" is an output. It cannot be used as an argument of = construct.\n"); Tbl_EntryFree(entry); return NIL(Tbl_Entry_t); } /* check if the two variables connected with = construct have the same domain */ if (Var_VariablesTestHaveSameDomain(var,varCandidate) == 0){ error_append("Variables "); error_append((char *)value->left); error_append(" and "); error_append(Var_VariableReadName(var)); error_append(" have different domains. Cannot be used in = construct.\n"); Tbl_EntryFree(entry); return NIL(Tbl_Entry_t); } Tbl_EntrySetEqual(entry,i); return entry; } else { return NIL(Tbl_Entry_t); } } /**Function******************************************************************** Synopsis [Returns the integer index given a value.] Description [Returns the integer index given a value. The value is either an integer or a symbolic name. If the latter is the case, it is transformed into the corresponding integer. If a given symbolic name is not valid, the routine returns -1.] SideEffects [] SeeAlso [] ******************************************************************************/ static int VariableReadIndex( Var_Variable_t *var, char *value) { int integer; if (Var_VariableTestIsEnumerative(var) == 1){ integer = IoAtoi(value); if (integer == -1 || integer >= Var_VariableReadNumValues(var)){ error_append("Value "); error_append(value); error_append(" is not a proper value for variable "); error_append(Var_VariableReadName(var)); error_append("\n"); return -1; } return integer; } /* var is now a symbolic variable */ if ((integer = Var_VariableReadIndexFromSymbolicValue(var,value)) == -1){ error_append("Value "); error_append(value); error_append(" is not a proper value for variable "); error_append(Var_VariableReadName(var)); error_append("\n"); return -1; } return integer; }