/* save resource to stream with garbage collection. the resources with reference count of zero are not saved. */ static __bool _save_res_stream(IF8Stream * str, F8_RESOURCE * res) { __uint itemcount; void * itembuf = 0; c_bstr_t cbstr; ITEMMAP::iterator it; __u16 magic = F8_RES_MAGIC; ITEMMAP & imap = *res->pItems; if(!res->refcount){ return __false; } itemcount = imap.size(); // 2003-11-20, save non-null resources only if(itemcount){ __vcall__(str, put, (str, &magic, sizeof(magic))); __vcall__(str, put, (str, (void*)&res->id, sizeof(f8_uuid))); __vcall__(str, put, (str, &itemcount, sizeof(itemcount))); it = imap.begin(); while(it != imap.end()){ cbstr.buffer = (char*)it->first.data(); cbstr.count = it->first.length(); bstr_to_stream(&cbstr, str); __vcall__(str, put, (str, &it->second.length, sizeof(__uint))); __vcall__(str, put, (str, it->second.buffer, it->second.length)); it++; } } return __true; }
/* save the instance resource into the stream */ static __bool _save_inst_res_proc(ITreeNode * nd, __bool firstVisit, f8_uint _s) { IBlk * blk; ICBlk * cblk; struct cblk_link_t * lk; struct blk_pin_t * p; struct cblk_pin_t * cp; IF8Stream * s; s = (IF8Stream*)_s; blk = __dcast__(ITreeNode, IBlk, nd); save_res_stream(&blk->uuid, s); if(blk->h.magic == CBLK_MAGIC){ cblk = __dcast__(IBlk, ICBlk, (blk)); lk = ICBlk_first_link(cblk); while(lk){ save_res_stream(&lk->uuid, s); lk = ICBlk_next_link(lk); } p = __vcall__(blk, first_pin, (blk)); while(p){ cp = CONTAINING_RECORD(p, struct cblk_pin_t, p); save_res_stream(&cp->uuid, s); p = __vcall__(blk, next_pin, (p)); } }
/* if mount_as_child_or_sibling is true, mount as child else mount as sibling fails if: 1) mount as sibling but peer has no parent, since allowing this will incur two or more roots. 2) mount as child but the newcomer has already a parent(you must umount it from its previous parent first), i.e., only root can be mounted */ __bool ITreeNode_mount(ITreeNode * peer, ITreeNode * newcomer, __bool mount_as_child) { __bool ret; if(mount_as_child){ if( newcomer->uplink ){ ret = __false; }else{ // insert as the last child newcomer->uplink = peer; if(peer->first_child){ RtkInsertTailList(&peer->first_child->sibling, &newcomer->sibling); }else{ peer->first_child = newcomer; } ret = __true; } }else{ // as sibling if( !peer->uplink ){ ret = __false; }else{ newcomer->uplink = peer->uplink; RtkInsertTailList( &peer->uplink->first_child->sibling, &newcomer->sibling ); ret = __true; } } if(ret){ __vcall__(newcomer, on_mount, (newcomer)); } return ret; }
LOCAL int IPeer_write_zero_copy(IPeer * _this,...) { va_list args; void * buf=(void*)-1; int len,totalLen=0; char rtu[PEER_RTU]; char *p; va_start(args, _this); p=rtu; while(buf){ buf = va_arg(args, void *); len = va_arg(args, int); if(buf){ if(len+totalLen <= PEER_RTU){ memcpy(p, buf, len); p += len; totalLen += len; }else{ return F8_BUFFER_TOO_SMALL; } } } return __vcall__(_this, write, (_this, rtu, totalLen)); }
static __bool _save_var(f8_uint context, const hash_key_t * k, const hash_val_t v) { IF8Stream * s; struct blk_var_t * nv; s = (IF8Stream*)context; nv = (struct blk_var_t*)v; if(!__vcall__(s, put, (s, nv, sizeof(struct blk_var_t)))){ return __false; } return __true; }
LIBCOBJ_API __bool bstr_from_stream(struct c_bstr_t * b, IF8Stream * s) { if(__vcall__(s, get, (s, &b->count, sizeof(b->count))) != sizeof(b->count)){ return __false; } b->buffer = c_alloc_str(b->count); if(!b->buffer){ return __false; } if(__vcall__(s, get, (s, b->buffer, b->count + 1)) != b->count + 1){ c_free_str(b->buffer); b->buffer = 0; return __false; } if(b->buffer[b->count] != '\0'){ c_free_str(b->buffer); b->buffer = 0; return __false; } return __true; }
void CRegRequirementList::Add( struct blk_pin_t * p, struct mem_addr_t * addr, int length ) { reg_item item; item.owner = p; item.addr = *addr; item.length = length; item.blk_id = p->blk->uuid; item.pin_id = __vcall__(p->blk, id_by_pin, (p)); m_rlist.insert(m_rlist.begin(), item); }
__uint ITreeNode_umount_children(ITreeNode * __this) { __uint res = 0; ITreeNode *nd, *next=0; nd = __this->first_child; if(nd){ next = ITreeNode_next(nd); } while(nd){ res += ITreeNode_umount_children(nd); __vcall__(nd, before_umount, (nd)); ITreeNode_umount(nd); __vcall__(nd, after_umount, (nd)); res++; nd = next; if(nd){ next = ITreeNode_next(nd); } } return res; }
static int UTILS_API _e_file( const char * szBaseDir, const char * szFullPath, const char * szRelativePath, const void * pvSearchContext ) { IBlk * blk; char buf[128]; IFileStream *fs; IF8Stream *s; int roffset; fs = IFileStream_from_file(szFullPath, "rb"); if(!fs){ return 1; } s = __ucast__(IFileStream, IF8Stream, (fs)); blk = IBlk_from_stream(s); if(!blk){ __delete__(fs); return 1; } roffset = __vcall__(s, tell, (s)); load_res_stream(s); probe_blk_resources(blk); fprintf(fdb, "%d=%s,%c%c,%s", count, IBlk_class_name(blk), blk->h.magic >> 8, blk->h.magic & 0xff, szRelativePath ); f8_uuid_to_string(&blk->h.uuid, buf, sizeof(buf)); fprintf(fdb, ",%s", buf); fprintf(fdb, ",%d", roffset); fprintf(fdb, "\n"); delete_blk(blk); __delete__(fs); count++; return 1; }
static __inline struct blk_pin_t * _extract_pin( struct kernel_t * kernel, IMemStream *s) { IBlk * blk; __u16 pid; blk = _extract_blk_by_uuid(kernel, s); if(!blk){ return 0; } if(!_extract_u16(s, &pid)){ return 0; } return __vcall__(blk, pin_by_id, (blk, pid)); }
/* load resources in the stream, note the reference count of the resources are not affected, or set to zero if not already present. */ F8RES_API __bool load_res_stream( IF8Stream * s ) { F8_RESOURCE *h; do{ h = _load_res_stream(s); }while(h); /* we should have consumed all the stream contents */ if(!__vcall__(s, eos, (s))){ return __false; } return __true; }
void ki_halt(struct kernel_t * kernel, f8_status code) { f8_u32 c1,c2,c3; c1=c2=c3=0; if(kernel->current_blk){ c1 = (f8_u32)(kernel->current_blk->uuid >> 32); c2 = (f8_u32)(kernel->current_blk->uuid & 0xffffffff); if(kernel->current_pin){ c3 = __vcall__( kernel->current_blk, id_by_pin, (kernel->current_pin) ); }else{ c3 = -1; } }
ICBlk * ICBlk_from_stream (IF8Stream * s) { ICBlk * blk; IBlk * b; blk = mm_alloc(g_hBlkHeap, sizeof(ICBlk), 0); if(!blk) { return 0; } __create__(ICBlk, blk); b = __ucast__(ICBlk, IBlk, blk); if(!__vcall__(b, load, (b, s))) { delete_blk(b); return 0; } return blk; }
__bool CRegRequirementList::Alloc(struct blk_pin_t * p) { reg_item item; p->u2.mem_addr.section = ke_section_by_type(p->type); item.length = _type_size(p->type); if(!alloc_reg((void*)p, &p->u2.mem_addr, item.length, PIN_MAGIC)){ m_errcode = F8_LOW_REGISTERS; return __false; } item.blk_id = p->blk->uuid; item.pin_id = __vcall__(p->blk, id_by_pin, (p)); item.owner = p; item.addr = p->u2.mem_addr; m_rlist.insert(m_rlist.end(), item); return __true; }
void CRegRequirementList::Commit(__bool bCharge) { reglist::iterator it; varlist::iterator vit; reg_item *item; var_item *vitem; int i; for(i = m_rlist.size(), it = m_rlist.begin(); i; i--, it++){ item = &(*it); /* fixup owner */ if(item->blk_id != BLK_ID_NONE){ IBlk * blk; blk = ke_get_blk(proxy_adapter->kernel, &item->blk_id); assert(blk); item->owner = __vcall__(blk, pin_by_id, (blk, item->pin_id)); assert(item->owner); } set_address_owner( item->owner, &item->addr, item->length, PIN_MAGIC, bCharge ); } for(i = m_vlist.size(), vit = m_vlist.begin(); i; i--, vit++){ vitem = &(vit->second); vitem->var->blk = ke_get_blk( proxy_adapter->kernel, &vitem->var->blk->uuid ); vitem->var->ref_count += vitem->ref_count; } m_rlist.clear(); m_vlist.clear(); }
LIBCOBJ_API void bstr_to_stream(struct c_bstr_t * b, IF8Stream *s) { __vcall__(s, put, (s, &b->count, sizeof(b->count))); __vcall__(s, put, (s, b->buffer, b->count + 1)); }
/* construct a resource object in memory from a stream the stream is composed of: 1) a magic 2) uuid 3) item count 4) array of items NOTE!! 1) On success, the resource item is not reference counted. If the client won't addref on the loaded resource, then the item is exposed to the garbage collector. More exactly, this proc won't addref on the resource when the resource already exists. */ static F8_RESOURCE * _load_res_stream(IF8Stream * str) { __u16 magic; RESMAP::iterator it; __u32 itemcount; c_bstr_t cbstr; f8_uuid id; __int length; void * buffer; F8_RESOURCE * res; __bool ret; // DEBUG_PRINTF(("stream %08x\n", __vcall__(str, tell, (str)))); if(!__vcall__(str, get, (str, &magic, sizeof(magic)))){ return 0; } if(magic != F8_RES_MAGIC && magic != F8_RES_MAGIC_2){ __vcall__(str, seek, (str, -sizeof(magic), SEEK_CUR)); return 0; } if(!__vcall__(str, get, (str, &id, sizeof(id)))){ return 0; } res = create_resource_bibibobo(&id, __false); if(!res){ return 0; } /* the resource has not been loaded yet */ if(!__vcall__(str, get, (str, &itemcount, sizeof(itemcount)))){ return 0; } if(res->refcount){ /* note if the resource is already present we silently eat the stream without modifing the in-memory version */ for(; itemcount; itemcount--){ if(!__vcall__(str, get, (str, &cbstr.count, sizeof(cbstr.count)))){ goto __failed; } __vcall__(str, seek, (str, cbstr.count, SEEK_CUR)); if(!__vcall__(str, get, (str, &length, sizeof(length)))){ goto __failed; } __vcall__(str, seek, (str, length, SEEK_CUR)); } }else{ for(; itemcount; itemcount--){ if(!bstr_from_stream(&cbstr, str)){ goto __failed; } if(!__vcall__(str, get, (str, &length, sizeof(length)))){ goto __failed; } if(length){ buffer = __malloc__(length); if(!buffer){ goto __failed; } if(!__vcall__(str, get, (str, buffer, length))){ goto __failed; } }else{ buffer = 0; } ret = set_res_buf(&id, buffer, length, cbstr.buffer); __free__(buffer); c_free_bstr(&cbstr); if(!ret){ goto __failed; } } } return res; __failed: /* the unload_resource will decrease the refcount */ res->refcount++; unload_resource(&id); return 0; }
static void dumpBblk(IBlk * b, FILE * of) { const char * name; char path[F8_MAX_PATH]; char buf[1024]; char idName[128]; struct blk_ent_t be; struct blk_pin_t * p; *buf=0; if(!(parent_blk(b)->h.flags & BLK_F_READONLY)){ name = IBlk_name(b); IBlk_path_by_blk(parent_blk(b), path, sizeof(buf)); if(blklib_query(&b->h.uuid, &be)){ sprintf(buf, "mount path=\"%s\" type=\"%s.%s\" name=\"%s\"", path, be.dir, be.name, name); }else{ f8_uuid_to_string(&b->h.uuid, idName, sizeof(idName)); sprintf(buf, "mount path=\"%s\" id=%s name=\"%s\" ", path, idName, name); } if(of==stdout) utils_trace("%s\n", buf); else fprintf(of, "%s\n", buf); IBlk_path_by_blk(b, path, sizeof(path)); sprintf(buf, "place block \"%s\" (%d,%d)", path, get_res_int(&b->uuid, "x", 0), get_res_int(&b->uuid, "y", 0)); if (of==stdout) utils_trace("%s\n", buf); else fprintf(of, "%s\n", buf); } for(p = __vcall__(b, first_pin, (b)); p; p = __vcall__(b, next_pin, (p))){ if(p->_class != PIN_CLASS_DI && p->_class != PIN_CLASS_DO){ continue; } IBlk_path_by_pin(p, path, sizeof(path)); // dump binding *buf = 0; if(p->binding == PIN_B_CONST){ switch(p->type){ case PIN_T_INTEGER : if(p->dp->u.d.i32 != 0){ sprintf(buf, "bind \"%s\" %d", path, p->dp->u.d.i32); } break; case PIN_T_BOOL : if(p->dp->u.d.ui8 != 0){ sprintf(buf, "bind \"%s\" %d", path, p->dp->u.d.ui8); } break; case PIN_T_FLOAT : if(p->dp->u.d.flt != 0){ sprintf(buf, "bind \"%s\" %f", path, p->dp->u.d.flt); } break; case PIN_T_BYTE : if(p->dp->u.d.ui8 != 0){ sprintf(buf, "bind \"%s\" %d", path, p->dp->u.d.ui8); } break; case PIN_T_WORD : if(p->dp->u.d.ui16 != 0){ sprintf(buf, "bind \"%s\" %d", path, p->dp->u.d.ui16); } break; case PIN_T_DOUBLE : if(p->dp->u.d.dbl != 0){ sprintf(buf, "bind \"%s\" %.15f", path, p->dp->u.d.dbl); } break; case PIN_T_DATE : if(fabs(p->dp->u.d.dbl) > 1e-9){ if(p->dp->u.d.dbl > 2.0){ sprintf(buf, "bind \"%s\" t#%fs", path, p->dp->u.d.dbl); }else{ sprintf(buf, "bind \"%s\" t#%fms", path, p->dp->u.d.dbl*1000); } } break; case PIN_T_CHAR : if(p->dp->u.d.i8 != 0){ sprintf(buf, "bind \"%s\" %d", path, p->dp->u.d.i8); } break; case PIN_T_SHORT : if(p->dp->u.d.i16 != 0){ sprintf(buf, "bind \"%s\" %d", path, p->dp->u.d.ui16); } break; case PIN_T_DWORD : if(p->dp->u.d.ui32 != 0){ sprintf(buf, "bind \"%s\" %d", path, p->dp->u.d.ui32); } break; } }else { struct blk_var_t * v; v = query_var_by_pin(p); if(v){ char vpath[F8_MAX_PATH]; IBlk_path_by_blk(v->blk, vpath, sizeof(vpath)); sprintf(buf, "bind \"%s\" %s.%s", path, vpath, v->name); // on_bind } } if(*buf){ if(of==stdout) utils_trace("%s\n", buf); else fprintf(of, "%s\n", buf); } if(p->type==PIN_T_BOOL && (p->flags & PIN_F_INVERTED)){ sprintf(buf, "invert \"%s\"", path); if(of==stdout) utils_trace("%s\n", buf); else fprintf(of, "%s\n", buf); } } }
/* finding out registers usage info for the block hive */ static __bool _gather_reg_usage(ITreeNode * nd, __bool firstVisit, __uint context) { IBlk * b; struct blk_pin_t *p, *rp; int length; CRegRequirementList * req; struct blk_var_t * var; char pName[F8_MAX_PATH]; b = __dcast__(ITreeNode, IBlk, nd); req = (CRegRequirementList *)context; if(b->h.magic == CBLK_MAGIC && req->m_bGatherForDelete){ enum_variables(b, _e_var, (__uint)req); } for(p = __vcall__(b, first_pin, (b)); p; p = __vcall__(b, next_pin, (p))){ /* if the pin is exported, then the variable reference or memory address assignment is counted on the exported pins */ if(p->ulink){ continue; } rp = IBlk_real_pin(p); if(rp->_class != PIN_CLASS_DI && rp->_class != PIN_CLASS_DO){ continue; } if(rp->binding != PIN_B_MEMORY){ continue; } length = _type_size(rp->type); var = (blk_var_t*)query_var_by_pin(p); if(var){ req->Add(var); }else{ if(rp->_class == PIN_CLASS_DI){ if(RtkIsTripleListEmpty(&rp->u1.link)){ /* a data input pin can have a memory address only in two cases: 1) linked. or 2) connected with variable. */ IBlk_path_by_pin(p, pName, sizeof(pName)); utils_error( "%s - DI pin address %%%d%05d incorrect.\n", pName, rp->u2.mem_addr.section, rp->u2.mem_addr.addr ); req->m_errcode = F8_INVALID_DATA; } }else{ if(!is_address_valid(proxy_adapter->kernel, rp, &rp->u2.mem_addr)){ req->m_errcode = F8_INVALID_DATA; IBlk_path_by_pin(p, pName, sizeof(pName)); utils_error( "%s - DO pin address %%%d%05d incorrect.\n", pName, rp->u2.mem_addr.section, rp->u2.mem_addr.addr ); }else{ req->Add(rp, &rp->u2.mem_addr, length); } } } } return __true; }
/* expand or shrink section memory size usage memsize [section_id] [size] */ int on_memsize(char *v, void *k) { int i; CArgs a; _shproc_prolog_(); parse_arg_exA(v, &a, FS); if(a.argc == 1){ for(i=0; i<KERN_NUM_SECTIONS; i++){ utils_trace("memsize %d %d \n", i, g_regmap[i].total_items); } }else if(a.argc == 3){ int newSize; i = atoi(a.argv[1]); newSize = atoi(a.argv[2]); if(newSize < g_regmap[i].total_items){ // memory shrinking is not implemented utils_error("memory shrinking is dangerous.\n"); // return F8_UNIMPLEMENTED; } if(newSize > MAP_ENTRIES){ return F8_LOW_REGISTERS; } if(proxy_adapter->flags & ADAPTER_F_ONLINE){ return F8_INVALID_OPERATION; } /* load memory configuration */ struct ctrller_config cfg; cmd.cmd = F8_GET_SYS_CONFIG; cmd.osize = sizeof(struct ctrller_config); cmd.obuffer = (char *)&cfg; __vcall__( proxy_adapter, exec, (proxy_adapter, &cmd, 5000) ); if(!successful){ return cmd.retcode; } cfg.x_mem_sizes[i]=newSize; cmd.cmd=F8_SET_SYS_CONFIG; cmd.isize=sizeof(cfg); cmd.osize=0; cmd.ibuffer=&cfg; __vcall__( proxy_adapter, exec, (proxy_adapter, &cmd, 5000) ); if(!successful){ return cmd.retcode; } g_regmap[i].free_items += newSize - g_regmap[i].total_items; g_regmap[i].total_items = newSize; } return F8_SUCCESS; }
static __bool ICBlk_save(IBlk * _this, IF8Stream * s) { IBlk * sb; struct cblk_link_t * l; struct cblk_pin_t * p; union blk_pindef_t pd; ICBlk * cblk; cblk = __dcast__(IBlk, ICBlk, _this); // write header __vcall__(s, put, (s, &_this->h, sizeof(_this->h))); // write guid __vcall__(s, put, (s, &_this->uuid, sizeof(f8_uuid))); // write sub-blocks sb = first_subblk(_this); while(sb) { if(!__vcall__(sb, save, (sb, s))) { return __false; } sb = next_blk(sb); } // write link-defs l = _first_link(cblk); while(l) { __vcall__(s, put, (s, &l->uuid, sizeof(l->uuid))); pd.id.bid = IBlk_id_by_blk(l->s.pin->blk); pd.id.pid = __vcall__(l->s.pin->blk, id_by_pin, (l->s.pin)); __vcall__(s, put, (s, &pd, sizeof(pd))); pd.id.bid = IBlk_id_by_blk(l->t.pin->blk); pd.id.pid = __vcall__(l->t.pin->blk, id_by_pin, (l->t.pin)); __vcall__(s, put, (s, &pd, sizeof(pd))); l = _next_link(l); } // write pins p = _first_pin(cblk); while(p) { __vcall__(s, put, (s, &p->uuid, sizeof(p->uuid))); pd.id.bid = IBlk_id_by_blk(p->p.u1.x.id.llink->blk); pd.id.pid = __vcall__(p->p.u1.x.id.llink->blk, id_by_pin, (p->p.u1.x.id.llink)); __vcall__(s, put, (s, &pd, sizeof(pd))); p = _next_pin(cblk, p); } return __true; }
/* patch the memory address in a block hive, and remember all register allocated. */ static __bool _alloc_reg_proc(ITreeNode * nd, __bool firstVisit, __uint context) { IBlk * b, *pb; struct blk_pin_t *p, *rp; CRegRequirementList * req; char path[1024]; blk_var_t * v; req = (CRegRequirementList*)context; b = __dcast__(ITreeNode, IBlk, nd); pb = parent_blk(b); for(p = __vcall__(b, first_pin, (b)); p; p = __vcall__(b, next_pin, (p)) ){ if(p->_class == PIN_CLASS_EI || p->_class == PIN_CLASS_EO){ continue; } if(p->ulink){ // postpone register allocation until the outmost // parent block is being processed continue; } // ok, do allocation rp = IBlk_real_pin(p); if(rp->binding == PIN_B_CONST){ if(rp->_class == PIN_CLASS_DI){ memcpy(rp->dp, p->dp, _type_size(rp->type)); continue; }else{ req->m_errcode = F8_INVALID_DATA; return __false; } }else if(rp->binding != PIN_B_MEMORY){ req->m_errcode = F8_INVALID_DATA; return __false; } if(pb && p->u2.mem_addr.section == MEM_SECTION_VAR){ // // the pin references a variable // if(v = (blk_var_t * )query_var_by_id(pb, p->u2.mem_addr.addr)){ // // note!! address is fixed on real pin // if(v->type != rp->type){ req->m_errcode = F8_INVALID_DATA; return __false; } rp->u2.mem_addr = v->addr; req->Add(v); }else{ IBlk_path_by_pin(p, path, sizeof(path)); utils_error( "%s references undefined variable %d.\n", path, p->u2.mem_addr.addr ); req->m_errcode = F8_UNRESOLVED_REFERENCES; return __false; } }else{ // // the pin has an address on its own // if(!req->Alloc(rp)){ return __false; } } } return __true; }
/* ICBlk::load(IF8Stream * s) this will construct an in-memory composite block object. the most exciting part of F8 controller program. */ static __bool ICBlk_load(IBlk * blk, IF8Stream * s) { ICBlk * cblk; struct blk_hdr_t * h, _h; int i; IBlk * sb; union blk_pindef_t pd, ps, pt; f8_uuid uuid; cblk = __dcast__(IBlk, ICBlk, blk); h = &_h; if(__vcall__(s, get, (s, h, sizeof(struct blk_hdr_t))) != sizeof(struct blk_hdr_t) ) { return __false; } blk->h = *h; blk->h.u1.n_subblocks = 0; blk->h.u2.n_links = 0; blk->h.n_pins = 0; if(!__vcall__(s, get, (s, &blk->uuid, sizeof(blk->uuid)))) { goto __failed; } /* load sub-blocks */ for(i=0; i<h->u1.n_subblocks; i++) { sb = IBlk_from_stream(s); if(!sb) { goto __failed; } if(!ICBlk_add_blk(cblk, sb)) { delete_blk(sb); return __false; } } /* load links */ for(i=0; i<h->u2.n_links; i++) { if(!__vcall__(s, get, (s, &uuid, sizeof(uuid)))) { goto __failed; } if(!__vcall__(s, get, (s, &ps, sizeof(union blk_pindef_t)))) { goto __failed; } if(!__vcall__(s, get, (s, &pt, sizeof(union blk_pindef_t)))) { goto __failed; } locate_pin(blk, ps); locate_pin(blk, pt); if(!ps.pin || !pt.pin) { goto __failed; } if(!ICBlk_link(&uuid, ps.pin, pt.pin)) { goto __failed; } } /* load exports */ for(i=0; i<h->n_pins; i++) { if(!__vcall__(s, get, (s, &uuid, sizeof(uuid)))) { goto __failed; } if(!__vcall__(s, get, (s, &pd, sizeof(union blk_pindef_t)))) { goto __failed; } locate_pin(blk, pd); if(!pd.pin) { return __false; } if(!ICBlk_add_pin(&uuid, pd.pin)) { return __false; } } return __true; __failed: return __false; }
/* errors checked in this procedure 1) unattached DI with memory binding 2) DO without memory binding 3) DO with incorrect memory address 4) DO with conflicting address 5) multiple assignments of a variable */ __bool CErrorDetector::_fixup_pins(ITreeNode * nd) { IBlk * b; struct blk_pin_t * p; void * o; const struct blk_var_t * var; struct blk_pin_t * rp; int length; b = __dcast__(ITreeNode, IBlk, nd); for(p = __vcall__(b, first_pin, (b)); p; p = __vcall__(b, next_pin, (p))){ if(p->ulink){ continue; } rp = IBlk_real_pin(p); if(!(rp->_class == PIN_CLASS_DI || rp->_class == PIN_CLASS_DO)){ continue; } if(rp->_class == PIN_CLASS_DO && rp->binding != PIN_B_MEMORY){ // invalid binding CInvalidAddress ia; ia.magic = PIN_MAGIC; ia.o = rp; ia.a = 0; /* DO without MEMORY BINDING */ m_invalidAddress.insert(m_invalidAddress.end(), ia); } if(rp->binding != PIN_B_MEMORY){ continue; } length = _type_size(rp->type); var = (blk_var_t*)query_var_by_pin(p); if(!var){ if(rp->_class == PIN_CLASS_DI){ if(RtkIsTripleListEmpty(&rp->u1.link)){ CInvalidAddress ia; ia.magic = PIN_MAGIC; ia.o = rp; ia.a = 1; /* unattached DI with memory binding */ m_invalidAddress.insert(m_invalidAddress.end(), ia); } }else{ if(!is_address_valid(proxy_adapter->kernel, rp, &rp->u2.mem_addr)){ CInvalidAddress ia; ia.magic = PIN_MAGIC; ia.o = rp; ia.a = 2; /* invalid address */ m_invalidAddress.insert(m_invalidAddress.end(), ia); } CAddressConflit ac; /* check conflicts */ o = get_address_owner(&rp->u2.mem_addr, 1, &ac.magic2); if(o == rp){ continue; } ac.magic1 = PIN_MAGIC; ac.o1 = rp; ac.o2 = o; m_addrConflicts.insert(m_addrConflicts.end(), ac); } }else{ // the error is credited to the variable, not check here } } return __true; }