esint8 ioman_directSectorWrite(IOManager *ioman,euint32 address, euint8* buf) { euint8* ibuf; esint16 bp; if((bp=ioman_findSectorInCache(ioman,address))!=-1){ ibuf=ioman_getPtr(ioman,bp); memCpy(buf,ibuf,512); ioman_setWritable(bp); return(0); } if((bp=ioman_findFreeSpot(ioman))!=-1){ ibuf=ioman_getPtr(ioman,bp); memCpy(buf,ibuf,512); ioman_resetCacheItem(ioman,bp); ioman->sector[bp]=address; ioman_setWritable(bp); ioman_setValid(bp); return(0); } if(ioman_writeSector(ioman,address,buf)){ return(-1); } return(0); }
signed char ioman_directSectorWrite(IOManager *ioman,unsigned long address, unsigned char* buf) { unsigned char* ibuf; signed short bp; if((bp=ioman_findSectorInCache(ioman,address))!=-1){ ibuf=ioman_getPtr(ioman,bp); memCpy(buf,ibuf,512); ioman_setWritable(bp); return(0); } if((bp=ioman_findFreeSpot(ioman))!=-1){ ibuf=ioman_getPtr(ioman,bp); memCpy(buf,ibuf,512); ioman_resetCacheItem(ioman,bp); ioman->sector[bp]=address; ioman_setWritable(bp); ioman_setValid(bp); return(0); } if(ioman_writeSector(ioman,address,buf)){ return(-1); } return(0); }
esint8 ioman_directSectorRead(IOManager *ioman,euint32 address, euint8* buf) { euint8* ibuf; esint16 bp; if((bp=ioman_findSectorInCache(ioman,address))!=-1){ ibuf=ioman_getPtr(ioman,bp); memCpy(ibuf,buf,512); return(0); } if((bp=ioman_findFreeSpot(ioman))!=-1){ if((ioman_putSectorInCache(ioman,address,bp))){ return(-1); } ibuf=ioman_getPtr(ioman,bp); memCpy(ibuf,buf,512); return(0); } if(ioman_readSector(ioman,address,buf)){ return(-1); } return(0); }
signed char ioman_directSectorRead(IOManager *ioman,unsigned long address, unsigned char* buf) { unsigned char* ibuf; signed short bp; if((bp=ioman_findSectorInCache(ioman,address))!=-1){ ibuf=ioman_getPtr(ioman,bp); memCpy(ibuf,buf,512); return(0); } if((bp=ioman_findFreeSpot(ioman))!=-1){ if((ioman_putSectorInCache(ioman,address,bp))){ return(-1); } ibuf=ioman_getPtr(ioman,bp); memCpy(ibuf,buf,512); return(0); } if(ioman_readSector(ioman,address,buf)){ return(-1); } return(0); }
/** * This function will set a hook function, which will be invoked when a memory * block is allocated from heap memory. * * @param hook the hook function */ int efs_rename(struct dfs_filesystem* fs, const char* oldpath, const char* newpath) { FileRecord old_entry, new_entry; FileLocation old_loc, new_loc; efsl_fs* efsfs; eint8 fatfilename[11]; efsfs = (efsl_fs*) fs->data ; RT_ASSERT(efsfs != RT_NULL); dir_getFatFileName((eint8 *)newpath, &fatfilename[0]); /* parameters check */ if (strlen(oldpath) > DFS_PATH_MAX || strlen(newpath) > DFS_PATH_MAX || /* old path is a directory that contains newpath */ strncmp(oldpath, newpath, strlen(newpath)) == 0) { dfs_log(DFS_DEBUG_ERROR, ("old path is a directory that contains newpath")); return -DFS_STATUS_EINVAL; } /* if can't find old direntry */ if(fs_findFile(&efsfs->filesystem, (eint8 *)oldpath, &old_loc, 0) == 0) { dfs_log(DFS_DEBUG_ERROR, ("can't find old direntry")); return -DFS_STATUS_ENOENT; } dir_getFileStructure(&efsfs->filesystem, &old_entry, &old_loc); /* if the new direntry exist */ if(fs_findFile(&efsfs->filesystem, (eint8 *)newpath, &new_loc, 0) > 0) { dfs_log(DFS_DEBUG_ERROR, ("new direntry existed")); return -DFS_STATUS_ENOENT; } if(fs_findFreeFile(&efsfs->filesystem, (eint8 *)newpath, &new_loc, 0)) { memCpy(&old_entry, &new_entry, sizeof(FileRecord)); memCpy(fatfilename, new_entry.FileName, 11); dir_createDirectoryEntry(&efsfs->filesystem, &new_entry, &new_loc); } /* delete the old direntry */ old_entry.FileName[0] = 0xe5; dir_updateDirectoryEntry(&efsfs->filesystem, &old_entry, &old_loc); return 0; }
static void stringSubst2 ( char * const bsrcptr, char * const bdstptr, const char * const pattstr, const char * const replstr, const int pattsiz, const int replsiz) { char * pattptr; int pattidx; pattptr = strstr (bsrcptr, pattstr); /* Search for the pattern in the remaining source string */ pattidx = (pattptr == NULL) ? (strlen (bsrcptr) + 1): (pattptr - bsrcptr); /* Get length of unchanged part */ if (replsiz < pattsiz) /* If replacement is smaller, pre-move unchanged part */ memMov (bdstptr, bsrcptr, pattidx * sizeof (char)); if (pattptr != NULL) /* If remaining part of string has to be processed */ stringSubst2 (pattptr + pattsiz, bdstptr + pattidx + replsiz, pattstr, replstr, pattsiz, replsiz); if (replsiz > pattsiz) /* If replacement is longer, post-move unchanged part */ memMov (bdstptr, bsrcptr, pattidx * sizeof (char)); if (pattptr != NULL) /* If there is something to replace */ memCpy (bdstptr + pattidx, replstr, replsiz * sizeof (char)); /* Write replacement string */ return; }
static void dup_parent_class(struct ZObjClass *self) { if(self->parent == NULL) return; struct ZObjClass *new_parent = malloc(sizeof(struct ZObjClass)); assert(new_parent != NULL); memset(new_parent, 0, sizeof(struct ZObjClass)); new_parent->class_name = self->parent->class_name; new_parent->parent = self->parent->parent; new_parent->constructor = self->parent->constructor; new_parent->destructor = self->parent->destructor; new_parent->interfaces = makeMem(getMemIndex(self->parent->interfaces)); new_parent->class_body = makeMem(getMemIndex(self->parent->class_body)); memCpy(&new_parent->class_body, getMemPtr(&self->parent->class_body, 0, 0), getMemIndex(self->parent->class_body)); for(int i = 0; i < GET_ITEM_NUM(self->parent->interfaces, struct ZObjInterface); ++i) { struct InterfaceInfo *info = find_interface(GET_TYPE_MEM(&self->parent->interfaces, struct ZObjInterface, i)->interface_name); if(info == NULL) { printf("CRITICAL: can't find interface %s when dup_parent_class\n", GET_TYPE_MEM(&self->parent->interfaces,struct ZObjInterface, i)->interface_name); continue; } void *body = malloc(info->struct_size); assert(body != NULL); if(GET_TYPE_MEM(&self->parent->interfaces, struct ZObjInterface, i)->interface_body) memcpy(body, GET_TYPE_MEM(&self->parent->interfaces, struct ZObjInterface, i)->interface_body, info->struct_size); ADD_ITEM(&new_parent->interfaces, struct ZObjInterface, ((struct ZObjInterface){ GET_TYPE_MEM(&self->parent->interfaces,struct ZObjInterface, i)->interface_name, body }));
void kgraphStoreSave ( const Kgraph * const grafptr, KgraphStore * const storptr) { storptr->mflaval = grafptr->commload; storptr->domnnbr = grafptr->m.domnnbr; storptr->fronnbr = grafptr->fronnbr; storptr->kbalval = grafptr->kbalval; storptr->commload = grafptr->commload; memCpy (storptr->parttab, grafptr->m.parttax + grafptr->s.baseval, grafptr->s.vertnbr * sizeof (Anum)); memCpy (storptr->domntab, grafptr->m.domntab, grafptr->m.domnnbr * sizeof (ArchDom)); memCpy (storptr->frontab, grafptr->frontab, storptr->fronnbr * sizeof (Gnum)); memCpy (storptr->comploadavg, grafptr->comploadavg, storptr->partnbr * sizeof (Gnum)); memCpy (storptr->comploaddlt, grafptr->comploaddlt, storptr->partnbr * sizeof (Gnum)); }
/* **************************************************************************** * void dir_createDirectoryEntry(FileSystem *fs,FileRecord *filerec,FileLocation *loc) * Description: This function writes the filerecord stored in filerec to disc at * location loc. * Return value: void */ void dir_createDirectoryEntry(FileSystem *fs,FileRecord *filerec,FileLocation *loc) { euint8 *buf; buf = part_getSect(fs->part,loc->Sector,IOM_MODE_READWRITE); memCpy(filerec,buf+(loc->Offset*sizeof(*filerec)),sizeof(*filerec)); part_relSect(fs->part,buf); }
void ls_fileEntryToDirListEntry(DirList *dlist, euint8* buf, euint16 offset) { if(offset>480 || offset%32)return; buf+=offset; memCpy(buf+OFFSET_DE_FILENAME,dlist->currentEntry.FileName,LIST_MAXLENFILENAME); dlist->currentEntry.Attribute = *(buf+OFFSET_DE_ATTRIBUTE); dlist->currentEntry.FileSize = ex_getb32(buf,OFFSET_DE_FILESIZE); }
/* **************************************************************************** * esint8 dir_updateDirectoryEntry(FileSystem *fs,FileRecord *entry,FileLocation *loc)) * This function changes the entire entity stores at loc to the data recorded * in entry. This is for custom updates to the directoryentry. * Return value: 0 on success, -1 on failure */ esint8 dir_updateDirectoryEntry(FileSystem *fs,FileRecord *entry,FileLocation *loc) { euint8 *buf; buf = part_getSect(fs->part,loc->Sector,IOM_MODE_READWRITE); memCpy(entry,buf+(loc->Offset*sizeof(*entry)),sizeof(*entry)); part_relSect(fs->part,buf); return(0); }
/* **************************************************************************** * euint32 file_fread(File *file,euint32 offset, euint32 size,euint8 *buf) * Description: This function reads 'size' bytes from 'file' starting at * 'offset' and puts the result in '*buf'. * Return value: amount of bytes actually read (can differ from the given * size when the file was smaller */ euint32 file_fread(File *file,euint32 offset, euint32 size,euint8 *buf) { //OSTaskSuspend(1); euint32 bytes_read=0,size_left=size,coffset=offset; euint32 cclus,csec,cbyte; euint32 rclus,rsec; euint32 btr; euint8 *tbuf; if(!file_getAttr(file,FILE_STATUS_OPEN))return(0); if(offset>=file->FileSize) size_left=0; /* Offset check */ if( (offset+size > file->FileSize) && size_left!=0) size_left=file->FileSize-offset; while(size_left>0){ //printf("size_left = %d\n", size_left); cclus = coffset/(512*file->fs->volumeId.SectorsPerCluster); csec = (coffset/(512))%file->fs->volumeId.SectorsPerCluster; cbyte = coffset%512; if(cbyte!=0 || size_left<512){ btr = 512-(coffset%512)>=size_left?size_left:512-(coffset%512); }else{ btr = 512; } if((fat_LogicToDiscCluster(file->fs,&(file->Cache),cclus))!=0){ return(0); } rclus=file->Cache.DiscCluster; rsec=fs_clusterToSector(file->fs,rclus); if(btr==512){ /*part_readBuf(file->fs->part,rsec+csec,buf+bytes_read);*/ part_directSectorRead(file->fs->part,rsec+csec,buf+bytes_read); }else{ /*part_readBuf(file->fs->part,rsec+csec,tbuf);*/ tbuf = part_getSect(file->fs->part,rsec+csec,IOM_MODE_READONLY); memCpy(tbuf+(coffset%512),buf+bytes_read,btr); part_relSect(file->fs->part,tbuf); } coffset+=btr; bytes_read+=btr; size_left-=btr; } //OSTaskResume(1); return(bytes_read); }
void symbolRealloc ( SymbolMatrix * const symbptr) { SymbolCblk * cblktab = NULL; SymbolBlok * bloktab = NULL; if ((cblktab = (SymbolCblk *) memAlloc ((symbptr->cblknbr + 1) * sizeof (SymbolCblk))) == NULL) return; /* Cannot move smallest array */ memCpy (cblktab, symbptr->cblktab, (symbptr->cblknbr + 1) * sizeof (SymbolCblk)); memFree (symbptr->cblktab); /* Move column block array */ symbptr->cblktab = cblktab; if ((bloktab = (SymbolBlok *) memAlloc (symbptr->bloknbr * sizeof (SymbolBlok))) == NULL) return; /* Cannot move array */ memCpy (bloktab, symbptr->bloktab, symbptr->bloknbr * sizeof (SymbolBlok)); memFree (symbptr->bloktab); /* Move column block array */ symbptr->bloktab = bloktab; }
//重新分配内存(外部调用) //memx:所属内存块 //*ptr:旧内存首地址 //size:要分配的内存大小(字节) //返回值:新分配到的内存首地址. void *cJsonRealloc(void *ptr,uint32_t size) { uint32_t offset; offset=memMalloc(size); if(offset==0XFFFFFFFF)return NULL; else { memCpy((void*)((uint32_t)mallco_dev.membase+offset),ptr,size); //拷贝旧内存内容到新内存 cJsonFree(ptr); //释放旧内存 return (void*)((uint32_t)mallco_dev.membase+offset); //返回新内存首地址 } }
/* **************************************************************************** * unsigned long file_fread(File *file,unsigned long offset, unsigned long size,unsigned char *buf) * Description: This function reads 'size' bytes from 'file' starting at * 'offset' and puts the result in '*buf'. * Return value: amount of bytes actually read (can differ from the given * size when the file was smaller */ unsigned long file_fread(File *file,unsigned long offset, unsigned long size,unsigned char *buf) { unsigned long bytes_read=0,size_left=size,coffset=offset; unsigned long cclus,csec,cbyte; unsigned long rclus,rsec; unsigned long btr; unsigned char *tbuf; if(!file_getAttr(file,FILE_STATUS_OPEN))return(0); if(offset>=file->FileSize) size_left=0; /* Offset check */ if( (offset+size > file->FileSize) && size_left!=0) size_left=file->FileSize-offset; while(size_left>0){ cclus = coffset/(512*file->fs->volumeId.SectorsPerCluster); csec = (coffset/(512))%file->fs->volumeId.SectorsPerCluster; cbyte = coffset%512; if(cbyte!=0 || size_left<512){ btr = 512-(coffset%512)>=size_left?size_left:512-(coffset%512); }else{ btr = 512; } if((fat_LogicToDiscCluster(file->fs,&(file->Cache),cclus))!=0){ return(0); } rclus=file->Cache.DiscCluster; rsec=fs_clusterToSector(file->fs,rclus); if(btr==512){ /*part_readBuf(file->fs->part,rsec+csec,buf+bytes_read);*/ part_directSectorRead(file->fs->part,rsec+csec,buf+bytes_read); }else{ /*part_readBuf(file->fs->part,rsec+csec,tbuf);*/ tbuf = part_getSect(file->fs->part,rsec+csec,IOM_MODE_READONLY); memCpy(tbuf+(coffset%512),buf+bytes_read,btr); part_relSect(file->fs->part,tbuf); } coffset+=btr; bytes_read+=btr; size_left-=btr; } return(bytes_read); }
static int thread_read( UThread* ut, UBuffer* port, UCell* dest, int part ) { UBuffer tbuf; ThreadExt* ext = (ThreadExt*) port->ptr.v; ThreadQueue* queue; (void) part; tbuf.type = 0; queue = (port->SIDE == SIDE_A) ? &ext->B : &ext->A; if( ! queue->readIt ) readEvent( queue ); // Waits until data is available. mutexLock( queue->mutex ); while( queue->readIt >= queue->buf.used ) { if( condWaitF( queue->cond, queue->mutex ) ) { mutexUnlock( queue->mutex ); goto waitError; } } queue->readIt = thread_dequeue( &queue->buf, queue->readIt, dest, &tbuf ); mutexUnlock( queue->mutex ); if( tbuf.type ) { UIndex bufN; dest->series.buf = UR_INVALID_BUF; ur_genBuffers( ut, 1, &bufN ); dest->series.buf = bufN; memCpy( ur_buffer( bufN ), &tbuf, sizeof(UBuffer) ); } else { int type = ur_type(dest); if( ur_isWordType(type) ) { if( ur_binding(dest) == UR_BIND_THREAD ) ur_unbind(dest); } } return UR_OK; waitError: return ur_error( ut, UR_ERR_INTERNAL, "thread_read condWait failed" ); }
void kgraphStoreUpdt ( Kgraph * const grafptr, const KgraphStore * const storptr) { grafptr->commload = storptr->mflaval; grafptr->m.domnnbr = storptr->domnnbr; grafptr->fronnbr = storptr->fronnbr; grafptr->kbalval = storptr->kbalval; grafptr->commload = storptr->commload; memCpy (grafptr->m.parttax + grafptr->s.baseval, storptr->parttab, grafptr->s.vertnbr * sizeof (Anum)); memCpy (grafptr->m.domntab, storptr->domntab, grafptr->m.domnnbr * sizeof (ArchDom)); memCpy (grafptr->frontab, storptr->frontab, storptr->fronnbr * sizeof (Gnum)); memCpy (grafptr->comploadavg, storptr->comploadavg, storptr->partnbr * sizeof (Gnum)); memCpy (grafptr->comploaddlt, storptr->comploaddlt, storptr->partnbr * sizeof (Gnum)); #ifdef SCOTCH_DEBUG_KGRAPH2 if (kgraphCheck (grafptr) != 0) errorPrint ("kgraphStoreUpdt: inconsistent graph data"); #endif /* SCOTCH_DEBUG_KGRAPH2 */ }
static UIndex thread_dequeue( UBuffer* qbuf, UIndex it, UCell* dest, UBuffer* transitBuf ) { *dest = qbuf->ptr.cell[ it ]; ++it; if( ur_isSeriesType(ur_type(dest)) && ! ur_isShared( dest->series.buf ) ) { memCpy( transitBuf, qbuf->ptr.cell + it, sizeof(UBuffer) ); ++it; } if( it == qbuf->used ) it = qbuf->used = 0; return it; }
/* **************************************************************************** * void dir_createDefaultEntry(FileSystem *fs,FileRecord *filerec,eint8* fatfilename) * Description: This function fills in a filerecord with safe default values, and * a given fatfilename. If your system has a means of knowing time, here is an * excellent place to apply it to the filerecord. * Return value: void */ void dir_createDefaultEntry(FileSystem *fs,FileRecord *filerec,eint8* fatfilename) { memCpy(fatfilename,filerec->FileName,11); filerec->Attribute=0x00; filerec->NTReserved=0x00; filerec->MilliSecTimeStamp=0x00; filerec->CreatedTime=time_getTime(); filerec->CreatedDate=time_getDate(); filerec->AccessDate=filerec->CreatedDate; filerec->FirstClusterHigh=0x0000; filerec->WriteTime=filerec->CreatedTime; filerec->WriteDate=filerec->CreatedDate; filerec->FirstClusterLow=0x0000; filerec->FileSize=0x00000000; }
void vmeshStoreUpdt ( Vmesh * const meshptr, const VmeshStore * const storptr) { byte * frontab; /* Pointer to frontier data save area */ byte * parttab; /* Pointer to part data save area */ meshptr->ecmpsize[0] = storptr->ecmpsize[0]; /* Load partition parameters */ meshptr->ecmpsize[1] = storptr->ecmpsize[1]; meshptr->ncmpload[0] = storptr->ncmpload[0]; meshptr->ncmpload[1] = storptr->ncmpload[1]; meshptr->ncmpload[2] = storptr->ncmpload[2]; meshptr->ncmploaddlt = storptr->ncmploaddlt; meshptr->ncmpsize[0] = storptr->ncmpsize[0]; meshptr->ncmpsize[1] = storptr->ncmpsize[1]; meshptr->fronnbr = storptr->fronnbr; frontab = storptr->datatab; /* Compute data offsets within save structure */ parttab = frontab + storptr->fronnbr * sizeof (Gnum); memCpy (meshptr->frontab, frontab, storptr->fronnbr * sizeof (Gnum)); memCpy (meshptr->parttax + meshptr->m.baseval, parttab, (meshptr->m.velmnbr + meshptr->m.vnodnbr) * sizeof (GraphPart)); }
static void thread_queue( UBuffer* qbuf, const UCell* data, UBuffer* dataBuf ) { ur_arrReserve( qbuf, qbuf->used + 2 ); qbuf->ptr.cell[ qbuf->used ] = *data; ++qbuf->used; if( dataBuf ) { memCpy( qbuf->ptr.cell + qbuf->used, dataBuf, sizeof(UBuffer) ); ++qbuf->used; // Buffer is directly transferred through port to avoid copying. dataBuf->used = 0; dataBuf->ptr.v = 0; } }
/* **************************************************************************** * esint8 dir_getFatFileName(eint8* filename, eint8* fatfilename) * This function will take a full directory path, and strip off all leading * dirs and characters, leaving you with the MS-DOS notation of the actual filename. * Return value: 1 on success, 0 on not being able to produca a filename */ esint8 dir_getFatFileName(eint8* filename, eint8* fatfilename) { eint8 ffnamec[11],*next,nn=0; memClr(ffnamec,11); memClr(fatfilename,11); next = filename; if(*filename=='/')next++; while((next=file_normalToFatName(next,ffnamec))){ memCpy(ffnamec,fatfilename,11); nn++; } if(nn)return(1); return(0); }
signed short mkfs_makevfat(Partition *part) { unsigned long c,cc,ret; unsigned long ns,fs,ds,dc; unsigned char buf[512]; ns=part->disc->partitions[part->activePartition].numSectors; if( ns < 66581 ) { DBG((TXT("This is not possible due to insufficient sectors. Sorry\n"))); return(MKFS_ERR_TOOLITTLESECTORS); } ret=0; for(c=1<<6; c>=1; c>>=1) { /* First guess */ ds = ns - 32; fs = ((ds/c)+127)/128; /* ds was guess too large, so fs is too large now too. */ for(cc=0; cc<2; cc++) { /* Round 2, error round */ ds = ns - 32 - 2*fs; fs = ((ds/c)+127)/128; /* Since fs was too large, ds became too small. So the fs for this small ds is too small as well. */ /* Round 3, correction round */ ds = ns - 32 - 2*fs; fs = ((ds/c)+127)/128; /* The fs was too small, so ds was too large. The calculated fs should be slightly too large. */ } /* Round 4, finalise */ ds = ns - 32 - 2*fs; dc = ds / c; if(ret<(fs*128-dc)/128)ret=(fs*128-dc)/128; /* Check if with current setting we have a valid fat ? */ if(dc >= 65525 + 16) { break; } } /* Generate BPB */ memClr(buf,512); /* Boot code */ *(buf+0)=0xE9; *(buf+1)=0x00; *(buf+2)=0x00; /* RESET */ /* OEM name */ memCpy("DSCOSMSH",buf+3,8); /* Bytes/Sector */ *((unsigned short*)(buf+11)) = 512; /* Sectors/Cluster */ *(buf+13) = c; /* Reserved Sectors */ *((unsigned short*)(buf+14)) = 32; /* Number of FAT Tables */ *(buf+16) = 2; /* RootEntryCount */ *((unsigned short*)(buf+17)) = 0; /* Total Sector Count __16 */ *((unsigned short*)(buf+19)) = 0; /* Media (crap) */ *(buf+21) = 0xF8; /* FAT size 16 */ *((unsigned short*)(buf+22)) = 0; /* Total Sector Count __32 */ *((unsigned long*)(buf+32)) = ns; /* Fat Size 32 */ *((unsigned long*)(buf+36)) = fs; /* First Cluster Root Dir */ *((unsigned long*)(buf+44)) = 2; /* VolumeID */ *((unsigned long*)(buf+67)) = 0x13371337; /* Volume Label */ memCpy("DISCOSMASH!",buf+71,11); /* Filesystemtype */ memCpy("FAT32 ",buf+82,8); /* Magic */ *(buf+510) = 0x55; *(buf+511) = 0xAA; part_writeBuf(part,0,buf); memClr(buf,512); for(c=32; c<(32+2*fs); c++) { part_writeBuf(part,c,buf); } *(((unsigned long*)buf) )=0x0FFFFFF8; *(((unsigned long*)buf)+1)=0x0FFFFFFF; *(((unsigned long*)buf)+2)=0x0FFFFFF8; part_writeBuf(part,32,buf); part_writeBuf(part,32+fs,buf); return(0); }
void kass(int levelk, int rat, SymbolMatrix * symbptr, PASTIX_INT baseval, PASTIX_INT vertnbr, PASTIX_INT edgenbr, PASTIX_INT * verttab, PASTIX_INT * edgetab, Order * orderptr, MPI_Comm pastix_comm) { PASTIX_INT snodenbr; PASTIX_INT *snodetab = NULL; PASTIX_INT *treetab = NULL; PASTIX_INT *ia = NULL; PASTIX_INT *ja = NULL; PASTIX_INT i, j, n; PASTIX_INT ind; csptr mat; PASTIX_INT *tmpj = NULL; PASTIX_INT *perm = NULL; PASTIX_INT *iperm = NULL; PASTIX_INT newcblknbr; PASTIX_INT *newrangtab = NULL; Dof dofstr; Clock timer1; double nnzS; int procnum; (void)edgenbr; MPI_Comm_rank(pastix_comm,&procnum); #ifdef DEBUG_KASS print_one("--- kass begin ---\n"); #endif /* graphData (graphptr, */ /* (SCOTCH_Num * )&baseval, */ /* (SCOTCH_Num * )&vertnbr, */ /* (SCOTCH_Num **)&verttab, */ /* NULL, NULL, NULL, */ /* (SCOTCH_Num * )&edgenbr, */ /* (SCOTCH_Num **)&edgetab, */ /* NULL); */ n = vertnbr; ia = verttab; ja = edgetab; perm = orderptr->permtab; iperm = orderptr->peritab; /*** Convert Fortran to C numbering ***/ if(baseval == 1) { for(i=0;i<=n;i++) ia[i]--; for(i=0;i<n;i++) for(j=ia[i];j<ia[i+1];j++) ja[j]--; for(i=0;i<n;i++) orderptr->permtab[i]--; for(i=0;i<n;i++) orderptr->peritab[i]--; } MALLOC_INTERN(treetab, n, PASTIX_INT); #ifndef SCOTCH_SNODE /*if(rat != -1 )*/ { /***** FIND THE SUPERNODE PARTITION FROM SCRATCH ********/ /*** Find the supernodes of the direct factorization ***/ MALLOC_INTERN(snodetab, n+1, PASTIX_INT); clockInit(&timer1); clockStart(&timer1); find_supernodes(n, ia, ja, perm, iperm, &snodenbr, snodetab, treetab); clockStop(&timer1); print_one("Time to find the supernode (direct) %.3g s \n", clockVal(&timer1)); /*memfree(treetab);*/ print_one("Number of supernode for direct factorization %ld \n", (long)snodenbr); } #else /*else*/ { /***** USE THE SUPERNODE PARTITION OF SCOTCH ********/ snodenbr = orderptr->cblknbr; MALLOC_INTERN(snodetab, n+1, PASTIX_INT); memCpy(snodetab, orderptr->rangtab, sizeof(PASTIX_INT)*(snodenbr+1)); print_one("Number of column block found in scotch (direct) %ld \n", (long)snodenbr); } #endif /****************************************/ /* Convert the graph */ /****************************************/ MALLOC_INTERN(mat, 1, struct SparRow); initCS(mat, n); MALLOC_INTERN(tmpj, n, PASTIX_INT); /**** Convert and permute the matrix in sparrow form ****/ /**** The diagonal is not present in the CSR matrix, we have to put it in the matrix ***/ bzero(tmpj, sizeof(PASTIX_INT)*n); for(i=0;i<n;i++) { /*** THE GRAPH DOES NOT CONTAIN THE DIAGONAL WE ADD IT ***/ tmpj[0] = i; ind = 1; for(j=ia[i];j<ia[i+1];j++) tmpj[ind++] = ja[j]; mat->nnzrow[i] = ind; MALLOC_INTERN(mat->ja[i], ind, PASTIX_INT); memCpy(mat->ja[i], tmpj, sizeof(PASTIX_INT)*ind); mat->ma[i] = NULL; } CS_Perm(mat, perm); /*** Reorder the matrix ***/ sort_row(mat); memFree(tmpj); /***** COMPUTE THE SYMBOL MATRIX OF ILU(K) WITH AMALGAMATION *****/ kass_symbol(mat, levelk, (double)(rat)/100.0, perm, iperm, snodenbr, snodetab, treetab, &newcblknbr, &newrangtab, symbptr, pastix_comm); cleanCS(mat); memFree(mat); memFree(treetab); dofInit(&dofstr); dofConstant(&dofstr, 0, symbptr->nodenbr, 1); nnzS = recursive_sum(0, symbptr->cblknbr-1, nnz, symbptr, &dofstr); print_one("Number of non zero in the non patched symbol matrix = %g, fillrate1 %.3g \n", nnzS+n, (nnzS+n)/(ia[n]/2.0 +n)); dofExit(&dofstr); if(symbolCheck(symbptr) != 0) { errorPrint("SymbolCheck after kass_symbol."); ASSERT(0, MOD_KASS); } if(levelk != -1) { /********************************************************/ /** ADD BLOCKS IN ORDER TO GET A REAL ELIMINATION TREE **/ /********************************************************/ Patch_SymbolMatrix(symbptr); } dofInit(&dofstr); dofConstant(&dofstr, 0, symbptr->nodenbr, 1); nnzS = recursive_sum(0, symbptr->cblknbr-1, nnz, symbptr, &dofstr); dofExit(&dofstr); print_one("Number of block in final symbol matrix = %ld \n", (long)symbptr->bloknbr); print_one("Number of non zero in final symbol matrix = %g, fillrate2 %.3g \n", nnzS+n, (nnzS+n)/(ia[n]/2.0 +n)); if(symbolCheck(symbptr) != 0) { errorPrint("SymbolCheck after Patch_SymbolMatrix."); ASSERT(0, MOD_KASS); } #ifdef DEBUG_KASS print_one("--- kass end ---\n"); #endif memFree(snodetab); orderptr->cblknbr = newcblknbr; memFree(orderptr->rangtab); orderptr->rangtab = newrangtab; }
void Patch_SymbolMatrix(SymbolMatrix *symbmtx) { PASTIX_INT i,j, k; PASTIX_INT vroot; PASTIX_INT *father = NULL; /** For the cblk of the symbol matrix **/ SymbolBlok *newbloktab = NULL; SymbolCblk *cblktab = NULL; SymbolBlok *bloktab = NULL; csptr Q; cblktab = symbmtx->cblktab; bloktab = symbmtx->bloktab; MALLOC_INTERN(father, symbmtx->cblknbr, PASTIX_INT); MALLOC_INTERN(newbloktab, symbmtx->bloknbr + symbmtx->cblknbr, SymbolBlok); MALLOC_INTERN(Q, 1, struct SparRow); initCS(Q, symbmtx->cblknbr); /* Count how many extra-diagonal bloks are facing each diagonal blok */ for(i=0;i<symbmtx->cblknbr;i++) for(j=cblktab[i].bloknum+1;j<cblktab[i+1].bloknum;j++) Q->nnzrow[bloktab[j].cblknum]++; /* Allocate nFacingBlok integer for each diagonal blok */ for(i=0;i<symbmtx->cblknbr;i++) { MALLOC_INTERN(Q->ja[i], Q->nnzrow[i], PASTIX_INT); Q->ma[i] = NULL; } for(i=0;i<symbmtx->cblknbr;i++) Q->nnzrow[i] = 0; /* Q->ja[k] will contain, for each extra-diagonal facing blok * of the column blok k, its column blok. */ for(i=0;i<symbmtx->cblknbr;i++) for(j=cblktab[i].bloknum+1;j<cblktab[i+1].bloknum;j++) { k = bloktab[j].cblknum; Q->ja[k][Q->nnzrow[k]++] = i; } for(i=0;i<Q->n;i++) father[i] = -1; for(i=0;i<Q->n;i++) { /* for each blok facing diagonal blok i, * belonging to column blok k. * */ for(j=0;j<Q->nnzrow[i];j++) { k = Q->ja[i][j]; #ifdef DEBUG_KASS assert(k<i); #endif vroot = k; while(father[vroot] != -1 && father[vroot] != i) vroot = father[vroot]; father[vroot] = i; } } for(i=0;i<Q->n;i++) if(father[i] == -1) father[i]=i+1; cleanCS(Q); memFree(Q); k = 0; for(i=0;i<symbmtx->cblknbr-1;i++) { PASTIX_INT odb, fbloknum; fbloknum = cblktab[i].bloknum; memCpy(newbloktab+k, bloktab + fbloknum, sizeof(SymbolBlok)); cblktab[i].bloknum = k; k++; odb = cblktab[i+1].bloknum-fbloknum; if(odb <= 1 || bloktab[fbloknum+1].cblknum != father[i]) { /** Add a blok toward the father **/ newbloktab[k].frownum = cblktab[ father[i] ].fcolnum; newbloktab[k].lrownum = cblktab[ father[i] ].fcolnum; /** OIMBE try lcolnum **/ newbloktab[k].cblknum = father[i]; #ifdef DEBUG_KASS if(father[i] != i) assert(cblktab[father[i]].fcolnum > cblktab[i].lcolnum); #endif newbloktab[k].levfval = 0; k++; } if( odb > 1) { memCpy(newbloktab +k, bloktab + fbloknum+1, sizeof(SymbolBlok)*(odb-1)); k+=odb-1; } } /** Copy the last one **/ memCpy(newbloktab+k, bloktab + symbmtx->cblktab[symbmtx->cblknbr-1].bloknum, sizeof(SymbolBlok)); cblktab[symbmtx->cblknbr-1].bloknum = k; k++; /** Virtual cblk **/ symbmtx->cblktab[symbmtx->cblknbr].bloknum = k; #ifdef DEBUG_KASS assert(k >= symbmtx->bloknbr); assert(k < symbmtx->cblknbr+symbmtx->bloknbr); #endif symbmtx->bloknbr = k; memFree(symbmtx->bloktab); MALLOC_INTERN(symbmtx->bloktab, k, SymbolBlok); memCpy( symbmtx->bloktab, newbloktab, sizeof(SymbolBlok)*symbmtx->bloknbr); /* virtual cblk to avoid side effect in the loops on cblk bloks */ cblktab[symbmtx->cblknbr].bloknum = k; memFree(father); memFree(newbloktab); }
void Build_SymbolMatrix(csptr P, PASTIX_INT cblknbr, PASTIX_INT *rangtab, SymbolMatrix *symbmtx) { PASTIX_INT i, j, k, l; PASTIX_INT cblknum; PASTIX_INT ind; PASTIX_INT *tmpj = NULL; double *tmpa = NULL; PASTIX_INT *node2cblk = NULL; PASTIX_INT *ja = NULL; PASTIX_INT n; n = rangtab[cblknbr]; /**** First we transform the P matrix to find the block ****/ MALLOC_INTERN(tmpj, n, PASTIX_INT); MALLOC_INTERN(tmpa, n, double); MALLOC_INTERN(node2cblk, n, PASTIX_INT); for(k=0;k<cblknbr;k++) for(i=rangtab[k];i<rangtab[k+1];i++) node2cblk[i] = k; for(k=0;k<cblknbr;k++) { /*i = rangtab[k];*/ /*OLD VERSION QUAND P pas recompacte */ i = k; #ifdef DEBUG_KASS ASSERT(P->nnzrow[i] >= (rangtab[k+1]-rangtab[k]), MOD_KASS); for(l=0;l<rangtab[k+1]-rangtab[k];l++) { ASSERT(P->ja[i][l] == rangtab[k]+l, MOD_KASS); ASSERT(node2cblk[P->ja[i][l]] == i, MOD_KASS); } #endif ja = P->ja[i]; j = 0; ind = 0; while(j<P->nnzrow[i]) { cblknum = node2cblk[ja[j]]; l=j+1; while(l < P->nnzrow[i] && ja[l] == ja[l-1]+1 && node2cblk[ja[l]] == cblknum) l++; tmpj[ind] = ja[j]; tmpa[ind] = (double)(l-j); j = l; ind++; } memFree(P->ja[i]); P->nnzrow[i] = ind; MALLOC_INTERN(P->ja[i], ind, PASTIX_INT); MALLOC_INTERN(P->ma[i], ind, double); memCpy(P->ja[i], tmpj, sizeof(PASTIX_INT)*ind); memCpy(P->ma[i], tmpa, sizeof(double)*ind); } memFree(tmpj); memFree(tmpa); #ifdef DEBUG_KASS for(k=0;k<cblknbr;k++) { /*i = rangtab[k];*/ i = k; assert(P->nnzrow[i] > 0); if(P->ma[i][0] != (double)(rangtab[k+1]-rangtab[k])) print_one("Cblk %ld ma %ld rg %ld \n", k, (PASTIX_INT)P->ma[i][0],rangtab[k+1]-rangtab[k]); assert(P->ma[i][0] == (double)(rangtab[k+1]-rangtab[k])); } #endif /**********************************/ /*** Compute the symbol matrix ****/ /**********************************/ symbmtx->baseval = 0; symbmtx->cblknbr = cblknbr; ind = 0; symbmtx->bloknbr = CSnnz(P); symbmtx->nodenbr = rangtab[cblknbr]; MALLOC_INTERN(symbmtx->cblktab, cblknbr+1, SymbolCblk); MALLOC_INTERN(symbmtx->bloktab, symbmtx->bloknbr, SymbolBlok); ind = 0; for(k=0;k<cblknbr;k++) { symbmtx->cblktab[k].fcolnum = rangtab[k]; symbmtx->cblktab[k].lcolnum = rangtab[k+1]-1; symbmtx->cblktab[k].bloknum = ind; /*l = rangtab[k];*/ /** OLD VERSION **/ l = k; for(i=0;i<P->nnzrow[l];i++) { j = P->ja[l][i]; symbmtx->bloktab[ind].frownum = j; symbmtx->bloktab[ind].lrownum = j+(PASTIX_INT)(P->ma[l][i])-1; symbmtx->bloktab[ind].cblknum = node2cblk[j]; symbmtx->bloktab[ind].levfval = 0; ind++; } #ifdef DEBUG_KASS assert(symbmtx->bloktab[symbmtx->cblktab[k].bloknum].frownum == symbmtx->cblktab[k].fcolnum); assert(symbmtx->bloktab[symbmtx->cblktab[k].bloknum].lrownum == symbmtx->cblktab[k].lcolnum); assert(symbmtx->bloktab[symbmtx->cblktab[k].bloknum].cblknum == k); #endif } /* virtual cblk to avoid side effect in the loops on cblk bloks */ symbmtx->cblktab[cblknbr].fcolnum = symbmtx->cblktab[cblknbr-1].lcolnum+1; symbmtx->cblktab[cblknbr].lcolnum = symbmtx->cblktab[cblknbr-1].lcolnum+1; symbmtx->cblktab[cblknbr].bloknum = ind; #ifdef DEBUG_KASS if(ind != symbmtx->bloknbr) fprintf(stderr, "ind %ld bloknbr %ld \n", ind, symbmtx->bloknbr); assert(ind == symbmtx->bloknbr); #endif memFree(node2cblk); }
static void itemview_rebuildAttr( UThread* ut, GItemView* ep, const UBuffer* items, int page ) { #define MAX_ITEM_TRIS 400 #define MAX_DEC_TRIS 100 #define TRI_ATTR_BYTES (3 * AttrCount * sizeof(GLfloat)) DrawContext dc; UBlockIter bi; UBlockIter layout; UBuffer* fcBuf; const UCell* loStart; UCell* cell; float* attr; int bsize; int height = ep->itemHeight; int caOffset = items->used + DECORATION_GROUPS; // Reserve triangles for each item. ur_binReserve( &glEnv.tmpBin, (MAX_DEC_TRIS + (items->used * MAX_ITEM_TRIS)) * TRI_ATTR_BYTES ); attr = glEnv.tmpBin.ptr.f; // Reserve first & count arrays. fcBuf->used tracks the number of items // and view decorations, which is half the number of integers used for // both arrays. fcBuf = &ep->fc[ page ]; ur_arrReserve( fcBuf, caOffset * 2 ); fcBuf->used = 0; dc.attr = attr; dc.drawFirst = 0; dc.penX = 0.0; #if 1 // Build selected background tris. dc.drawCount = 0; if( ep->selRow > -1 ) { dc.color[0] = 1.0; dc.color[1] = dc.color[2] = 0.0; dc.penY = ep->wid.area.h; cell = glEnv.guiStyle + CI_STYLE_AREA; //ur_setId(cell, UT_COORD) cell->coord.len = 4; cell->coord.n[0] = 0; cell->coord.n[1] = (ep->selRow + 1) * -height; cell->coord.n[2] = ep->itemWidth; cell->coord.n[3] = height; layout.buf = ur_buffer( ep->selectBgBlkN ); layout.it = layout.buf->ptr.cell; layout.end = layout.it + layout.buf->used; if( ! itemview_parse( &dc, ut, &layout, (GWidget*) ep ) ) { boron_reset(ut); printf( "KR itemview_parse failed\n" ); } } fcBuf->ptr.i[ fcBuf->used ] = dc.drawFirst; fcBuf->ptr.i[ fcBuf->used + caOffset ] = dc.drawCount; ++fcBuf->used; dc.attr = attr + MAX_DEC_TRIS * 3 * AttrCount; dc.drawFirst = MAX_DEC_TRIS * 3; #endif dc.penY = ep->wid.area.h; // Setup the data item and layout iterators. bi.it = items->ptr.cell; bi.end = bi.it + items->used; layout.buf = ur_buffer( ep->layoutBlkN ); loStart = layout.buf->ptr.cell; layout.end = loStart + layout.buf->used; ur_foreach( bi ) { // Set item word to current data value. cell = ur_ctxCell( ur_buffer( ep->bindCtxN ), 0 ); *cell = *bi.it; dc.drawCount = 0; dc.color[0] = 1.0; dc.color[1] = dc.color[2] = 0.0; dc.penY -= height; layout.it = loStart; if( ! itemview_parse( &dc, ut, &layout, (GWidget*) ep ) ) { boron_reset(ut); printf( "KR itemview_parse failed\n" ); } //printf( "KR fc %d,%d\n", dc.drawFirst, dc.drawCount ); fcBuf->ptr.i[ fcBuf->used ] = dc.drawFirst; fcBuf->ptr.i[ fcBuf->used + caOffset ] = dc.drawCount; ++fcBuf->used; dc.drawFirst += dc.drawCount; //dc.drawFirst += MAX_ITEM_TRIS; } assert( fcBuf->used == caOffset ); // Transfer vertex data to GPU. bsize = dc.drawFirst * TRI_ATTR_BYTES; if( ep->vboSize[ page ] < bsize ) { ep->vboSize[ page ] = bsize; glBufferData( GL_ARRAY_BUFFER, bsize, attr, GL_STATIC_DRAW ); } else { float* abuf = (float*) glMapBuffer( GL_ARRAY_BUFFER, GL_WRITE_ONLY ); if( abuf ) { memCpy( abuf, attr, bsize ); glUnmapBuffer( GL_ARRAY_BUFFER ); } } }
/* ***************************************************************************\ * signed eint8 file_fopen(FileSystem *fs,File* file,eint8* filename) * Description: This functions opens a file. * This function is about to be redesigned. No Docs. * Return value: */ esint8 file_fopen(File* file,FileSystem *fs,eint8* filename,eint8 mode) { FileLocation loc; FileRecord wtmp; eint8 fatfilename[LIST_MAXLENFILENAME]; euint32 sec; dir_getFatFileName(filename,fatfilename); switch(mode) { case MODE_READ: if(fs_findFile(fs,filename,&loc,0)==1) { dir_getFileStructure(fs,&(file->DirEntry), &loc); file_initFile(file,fs,&loc); file_setAttr(file,FILE_STATUS_OPEN,1); file_setAttr(file,FILE_STATUS_WRITE,0); return(0); } return(-1); break; case MODE_WRITE: if(fs_findFile(fs,filename,&loc,&sec)) /* File may NOT exist, but parent HAS to exist */ { return(-2); } if(sec==0){ /* Parent dir does not exist */ return(-4); } if(fs_findFreeFile(fs,filename,&loc,0)) { dir_createDefaultEntry(fs,&wtmp,fatfilename); dir_createDirectoryEntry(fs,&wtmp,&loc); memCpy(&wtmp,&(file->DirEntry),sizeof(wtmp)); file_initFile(file,fs,&loc); sec=fs_getNextFreeCluster(file->fs,fs_giveFreeClusterHint(file->fs)); dir_setFirstCluster(file->fs,&(file->Location),sec); fs_setFirstClusterInDirEntry(&(file->DirEntry),sec); fs_initClusterChain(fs,&(file->Cache),sec); fat_setNextClusterAddress(fs,sec,fat_giveEocMarker(fs)); file_setAttr(file,FILE_STATUS_OPEN,1); file_setAttr(file,FILE_STATUS_WRITE,1); return(0); } else { return(-3); } break; case MODE_APPEND: if(fs_findFile(fs,filename,&loc,0)==1) /* File exists */ { dir_getFileStructure(fs,&(file->DirEntry), &loc); file_initFile(file,fs,&loc); if(file->Cache.FirstCluster==0){ sec=fs_getNextFreeCluster(file->fs,fs_giveFreeClusterHint(file->fs)); dir_setFirstCluster(file->fs,&(file->Location),sec); fs_setFirstClusterInDirEntry(&(file->DirEntry),sec); fat_setNextClusterAddress(fs,sec,fat_giveEocMarker(fs)); file_initFile(file,fs,&loc); } file_setpos(file,file->FileSize); file_setAttr(file,FILE_STATUS_OPEN,1); file_setAttr(file,FILE_STATUS_WRITE,1); } else /* File does not excist */ { if(fs_findFreeFile(fs,filename,&loc,0)) { dir_createDefaultEntry(fs,&wtmp,fatfilename); dir_createDirectoryEntry(fs,&wtmp,&loc); memCpy(&wtmp,&(file->DirEntry),sizeof(wtmp)); file_initFile(file,fs,&loc); sec=fs_getNextFreeCluster(file->fs,fs_giveFreeClusterHint(file->fs)); dir_setFirstCluster(file->fs,&(file->Location),sec); fs_setFirstClusterInDirEntry(&(file->DirEntry),sec); fs_initClusterChain(fs,&(file->Cache),sec); fat_setNextClusterAddress(fs,sec,fat_giveEocMarker(fs)); file_setAttr(file,FILE_STATUS_OPEN,1); file_setAttr(file,FILE_STATUS_WRITE,1); } else { return(-3); } } return(0); break; default: return(-4); break; } return(-5); }
/* **************************************************************************** * euint32 file_fwrite(File* file,euint32 offset,euint32 size,euint8* buf) * Description: This function writes to a file, at offset 'offset' and size 'size'. * It also updates the FileSize in the object, and discstructure. * Return value: Bytes actually written. */ euint32 file_fwrite(File* file,euint32 offset,euint32 size,euint8* buf) { euint32 need_cluster; euint32 cclus,csec,cbyte; euint32 size_left=size,bytes_written=0; euint32 rclus,rsec; euint32 coffset=offset; euint16 btr; euint8 *tbuf; if(!file_getAttr(file,FILE_STATUS_OPEN) || !file_getAttr(file,FILE_STATUS_WRITE))return(0); if(offset>file->FileSize){ offset=file->FileSize; } need_cluster = file_requiredCluster(file,offset,size); if(need_cluster){ if(fat_allocClusterChain(file->fs,&(file->Cache),need_cluster+CLUSTER_PREALLOC_FILE)!=0){ return(0); } } while(size_left>0){ cclus = coffset/(512*file->fs->volumeId.SectorsPerCluster); csec = (coffset/(512))%file->fs->volumeId.SectorsPerCluster; cbyte = coffset%512; if(cbyte!=0 || size_left<512){ btr = 512-(coffset%512)>=size_left?size_left:512-(coffset%512); }else{ btr = 512; } if((fat_LogicToDiscCluster(file->fs,&(file->Cache),cclus))!=0){ file->FileSize+=bytes_written; dir_setFileSize(file->fs,&(file->Location),file->FileSize); return(bytes_written); } rclus=file->Cache.DiscCluster; rsec=fs_clusterToSector(file->fs,rclus); if(btr==512){ /*part_writeBuf(file->fs->part,rsec+csec,buf+bytes_written);*/ part_directSectorWrite(file->fs->part,rsec+csec,buf+bytes_written); }else{ /*part_readBuf(file->fs->part,rsec+csec,tbuf);*/ tbuf = part_getSect(file->fs->part,rsec+csec,IOM_MODE_READWRITE); memCpy(buf+bytes_written,tbuf+(coffset%512),btr); /*part_writeBuf(file->fs->part,rsec+csec,tbuf);*/ part_relSect(file->fs->part,tbuf); } coffset+=btr; bytes_written+=btr; size_left-=btr; } if(bytes_written>file->FileSize-offset){ file->FileSize+=bytes_written-(file->FileSize-offset); } return(bytes_written); }
/* Sets res to either a shader! or a context! whose first value is a shader!. Returns UR_OK/UR_THROW. */ int ur_makeShader( UThread* ut, const char* vert, const char* frag, UCell* res ) { #define MAX_SHADER_PARAM 16 // LIMIT: User parameters per shader. Shader shad; Shader* sh; UIndex bufN; UBuffer* buf; int i; char name[ 128 ]; ShaderParam param[ MAX_SHADER_PARAM ]; ShaderParam* pi; GLsizei length; GLint size; GLenum type; GLint count = 0; if( ! createShader( ut, &shad, vert, frag ) ) return UR_THROW; glGetProgramiv( shad.program, GL_ACTIVE_UNIFORMS, &count ); // Collect non-gl parameters. pi = param; for( i = 0; i < count; ++i ) { glGetActiveUniform( shad.program, i, 128, &length, &size, &type, name ); if( name[0] == 'g' && name[1] == 'l' && name[2] == '_' ) continue; pi->type = type; pi->location = glGetUniformLocation( shad.program, name ); pi->name = ur_internAtom( ut, name, name + length ); if( pi->name == UR_INVALID_ATOM ) return UR_THROW; ++pi; } count = pi - param; if( count ) { ShaderParam* pend; UBuffer* ctx; UCell* cval; // We have parameters - make context to hold shader & params. ctx = ur_makeContextCell( ut, count + 1, res ); cval = ur_ctxAddWord( ctx, UR_ATOM_SHADER ); pi = param; pend = param + count; while( pi != pend ) { cval = ur_ctxAddWord( ctx, pi->name ); #if 0 printf( "KR Shader Param %d is type %d\n", (int) (pi - param), pi->type ); #endif switch( pi->type ) { case GL_FLOAT: ur_setId( cval, UT_DECIMAL ); ur_decimal( cval ) = 0.0; break; case GL_FLOAT_VEC2: case GL_FLOAT_VEC3: //case GL_FLOAT_VEC4: ur_setId( cval, UT_VEC3 ); cval->vec3.xyz[0] = cval->vec3.xyz[1] = cval->vec3.xyz[2] = 0.0f; break; case GL_INT: ur_setId( cval, UT_INT ); ur_int( cval ) = 0; break; case GL_INT_VEC2: case GL_INT_VEC3: //case GL_INT_VEC4: ur_setId( cval, UT_COORD ); break; case GL_BOOL: ur_setId( cval, UT_LOGIC ); ur_int( cval ) = 0; break; case GL_SAMPLER_2D: case GL_SAMPLER_CUBE: #ifndef GL_ES_VERSION_2_0 case GL_SAMPLER_1D: case GL_SAMPLER_3D: case GL_SAMPLER_1D_SHADOW: case GL_SAMPLER_2D_SHADOW: #endif ur_setId( cval, UT_NONE ); ur_texId(cval) = 0; // Expecting texture!. break; #ifdef GL_ES_VERSION_2_0 case GL_FLOAT_MAT4: ur_setId( cval, UT_NONE ); break; #endif default: ur_setId( cval, UT_NONE ); break; /* GL_BOOL_VEC2: GL_BOOL_VEC3: GL_BOOL_VEC4: GL_FLOAT_MAT2: GL_FLOAT_MAT3: GL_FLOAT_MAT4: GL_SAMPLER_2D_RECT: GL_SAMPLER_2D_RECT_SHADOW: */ } ++pi; } ur_ctxSort( ctx ); } ur_genBuffers( ut, 1, &bufN ); buf = ur_buffer( bufN ); buf->type = UT_SHADER; buf->ptr.v = memAlloc( sizeof(Shader) + sizeof(ShaderParam) * (count - 1) ); sh = (Shader*) buf->ptr.v; sh->program = shad.program; sh->paramCount = count; if( count ) { memCpy( sh->param, param, sizeof(ShaderParam) * count ); // First context value will be set to shader!. res = ur_buffer( res->series.buf )->ptr.cell; } ur_setId( res, UT_SHADER ); ur_setSeries( res, bufN, 0 ); return UR_OK; }