/* * $Id: xtm.c,v 1.2 2004/09/15 11:39:27 jan Exp $ * * Copyright (c) 2002 Jan Algermissen * See the file "COPYING" for copying permission. * */ #include /* #include "df.h" */ #include #include #include "omnivore.h" #define SAM_NAME "http://purl.org/tm/sam/" #define PATH(t) (strcmp(elem_path(elem),(t)) == 0) /* element subtrees that we want to skip entirely: */ static struct TMList l3 = { NULL, "scope" }; static struct TMList l4 = { &l3, "variant" }; /* elements that contain text */ static struct TMList tel0 = { NULL, "property" }; static struct TMList tel1 = { &tel0, "resourceData" }; static struct TMList tel2 = { &tel1, "baseNameString" }; static int xtm_start_element(void *data, Omnivore ov, element *elem, const char **attr); static int xtm_end_element(void *data, Omnivore ov, element *elem); static char *PSYM[TM_MAXMEMBERS] = { "player-0", "player-1", "player-2", "player-3", "player-4", "player-5", "player-6", "player-7" }; static const char * _get_att_val(const char **attr, const char *name) { int i; for (i = 0; attr[i]; i += 2) { if( strcmp(name,attr[i]) == 0 ) { return attr[i + 1]; } } return NULL; } /* data that the proc model needs; will be passed to all the callbacks */ struct data { TM XX; TMTopicMap tm; TMPool pool; Omnivore omnivore; TMProperty Pasidp; TMProperty Psirs; TMProperty Pnames; TMProperty Psloc; TMProperty Pscr; TMProperty Psdata; char last_topic_source_locator[MAXLINE]; /* FIXME */ struct TMSubject topic_sbj; TMList sirs_list; TMList basenames; TMTable symtab; TMTable atomtab; TMProperty last_prop; void *asidp_value; char *a_topic_source_locator; char *occ_sloc; char *occ_isa_sloc; char *occ_class_sloc; char *occ_class_sid; char *occ_resref; TMProperty occ_prop; char *last_role_ref; int member_count; }; static const char* atom(struct data* self,const char *s) { char *atom; if( (atom = tm_table_get(self->atomtab,s)) == NULL) { atom = tm_strdup(self->pool,s); tm_table_put(self->atomtab,atom,atom); } return (atom); } /* * */ static int add_node_demander(struct data* self,const char *uri,const char *sym); /* * */ static int add_node_demander2(struct data* self,const char *uri,const char *sym); static int handle_topic(struct data* self,const char *uri,const char *sym); static char* assure_is_loaded(struct data* self,const char *uri); static void assertion_init(struct data *self); static void assertion_set_a(struct data *self,const char *a_sym); static int assertion_set_type(struct data *self,const char *at_sym); static int assertion_add_member(struct data *self,const char *role_sym, const char *player_sum); static int add_assertion(struct data *self,const char *symbol); static TMError _init(Omnivore omnivore,void*arg,void**data) { struct data *dp; /* struct TMList list; */ TM_NEW( tm_omnivore_get_pool(omnivore),dp); dp->pool = tm_omnivore_get_pool(omnivore); dp->tm = tm_omnivore_get_topicmap(omnivore); dp->XX = tm_omnivore_get_tm(omnivore); dp->omnivore = omnivore; /* FIXME: the require stuff could be part of proc model structure! */ if(dp->tm) { TMModel core; TMError e; if( (e = tm_lookup_model(dp->XX,SAM_NAME,&core)) != TM_OK) { assert(0); return(e); } if( (e = tm_topicmap_require_model(dp->tm,core)) != TM_OK) { assert(0); return(e); } } dp->Pasidp = tm_get_property(dp->XX,"http://purl.org/tm/amod/a-sidp"); dp->Psirs = tm_get_property(dp->XX,SAM_NAME"SubjectIndicators"); dp->Pnames = tm_get_property(dp->XX,SAM_NAME"BaseNames"); dp->Psloc = tm_get_property(dp->XX,SAM_NAME"SourceLocators"); dp->Pscr = tm_get_property(dp->XX,SAM_NAME"SubjectAddress"); dp->Psdata = tm_get_property(dp->XX,SAM_NAME"SubjectData"); assert(dp->Pasidp); assert(dp->Psirs); assert(dp->Pnames); assert(dp->Pscr); assert(dp->Psdata); assert(dp->Psloc); /* FIXME error handling */ dp->symtab = tm_table_new(dp->pool,100,tm_strcmp_v,tm_strhash_v); dp->atomtab = tm_table_new(dp->pool,100,tm_strcmp_v,tm_strhash_v); dp->asidp_value = NULL; dp->a_topic_source_locator = NULL; dp->occ_sloc = NULL; dp->occ_isa_sloc = NULL; dp->occ_class_sloc = NULL; dp->occ_class_sid = NULL; dp->occ_resref = NULL; dp->occ_prop = NULL; dp->last_role_ref = NULL; dp->member_count = 0; *data = dp; return TM_OK; } static void _delete(void **pself) { TMPool pool; struct data* self; assert(pself && *pself); self = (struct data*)*pself; pool = self->pool; tm_table_apply(self->symtab,tm_free_keys,pool); tm_table_delete(&( self->symtab)); tm_table_apply(self->atomtab,tm_free_keys,pool); tm_table_delete(&( self->atomtab)); TM_FREE(pool,self); } /* A processing model for a subset of XTM */ struct TMProcModel xtm = { "xtm", /* name */ _init, /* init callback */ _delete, /* delete callback */ "topicMap", /* root element name (for lookup) */ "http://www.topicmaps.org/xtm/1.0/", /* XML namespace */ "-//TopicMaps.Org//DTD XML Topic Map (XTM) 1.0//EN", /* DTD Public Identifier */ "http://www.topicmaps.org/xtm/1.0/xtm1.dtd", /* URL of DTD */ /* NULL, -- elements member of struct; unused */ "id", /* id_attribute_name */ "href", /* ref_attribute_name */ &l4, /* subtrees to skip */ &tel2, /* text elements */ &xtm_start_element, /* Omnivore XML start callback */ &xtm_end_element, /* Omnivore XML end callback */ NULL, /* no line-event handler needed in XML proc model */ NULL /* no RDF Statement-Handler-Table */ }; int xtm_start_element(void *s,Omnivore ov, element *elem, const char **attr) { struct data *self = (struct data *)s; TMTRACE(TM_PARSE_TRACE,"enter for path %s\n" _ elem_path(elem)); TMTRACE(TM_PARSE_TRACE,"elem URI: %s\n" _ elem_uri(elem)); if(!self->tm) { TMTRACE(TM_PARSE_TRACE,"exit (no topicmap)\n"); return (1); } if( PATH("/topicMap") ) { char *p; char buf[1024]; const char *require; const char *sp; require = _get_att_val(attr,"require"); if(!require) return (1); sp = require; while( (p = tm_strtok(&sp,"; \t\n",buf,sizeof(buf) )) != NULL) { TMError e; TMModel model; if( (e = tm_lookup_model(tm_omnivore_get_tm(ov),p,&model)) != TM_OK) { tm_omnivore_set_error(ov, "xtm: error : %s" , tm_get_error(tm_omnivore_get_tm(ov))); return(0); } if( tm_topicmap_require_model(self->tm,model) != TM_OK) { tm_omnivore_set_error(ov, "xtm: error: %s" , tm_get_error(tm_omnivore_get_tm(ov))); return (0); } } /* * ---------------------------------------------------------------- * * and subelements * * ---------------------------------------------------------------- */ } else if( PATH("/topicMap/topic") ) { if(!handle_topic(self,elem_uri(elem),"last-topic")) return 0; /* FIXME */ assert(strlen(elem_uri(elem)) < sizeof(self->last_topic_source_locator)); strcpy(self->last_topic_source_locator,elem_uri(elem)); } else if( PATH("/topicMap/topic/property")) { const char *fn; fn = _get_att_val(attr,"name"); if(!fn) { tm_omnivore_set_error(ov, "syntax error: missing attribute 'name'"); return (0); } self->last_prop = tm_get_property(self->XX,fn); if(!self->last_prop) { tm_omnivore_set_error(ov, "unable to get prop %s, %s", fn, tm_get_error(self->XX) ); return (0); } TMTRACE(TM_PARSE_TRACE,"propertyname=%s\n" _ fn); /* * ---------------------------------------------------------------- * * and subelements * * ---------------------------------------------------------------- */ } else if( PATH("/topicMap/topic/subjectIdentity") ) { ; } else if(PATH("/topicMap/topic/subjectIdentity/subjectIndicatorRef")){ assert(elem_ref_uri(elem) && *elem_ref_uri(elem)); self->sirs_list = tm_list_push(self->pool, self->sirs_list, tm_strdup(self->pool,elem_ref_uri(elem)) ); } else if( PATH("/topicMap/topic/subjectIdentity/topicRef") ) { assert(0); } else if(PATH("/topicMap/topic/subjectIdentity/resourceRef")){ assert(elem_ref_uri(elem) && *elem_ref_uri(elem)); TM_SUBJECT_ADD( &(self->topic_sbj), self->Pscr, tm_strdup(self->pool,elem_ref_uri(elem)), 0); /* * ---------------------------------------------------------------- * * and subelements (inside ) * * ---------------------------------------------------------------- */ } else if( PATH("/topicMap/topic/instanceOf") ) { if(!add_node_demander(self,elem_uri(elem),"a-topic")) return 0; assertion_init(self); assertion_set_a(self,elem_uri(elem)); if(!assertion_set_type(self,SAM_NAME"at-class-instance")) return(0); if(!assertion_add_member(self,SAM_NAME"role-instance","last-topic")) return(0); } else if( PATH("/topicMap/topic/instanceOf/topicRef") ) { /* FIXME: propably use a table since classes are likely * to be used often (also next if)*/ if(!add_node_demander(self,elem_ref_uri(elem),"class-topic")) return (0); if(!assertion_add_member(self,SAM_NAME"role-class", "class-topic")) return (0); if(!add_assertion(self,NULL)) return (0); } else if( PATH("/topicMap/topic/instanceOf/subjectIndicatorRef") ) { if(!add_node_demander2(self,elem_ref_uri(elem),"class-topic")) return 0; if(!assertion_add_member(self,SAM_NAME"role-class", "class-topic")) return (0); if(!add_assertion(self,NULL)) return (0); /* * ---------------------------------------------------------------- * * and subelements * * ---------------------------------------------------------------- */ } else if( PATH("/topicMap/topic/occurrence") ) { self->occ_sloc = tm_strdup(self->pool,elem_uri(elem)); } else if( PATH("/topicMap/topic/occurrence/instanceOf") ) { self->occ_isa_sloc = tm_strdup(self->pool,elem_uri(elem)); } else if( PATH("/topicMap/topic/occurrence/instanceOf/topicRef") ){ self->occ_class_sloc =tm_strdup(self->pool,elem_ref_uri(elem)); } else if( PATH("/topicMap/topic/occurrence/instanceOf/subjectIndicatorRef") ) { self->occ_class_sid = tm_strdup(self->pool,elem_ref_uri(elem)); self->occ_prop = tm_topicmap_get_property_by_name(self->tm, self->occ_class_sid); } else if(PATH("/topicMap/topic/occurrence/resourceData") ) { ; /* handled in end element */ } else if( PATH("/topicMap/topic/occurrence/resourceRef") ) { self->occ_resref = tm_strdup(self->pool,elem_ref_uri(elem)); /* * ---------------------------------------------------------------- * * and subelements * * ---------------------------------------------------------------- */ } else if( PATH("/topicMap/association") ) { assertion_init(self); assertion_set_a(self,elem_uri(elem)); } else if( PATH("/topicMap/association/instanceOf") ) { ; } else if( PATH("/topicMap/association/instanceOf/topicRef") ){ assert(0); /* we need special handling later on */ } else if(PATH("/topicMap/association/instanceOf/subjectIndicatorRef")){ if(!assertion_set_type(self,elem_ref_uri(elem)) ) return(0); } else if( PATH("/topicMap/association/member") ) { ; } else if( PATH("/topicMap/association/member/roleSpec") ) { ; } else if( PATH("/topicMap/association/member/roleSpec/topicRef")){ assert(0); /* we need special handling later on */ } else if( PATH("/topicMap/association/member/roleSpec/subjectIndicatorRef")) { assert(elem_ref_uri(elem) && *elem_ref_uri(elem)); self->last_role_ref = tm_strdup(self->pool,elem_ref_uri(elem)); } else if( PATH("/topicMap/association/member/topicRef")){ if(!add_node_demander(self,elem_ref_uri(elem),PSYM[self->member_count])) return(0); if(!assertion_add_member(self,self->last_role_ref,PSYM[self->member_count])) return(0); } else if(PATH("/topicMap/association/member/subjectIndicatorRef")){ if(!add_node_demander2(self,elem_ref_uri(elem),PSYM[self->member_count])) return(0); if(!assertion_add_member(self,self->last_role_ref,PSYM[self->member_count])) return(0); #if 0 /* * ---------------------------------------------------------------- * * and subelements * * ---------------------------------------------------------------- */ } else if( PATH("/topicMap/topic/baseName") ) { if(!add_node_demander(self,elem_uri(elem),"bn-topic")) return 0; assertion_init(self); assertion_set_a(self,elem_uri(elem)); if(!assertion_set_type(self,SAM_NAME"at-basenamed-basename")) return(0); if(!assertion_add_member(self,SAM_NAME"role-basenamed","last-topic")) return(0); } else if( PATH("/topicMap/topic/baseName/baseNameString") ) { ; } else { tm_omnivore_set_error(ov, "syntax error: unsupported path %s", elem_uri(elem)); return (0); #endif } return 1; } int xtm_end_element(void *s,Omnivore ov, element *elem) { TMError e; struct data *self = (struct data *)s; TMTRACE(TM_PARSE_TRACE,"enter\n"); if(!self->tm) { TMTRACE(TM_PARSE_TRACE,"exit (no topicmap)\n"); return (1); } if(!self->tm) return (1); if( PATH("/topicMap") ) { ; /* * ---------------------------------------------------------------- * * and subelements * * ---------------------------------------------------------------- */ } else if( PATH("/topicMap/topic") ) { if( self->sirs_list) { void *sirs_val = NULL; if( tm_subject_get_value(&(self->topic_sbj), "http://purl.org/tm/sam/SubjectIndicators", &sirs_val)) { assert(0); } TM_SUBJECT_ADD( &(self->topic_sbj), self->Psirs, self->sirs_list, 0); /* sirs_list will be freed below */ } if( self->basenames) { void *names_val = NULL; if( tm_subject_get_value(&(self->topic_sbj), "http://purl.org/tm/sam/BaseNames", &names_val)) { assert(0); } TM_SUBJECT_ADD( &(self->topic_sbj), self->Pnames, self->basenames, 0); /* basenames list will be freed below */ } if( self->topic_sbj.N > 1 ) { if( (e = tm_topicmap_add_topic(self->tm,&(self->topic_sbj),NULL )) != TM_OK) { tm_omnivore_set_error(ov,"cannot add subject %s (element URI is %s)" , tm_get_error(tm_omnivore_get_tm(ov) ) , "FIXME" ); return (0); } } /* N > 1? */ tm_subject_free_values(self->pool,&(self->topic_sbj)); } else if(strcmp(elem_path(elem),"/topicMap/topic/property") == 0) { void *value = tm_value_new_from_string(self->pool, self->last_prop->value_type,elem_text(elem)); TM_SUBJECT_ADD( &(self->topic_sbj), self->last_prop, value, 0); /* freed in */ /* * ---------------------------------------------------------------- * * stuff hack * * ---------------------------------------------------------------- */ } else if(PATH("/topicMap/topic/baseName/baseNameString")){ self->basenames = tm_list_push(self->pool, self->basenames, tm_strdup(self->pool,elem_text(elem)) ); /* * ---------------------------------------------------------------- * * and subelements * * ---------------------------------------------------------------- */ } else if( PATH("/topicMap/topic/occurrence/resourceData")) { struct TMSubject sbj; if(self->occ_prop) { void *value = tm_value_new_from_string( self->pool, self->occ_prop->value_type, elem_text(elem)); TM_SUBJECT_ADD( &(self->topic_sbj), self->occ_prop, value, 0); return(1); } TM_INIT_SUBJECT_N2(&sbj, self->Pscr,elem_uri(elem),0, self->Psdata,elem_text(elem),0); if( (e = tm_topicmap_add_topic(self->tm,&sbj,"r-topic")) != TM_OK) { tm_omnivore_set_error(ov, "xtm: proce error: %s" , tm_get_error(tm_omnivore_get_tm(ov))); return (0); } } else if( PATH("/topicMap/topic/occurrence/resourceRef")) { struct TMSubject sbj; if(self->occ_prop) { /* do we report that? (FIXME) */ /* we set it to NULL, to make occurrence end elem * correctly handle the assertion. Usually, it * uses occ_prop as test if occ has already * been handled as a property. */ self->occ_prop = NULL; } TM_INIT_SUBJECT_N1(&sbj, self->Pscr,self->occ_resref,0); if( (e = tm_topicmap_add_topic(self->tm,&sbj,"r-topic")) != TM_OK) { tm_omnivore_set_error(ov, "xtm: proce error: %s" , tm_get_error(tm_omnivore_get_tm(ov))); return (0); } } else if(PATH("/topicMap/topic/occurrence") ) { /* if prop-as-occ, we are already done */ if(self->occ_prop) return(1); assertion_init(self); assertion_set_a(self,self->occ_sloc); if(!assertion_set_type(self,SAM_NAME"at-occurring-occurrence")) return(0); if(!assertion_add_member(self,SAM_NAME"role-occurring","last-topic")) return(0); if(!assertion_add_member(self,SAM_NAME"role-occurrence","r-topic")) return(0); if(!add_assertion(self,"occ-topic")) return(0); if(!self->occ_isa_sloc) return (1); if(self->occ_class_sloc) { if(!add_node_demander(self, self->occ_class_sloc,"occ-class")) return(0); } else { assert(self->occ_class_sid); if(!add_node_demander2(self, self->occ_class_sid,"occ-class")) return(0); } assertion_init(self); assertion_set_a(self,self->occ_isa_sloc); if(!assertion_set_type(self,SAM_NAME"at-class-instance")) return(0); if(!assertion_add_member(self,SAM_NAME"role-class","occ-class")) return(0); if(!assertion_add_member(self,SAM_NAME"role-instance","occ-topic")) return(0); if(!add_assertion(self,NULL)) return(0); if(self->occ_sloc) TM_FREE(self->pool,self->occ_sloc); if(self->occ_isa_sloc) TM_FREE(self->pool,self->occ_isa_sloc); if(self->occ_class_sloc) TM_FREE(self->pool,self->occ_class_sloc); if(self->occ_class_sid) TM_FREE(self->pool,self->occ_class_sid); if(self->occ_resref) TM_FREE(self->pool,self->occ_resref); /* * ---------------------------------------------------------------- * * and subelements * * ---------------------------------------------------------------- */ } else if( PATH("/topicMap/association/member") ) { TM_FREE(self->pool,self->last_role_ref); } else if( PATH("/topicMap/association") ) { if(!add_assertion(self,NULL)) return (0); #if 0 /* * ---------------------------------------------------------------- * * and subelements * * ---------------------------------------------------------------- */ } else if( PATH("/topicMap/topic/baseName/baseNameString") ) { struct TMSubject sbj; struct TMList sirs; sirs.next = NULL; sirs.content = (void*)elem_uri(elem); TM_SET_SUBJECT_N2(&sbj, SAM_NAME,"SourceLocators",&sirs, SAM_NAME,"IndicatorData",elem_text(elem)); if( tm_topicmap_add_topic(self->tm,&sbj,"b-topic" ) != TM_OK) { tm_omnivore_set_error(ov, "xtm: proce error: %s" , tm_get_error(tm_omnivore_get_tm(ov))); return (0); } if(!assertion_add_member(self,SAM_NAME"role-basename", "b-topic")) return (0); { struct TMSubject sbj2; struct TMList sirs2; struct TMList list; list.next = NULL; list.content = (char*)elem_text(elem); sirs2.next = NULL; sirs2.content = self->last_topic_source_locator; TM_SET_SUBJECT_N2(&sbj2, SAM_NAME,"SourceLocators",&sirs2, SAM_NAME,"BaseNames",&list); if( tm_topicmap_add_topic(self->tm,&sbj2,NULL ) != TM_OK) { tm_omnivore_set_error(ov, "cannot add subject %s (element URI is %s)" , tm_get_error(tm_omnivore_get_tm(ov) ) , elem_uri(elem) ); return (0); } } } else if( PATH("/topicMap/topic/baseName") ) { if(!add_assertion(self,NULL)) return (0); } else if( PATH("/topicMap/mergeMap") ) { ; /* FIXME: added themes !*/ /* if(ov->merge_map_handler) ov->merge_map_handler(ov->user_data, elem_ref_uri(elem)); */ } else { /* no action for other paths. Syntax errors have been * handled by start element. */ #endif } return 1; } /* ------------------------------------------------------------------------*/ /* ------------------------------------------------------------------------*/ /* ------------------------------------------------------------------------*/ /* ------------------------------------------------------------------------*/ int add_node_demander(struct data* self,const char *uri,const char *sym) { struct TMSubject sbj; struct TMList sirs; sirs.next = NULL; sirs.content = (void*)uri; TM_INIT_SUBJECT_N1(&sbj,self->Psloc,&sirs,0); if( tm_topicmap_add_topic(self->tm,&sbj,sym) != TM_OK) { tm_omnivore_set_error(self->omnivore, "cannot add topic %s (element URI is %s)" , tm_get_error(tm_omnivore_get_tm(self->omnivore) ), uri); return (0); } return (1); } int handle_topic(struct data* self,const char *uri,const char *sym) { TMList slocs; TM_ENTER; slocs = tm_list_push(self->pool,NULL, tm_strdup(self->pool,uri) ); /* will be freed in */ self->sirs_list = NULL; self->basenames = NULL; TM_INIT_SUBJECT_N1(&(self->topic_sbj),self->Psloc,slocs,0); if( tm_topicmap_add_topic(self->tm,&(self->topic_sbj),sym) != TM_OK) { tm_omnivore_set_error(self->omnivore, "cannot add topic %s (element URI is %s)" , tm_get_error(tm_omnivore_get_tm(self->omnivore) ), uri); TM_RETURN(0); } assert(strlen(uri) < sizeof(self->last_topic_source_locator)); strcpy(self->last_topic_source_locator,uri); TM_RETURN(1); } int add_node_demander2(struct data* self,const char *uri,const char *sym) { struct TMSubject sbj; struct TMList sirs; sirs.next = NULL; sirs.content = (void*)uri; TM_INIT_SUBJECT_N1(&sbj,self->Psirs,&sirs,0); if( tm_topicmap_add_topic(self->tm,&sbj,sym) != TM_OK) { tm_omnivore_set_error(self->omnivore, "cannot add topic %s (element URI is %s)" , tm_get_error(tm_omnivore_get_tm(self->omnivore) ), uri); return (0); } return (1); } char* assure_is_loaded(struct data* self,const char *uri) { char *uri_atom; if( (uri_atom = tm_table_get(self->symtab,uri)) == NULL) { struct TMSubject sbj; struct TMList sirs; sirs.next = NULL; sirs.content = (void*)uri; TM_INIT_SUBJECT_N1(&sbj,self->Psirs,&sirs,0); /* uri is symbol! */ if( tm_topicmap_add_topic(self->tm,&sbj,uri) != TM_OK) { tm_omnivore_set_error(self->omnivore, "cannot add topic %s (element URI is %s)" , tm_get_error(tm_omnivore_get_tm(self->omnivore) ), uri); return (NULL); } uri_atom = tm_strdup(self->pool,uri); tm_table_put(self->symtab,uri_atom,uri_atom); } return (uri_atom); } void assertion_init(struct data *self) { assert(self->asidp_value == NULL); self->asidp_value = tm_value_new(self->pool,&ASIDP); self->member_count = 0; } void assertion_set_a(struct data *self,const char *a_source_loc) { assert(self->a_topic_source_locator == NULL); self->a_topic_source_locator = tm_strdup(self->pool,a_source_loc); } int assertion_set_type(struct data *self,const char *at_sym) { char *sym_atom; if( (sym_atom = assure_is_loaded(self,at_sym)) == NULL ) return (0); tm_value_call(&ASIDP,self->asidp_value,"setType",TM_TVAL_SYMBOL,sym_atom); return(1); } int assertion_add_member(struct data *self,const char *role_sym, const char *player_sym) { char *role_sym_atom; TM_ENTER; assert(self->member_count < TM_MAXMEMBERS ); if( (role_sym_atom = assure_is_loaded(self,role_sym)) == NULL ) return (0); tm_value_call(&ASIDP,self->asidp_value,"addMember", self->pool, TM_TVAL_SYMBOL, role_sym_atom,atom(self,player_sym) ); self->member_count++; TM_RETURN (1); } int add_assertion(struct data *self,const char *symbol) { struct TMList list; struct TMSubject a_sbj; TM_ENTER; assert(self->a_topic_source_locator); list.next = NULL; list.content = self->a_topic_source_locator; TM_INIT_SUBJECT_N2(&a_sbj, self->Pasidp, self->asidp_value,0, self->Psloc,&list,0 ); if( tm_topicmap_add_topic(self->tm,&a_sbj,symbol) != TM_OK) { tm_omnivore_set_error(self->omnivore, "cannot add assertion, %s" , tm_get_error(tm_omnivore_get_tm(self->omnivore))); assert(0); } TM_FREE(self->pool,self->a_topic_source_locator); tm_value_delete(self->pool,&ASIDP,&self->asidp_value); self->a_topic_source_locator = NULL; self->asidp_value = NULL; TM_RETURN(1); }