/* * base/generic/compiler/qlfdid.c created from tcltk/generic/interface/Qlfdid.c * Created: 1/94 * Version: $Revision: 1.22 $ * Version control file: $RCSfile: Qlfdid.c,v $ * Date last modified: $Date: 2003/08/23 18:43:07 $ * Last modified by: $Author: ballan $ * * This file is part of ASCEND. * * Copyright 1997, Carnegie Mellon University * * ASCEND is free software; you can redistribute * it and/or modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * ASCEND is distributed in hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "qlfdid.h" #include #include #include #include #include #include "instance_enum.h" #include "symtab.h" #include "simlist.h" #include "instance_io.h" #include "instance_name.h" #include "instquery.h" #include "parentchild.h" #include "expr_types.h" #include "stattypes.h" #include "instantiate.h" #ifndef MAXIMUM_STRING_LENGTH #define MAXIMUM_STRING_LENGTH 1024 #endif #define QLFDIDMALLOC ASC_NEW(struct SearchEntry); //#define QLFDID_DEBUG #ifdef QLFDID_DEBUG # define MSG CONSOLE_DEBUG #else # define MSG(ARGS...) ((void)0) #endif /* used for searching */ struct Instance *g_search_inst = NULL; struct Instance *g_relative_inst = NULL; /* FIXME remove this silly little function. Just ASC_NEW_ARRAY_CLEAR? It's fairly widely used in the Tcl/Tk GUI... could move it to there? */ char *Asc_MakeInitString(int len){ char *result; int defaultlen = 40; if (len<=0) { FPRINTF(stderr, "Setting length to %d due to invalid length given\n",defaultlen); len = defaultlen; } result = ASC_NEW_ARRAY(char,(len + 1)*sizeof(char)); assert(result!=NULL); sprintf(result,"%s","\0"); return result; } /* FIXME remove this silly little function. Just inline it? It's fairly widely used in the Tcl/Tk GUI... could move it to there? */ void Asc_ReInitString(char *str){ if ((str)&&(strlen(str))) { strcpy(str,""); } } /* Create a search entry node with a simple name such as : a. */ struct SearchEntry *Asc_SearchEntryCreate(char *name,struct Instance *i){ struct SearchEntry *result; result = QLFDIDMALLOC; assert(result!=NULL); result->name = ASC_NEW_ARRAY(char,strlen(name)+1); strcpy(result->name,name); result->i = i; return result; } /* Create a search entry node with a name that is formatted like a integer array. such as: [14]. */ static struct SearchEntry *SearchEntryCreateIntArray(char *name,struct Instance *i){ struct SearchEntry *result; result = QLFDIDMALLOC; assert(result!=NULL); result->name = ASC_NEW_ARRAY(char,strlen(name)+8); sprintf(result->name,"[%s]",name); result->i = i; return result; } /* Create a search entry node with a name that is formatted like a string array. such as: ['benzene.flow']. */ static struct SearchEntry *SearchEntryCreateStrArray(char *name,struct Instance *i){ struct SearchEntry *result; result = QLFDIDMALLOC; assert(result!=NULL); result->name = ASC_NEW_ARRAY(char,strlen(name)+8); sprintf(result->name,"[\'%s\']",name); result->i = i; return result; } struct Instance *Asc_SearchEntryInstance(struct SearchEntry *se){ assert(se!=NULL); return (se->i); } char *Asc_SearchEntryName(struct SearchEntry *se){ assert(se!=NULL); return (se->name); } void Asc_SearchEntryDestroy(struct SearchEntry *se){ if (!se) { return; } ascfree(se->name); se->name = NULL; se->i = NULL; ascfree(se); } void Asc_SearchListDestroy(struct gl_list_t *search_list){ struct SearchEntry *se; unsigned long len,c; if (!search_list) { return; } len = gl_length(search_list); for(c=1;c<=len;c++) { se = (struct SearchEntry *)gl_fetch(search_list,c); Asc_SearchEntryDestroy(se); } gl_destroy(search_list); } static int CheckChildExist(struct InstanceName name){ unsigned long ndx,nch; symchar *tablename; /* hacky, but centralized slop avoidance */ /* remember that a struct passed by value can be overwritten safely. */ nch = NumberChildren(g_search_inst); if (!nch) { g_search_inst = NULL; return 0; } switch (InstanceNameType(name)) { case IntArrayIndex: break; case StrName: tablename = InstanceNameStr(name); SetInstanceNameStrPtr(name,tablename); break; case StrArrayIndex: tablename = InstanceStrIndex(name); SetInstanceNameStrIndex(name,tablename); break; default: Asc_Panic(2,"%s: CheckChildExist called with bad arguments.",__FILE__); break; } ndx = ChildSearch(g_search_inst,&name); /* symchar safe */ if (ndx) { g_search_inst = InstanceChild(g_search_inst,ndx); return ndx; } else { g_search_inst = NULL; return 0; } } struct gl_list_t *Asc_BrowQlfdidSearch(char *str, char *temp){ register char *ptr, *org; struct InstanceName name; struct gl_list_t *search_list = NULL; struct SearchEntry *se; int ndx = 0; int open_bracket = 0; int open_quote = 0; g_search_inst = NULL; /* always start searches from the top */ if (!str) { return NULL; } search_list = gl_create(8L); ptr = temp; org = str; while(*str != '\0') { switch(*str) { case '.': if (*(str-1) != ']') { if(open_quote) { /* to deal b['funny.name'] */ *(ptr++) = *(str++); /* ---^--- */ break; } *ptr = '\0'; if (g_search_inst) { SetInstanceNameType(name,StrName); SetInstanceNameStrPtr(name,AddSymbol(temp)); if(0 == (ndx=CheckChildExist(name))) { Asc_SearchListDestroy(search_list); return NULL; } } else { g_search_inst = Asc_FindSimulationRoot(AddSymbol(temp)); if (!g_search_inst) { Asc_SearchListDestroy(search_list); return NULL; } } se = Asc_SearchEntryCreate(temp,g_search_inst); gl_append_ptr(search_list,se); } str++; ptr = temp; break; case '\'': str++; if(open_quote){ open_quote--; }else{ open_quote++; } break; case '[': if (*(str-1) != ']'){ *ptr = '\0'; if(g_search_inst){ SetInstanceNameType(name,StrName); SetInstanceNameStrPtr(name,AddSymbol(temp)); if(0 == (ndx=CheckChildExist(name))) { Asc_SearchListDestroy(search_list); return NULL; } }else{ g_search_inst = Asc_FindSimulationRoot(AddSymbol(temp)); if (!g_search_inst){ Asc_SearchListDestroy(search_list); return NULL; } } se = Asc_SearchEntryCreate(temp,g_search_inst); gl_append_ptr(search_list,se); } ptr = temp; open_bracket++; str++; break; case ']': open_bracket--; *ptr = '\0'; str++; switch(InstanceKind(g_search_inst)) { case ARRAY_INT_INST: SetInstanceNameType(name,IntArrayIndex); SetInstanceNameIntIndex(name,atol(temp)); if(0 == (ndx=CheckChildExist(name))) { Asc_SearchListDestroy(search_list); return NULL; } ptr = temp; se = SearchEntryCreateIntArray(temp,g_search_inst); gl_append_ptr(search_list,se); break; case ARRAY_ENUM_INST: SetInstanceNameType(name,StrArrayIndex); SetInstanceNameStrIndex(name,AddSymbol(temp)); if(0 == (ndx=CheckChildExist(name))) { /* sets g_search_inst */ Asc_SearchListDestroy(search_list); return NULL; } ptr = temp; se = SearchEntryCreateStrArray(temp,g_search_inst); gl_append_ptr(search_list,se); break; default: FPRINTF(stderr,"Mismatch in qlfdid (%s) and simulation.\n",org); break; } break; default: *(ptr++) = *(str++); break; } } *ptr = '\0'; if(*temp == '\0'){ return search_list; } // handle last part struct InstanceName name1; MSG("handling last part '%s'",temp); if(g_search_inst){ SetInstanceNameType(name1,StrName); SetInstanceNameStrPtr(name1,AddSymbol(temp)); CheckChildExist(name1); /* sets g_search_inst regardless */ }else{ g_search_inst = Asc_FindSimulationRoot(AddSymbol(temp)); } if(g_search_inst){ se = Asc_SearchEntryCreate(temp,g_search_inst); gl_append_ptr(search_list,se); return search_list; }else{ Asc_SearchListDestroy(search_list); return NULL; } } #if 0 /* DISUSED */ int Asc_QlfdidSearch2(char *str){ char temp[MAXIMUM_ID_LENGTH]; struct gl_list_t *search_list; search_list = Asc_BrowQlfdidSearch(str,temp); if((g_search_inst==NULL) || (search_list==NULL)){ return 1; }else{ Asc_SearchListDestroy(search_list); return 0; } } #endif /* ********************************************************************* * This is the version of the function that should be used purely * for the effect of leaving the g_search_inst looking at the result * of a qualified id search. ********************************************************************* */ /* Note that this function is ONLY called from Asc_QlfdidSearch3, and `temp` is a second (*writeable*) copy of `str`. FIXME merge this code into Asc_QlfdidSearch3, no need for a separate func?? */ static struct Instance *BrowQlfdidSearch3(CONST char *str, char *temp,int relative){ register char *ptr; struct InstanceName name; int ndx = 0; int open_bracket = 0; int open_quote = 0; CONST char *org; MSG("Starting search for '%s'",str); if (relative == 1) { g_search_inst = g_relative_inst; /* could be NULL */ } else { g_search_inst = NULL; /* start search from the top */ } if (str == NULL) { return NULL; } org = str; ptr = temp; while(*str != '\0'){ //MSG("Searching '%s'",str); switch(*str) { case '.': if(*(str-1) != ']'){ if(open_quote) { /* to handle b['funny.name'] */ *(ptr++) = *(str++); /* ---^--- */ break; } *ptr = '\0'; if(g_search_inst){ SetInstanceNameType(name,StrName); SetInstanceNameStrPtr(name,AddSymbol(temp)); ndx=CheckChildExist(name); if(ndx==0) { MSG("identifier '%s' not found",temp); return NULL; } MSG("found identifier '%s'",temp); }else{ g_search_inst = Asc_FindSimulationRoot(AddSymbol(temp)); if(!g_search_inst){ MSG("couldn't find simulation root '%s'",temp); return NULL; } MSG("found simulation root '%s' at %p",temp,g_search_inst); } } str++; ptr = temp; break; case '\'': str++; if(open_quote){ MSG("closed quote"); open_quote--; }else{ MSG("opened quote"); open_quote++; } break; case '[': MSG("open '['"); if(*(str-1) != ']'){ *ptr = '\0'; if(g_search_inst){ MSG("checking for child '%s'",temp); SetInstanceNameType(name,StrName); SetInstanceNameStrPtr(name,AddSymbol(temp)); ndx=CheckChildExist(name); if(ndx==0) { return NULL; } }else{ MSG("checking for root '%s'",temp); g_search_inst = Asc_FindSimulationRoot(AddSymbol(temp)); if (!g_search_inst) { return NULL; } } } ptr = temp; open_bracket++; str++; break; case ']': open_bracket--; *ptr = '\0'; str++; switch(InstanceKind(g_search_inst)){ case ARRAY_INT_INST: MSG("looking for array integer instance '%s'",temp); SetInstanceNameType(name,IntArrayIndex); SetInstanceNameIntIndex(name,atol(temp)); ndx=CheckChildExist(name); if(ndx==0) { return NULL; } ptr = temp; break; case ARRAY_ENUM_INST: MSG("looking for array enum instance '%s'",temp); SetInstanceNameType(name,StrArrayIndex); SetInstanceNameStrIndex(name,AddSymbol(temp)); ndx=CheckChildExist(name); if(ndx==0) { /* sets g_search_inst */ return NULL; } ptr = temp; break; default: FPRINTF(stderr,"Mismatch in values file (%s) and simulation.\n",org); break; } break; default: *(ptr++) = *(str++); break; } } *ptr = '\0'; if (*temp == '\0') { return g_search_inst; } // handle last part MSG("handling last part '%s'",temp); struct InstanceName name1; if(g_search_inst){ SetInstanceNameType(name1,StrName); SetInstanceNameStrPtr(name1,AddSymbol(temp)); CheckChildExist(name1); /* sets g_search_inst regardless */ MSG("%s final part '%s'",g_search_inst?"Found":"Did not find", temp); }else{ g_search_inst = Asc_FindSimulationRoot(AddSymbol(temp)); MSG("%s simulation root '%s'",g_search_inst?"Found":"Did not find", temp); } return g_search_inst; /* which may be NULL */ } int Asc_QlfdidSearch3(CONST char *str, int relative){ char *temp; struct Instance *found; if (str==NULL) { return 1; } temp = ASC_STRDUP((char *)str); if (temp==NULL) { return 1; } found = BrowQlfdidSearch3(str,temp,relative); ascfree(temp); if (found != NULL) { return 0; } else { return 1; } }