/********************************************************************************************************* ** 函数名称: __procFssupRootfsRead ** 功能描述: procfs 读一个根文件系统信息 proc 文件 ** 输 入 : p_pfsn 节点控制块 ** pcBuffer 缓冲区 ** stMaxBytes 缓冲区大小 ** oft 文件指针 ** 输 出 : 实际读取的数目 ** 全局变量: ** 调用模块: *********************************************************************************************************/ static ssize_t __procFssupStatRead (PLW_PROCFS_NODE p_pfsn, PCHAR pcBuffer, size_t stMaxBytes, off_t oft) { REGISTER PCHAR pcFileBuffer; size_t stRealSize; /* 实际的文件内容大小 */ size_t stCopeBytes; /* * 程序运行到这里, 文件缓冲一定已经分配了预置的内存大小(创建节点时预置大小为 64 字节). */ pcFileBuffer = (PCHAR)API_ProcFsNodeBuffer(p_pfsn); if (pcFileBuffer == LW_NULL) { _ErrorHandle(ENOMEM); return (0); } stRealSize = API_ProcFsNodeGetRealFileSize(p_pfsn); if (stRealSize == 0) { /* 需要生成文件 */ struct statfs statfsBuf; PCHAR pcFs; if (p_pfsn->PFSN_p_pfsnoFuncs == &_G_pfsnoFssupRootfsFuncs) { pcFs = "/"; } else if (p_pfsn->PFSN_p_pfsnoFuncs == &_G_pfsnoFssupProcfsFuncs) { pcFs = "/proc"; } else { pcFs = "/"; /* 不可能运行到这里 */ } if (statfs(pcFs, &statfsBuf) < ERROR_NONE) { stRealSize = bnprintf(pcFileBuffer, __PROCFS_BUFFER_SIZE_ROOTFS, 0, "get root file system status error."); } else { stRealSize = bnprintf(pcFileBuffer, __PROCFS_BUFFER_SIZE_ROOTFS, 0, "memory used : %ld bytes\n" "total files : %ld\n", (ULONG)(statfsBuf.f_bsize * statfsBuf.f_blocks), statfsBuf.f_files); } API_ProcFsNodeSetRealFileSize(p_pfsn, stRealSize); } if (oft >= stRealSize) { _ErrorHandle(ENOSPC); return (0); } stCopeBytes = __MIN(stMaxBytes, (size_t)(stRealSize - oft)); /* 计算实际拷贝的字节数 */ lib_memcpy(pcBuffer, (CPVOID)(pcFileBuffer + oft), (UINT)stCopeBytes); return ((ssize_t)stCopeBytes); }
/********************************************************************************************************* ** 函数名称: __buildinRtPrint ** 功能描述: 打印 lwip 内建路由信息 ** 输 入 : rt aodv 路由条目 ** 输 出 : NONE ** 全局变量: ** 调用模块: *********************************************************************************************************/ static VOID __buildinRtPrint (PCHAR pcBuffer, size_t stSize, size_t *pstOffset) { struct netif *netif; ip_addr_t ipaddr; CHAR cIpDest[INET_ADDRSTRLEN]; CHAR cGateway[INET_ADDRSTRLEN] = "*"; CHAR cMask[INET_ADDRSTRLEN]; CHAR cFlag[6]; CHAR cIfName[IF_NAMESIZE] = "\0"; for (netif = netif_list; netif != NULL; netif = netif->next) { if (netif->flags & NETIF_FLAG_POINTTOPOINT) { /* PPP / SLIP 连接 */ ipaddr.addr = netif->gw.addr; ipaddr_ntoa_r(&ipaddr, cIpDest, INET_ADDRSTRLEN); ipaddr_ntoa_r(&netif->netmask, cMask, INET_ADDRSTRLEN); if_indextoname(netif->num, cIfName); lib_strcpy(cFlag, "UH"); } else { /* 普通链接 */ ipaddr.addr = netif->ip_addr.addr & netif->netmask.addr; ipaddr_ntoa_r(&ipaddr, cIpDest, INET_ADDRSTRLEN); ipaddr_ntoa_r(&netif->netmask, cMask, INET_ADDRSTRLEN); if_indextoname(netif->num, cIfName); lib_strcpy(cFlag, "U"); } *pstOffset = bnprintf(pcBuffer, stSize, *pstOffset, "%-18s %-18s %-18s %-8s %-3s\n", cIpDest, cGateway, cMask, cFlag, cIfName); ipaddr_ntoa_r(&netif->ip_addr, cIpDest, INET_ADDRSTRLEN); lib_strcpy(cFlag, "UH"); *pstOffset = bnprintf(pcBuffer, stSize, *pstOffset, "%-18s %-18s %-18s %-8s %-3s\n", cIpDest, cGateway, cMask, cFlag, cIfName); } if (netif_default) { ipaddr_ntoa_r(&netif_default->gw, cGateway, INET_ADDRSTRLEN); ipaddr_ntoa_r(&netif_default->netmask, cMask, INET_ADDRSTRLEN); if_indextoname(netif_default->num, cIfName); lib_strcpy(cFlag, "UG"); *pstOffset = bnprintf(pcBuffer, stSize, *pstOffset, "%-18s %-18s %-18s %-8s %-3s\n", "default", cGateway, cMask, cFlag, cIfName); } }
/********************************************************************************************************* ** 函数名称: __procFsPowerDevPrint ** 功能描述: 打印电源管理设备文件 ** 输 入 : pmdev 设备节点 ** pcBuffer 缓冲 ** stTotalSize 缓冲区大小 ** pstOft 当前偏移量 ** 输 出 : NONE ** 全局变量: ** 调用模块: *********************************************************************************************************/ static VOID __procFsPowerDevPrint (PLW_PM_DEV pmdev, PCHAR pcBuffer, size_t stTotalSize, size_t *pstOft) { PLW_PM_ADAPTER pmadapter = pmdev->PMD_pmadapter; BOOL bIsOn = LW_FALSE; PCHAR pcIsOn; PCHAR pcName; if (pmadapter && pmadapter->PMA_pmafunc && pmadapter->PMA_pmafunc->PMAF_pfuncIsOn) { pmadapter->PMA_pmafunc->PMAF_pfuncIsOn(pmadapter, pmdev, &bIsOn); if (bIsOn) { pcIsOn = "on"; } else { pcIsOn = "off"; } } else { pcIsOn = "<unknown>"; } if (pmdev->PMD_pcName) { pcName = pmdev->PMD_pcName; } else { pcName = "<unknown>"; } *pstOft = bnprintf(pcBuffer, stTotalSize, *pstOft, "%-14s %-14s %-9u %s\n", pcName, pmadapter->PMA_cName, pmdev->PMD_uiChannel, pcIsOn); }
/********************************************************************************************************* ** 函数名称: __aodvEntryPrint ** 功能描述: 打印 aodv 路由信息 ** 输 入 : rt aodv 路由条目 ** pcBuffer 缓冲区 ** stSize 缓冲区大小 ** pstOffset 偏移量 ** 输 出 : NONE ** 全局变量: ** 调用模块: *********************************************************************************************************/ static VOID __aodvEntryPrint (struct aodv_rtnode *rt, PCHAR pcBuffer, size_t stSize, size_t *pstOffset) { CHAR cIpDest[INET_ADDRSTRLEN]; CHAR cNextHop[INET_ADDRSTRLEN]; CHAR cMask[INET_ADDRSTRLEN]; CHAR cFlag[16] = "\0"; CHAR cIfName[IF_NAMESIZE] = "\0"; inet_ntoa_r(rt->dest_addr, cIpDest, INET_ADDRSTRLEN); inet_ntoa_r(rt->next_hop, cNextHop, INET_ADDRSTRLEN); if (rt->state & AODV_VALID) { lib_strcat(cFlag, "U"); } if (rt->hcnt > 0) { lib_strcat(cFlag, "G"); } if ((rt->flags & AODV_RT_GATEWAY) == 0) { lib_strcat(cFlag, "H"); } if ((rt->flags & AODV_RT_UNIDIR) == 0) { /* 单向连接 */ lib_strcat(cFlag, "-ud"); } /* * aodv 路由节点网络接口一定有效 */ ipaddr_ntoa_r(&rt->netif->netmask, cMask, INET_ADDRSTRLEN); if_indextoname(rt->netif->num, cIfName); *pstOffset = bnprintf(pcBuffer, stSize, *pstOffset, "%-18s %-18s %-18s %-8s %8d %-3s\n", cIpDest, cNextHop, cMask, cFlag, rt->hcnt, cIfName); }
static VOID __rtEntryPrint (PLW_RT_ENTRY prte, PCHAR pcBuffer, size_t stSize, size_t *pstOffset) { CHAR cIpDest[INET_ADDRSTRLEN]; CHAR cGateway[INET_ADDRSTRLEN] = "*"; CHAR cMask[INET_ADDRSTRLEN] = "*"; CHAR cFlag[6] = "\0"; ipaddr_ntoa_r(&prte->RTE_ipaddrDest, cIpDest, INET_ADDRSTRLEN); if (prte->RTE_pnetif) { ipaddr_ntoa_r(&prte->RTE_pnetif->gw, cGateway, INET_ADDRSTRLEN); ipaddr_ntoa_r(&prte->RTE_pnetif->netmask, cMask, INET_ADDRSTRLEN); } if (prte->RTE_uiFlag & LW_RT_FLAG_U) { lib_strcat(cFlag, "U"); } if (prte->RTE_uiFlag & LW_RT_FLAG_G) { lib_strcat(cFlag, "G"); } else { lib_strcpy(cGateway, "*"); /* 直接路由 (不需要打印网关) */ } if (prte->RTE_uiFlag & LW_RT_FLAG_H) { lib_strcat(cFlag, "H"); } if (prte->RTE_uiFlag & LW_RT_FLAG_D) { lib_strcat(cFlag, "D"); } if (prte->RTE_uiFlag & LW_RT_FLAG_M) { lib_strcat(cFlag, "M"); } *pstOffset = bnprintf(pcBuffer, stSize, *pstOffset, "%-18s %-18s %-18s %-8s %-3s\n", cIpDest, cGateway, cMask, cFlag, prte->RTE_cNetifName); }
int bneratoprintf(EArr* tab) { EPr* i=(*tab).begin; while(i!=NULL) { if((*i).isPrime) { bnprintf((*i).num); printf("\n"); } i=(*i).forw; } return 0; }
/********************************************************************************************************* ** 函数名称: __procFsPowerAdapterRead ** 功能描述: procfs 读一个读取网络 adapter 文件 ** 输 入 : p_pfsn 节点控制块 ** pcBuffer 缓冲区 ** stMaxBytes 缓冲区大小 ** oft 文件指针 ** 输 出 : 实际读取的数目 ** 全局变量: ** 调用模块: *********************************************************************************************************/ static ssize_t __procFsPowerAdapterRead (PLW_PROCFS_NODE p_pfsn, PCHAR pcBuffer, size_t stMaxBytes, off_t oft) { const CHAR cAdapterInfoHdr[] = "ADAPTER MAX-CHANNLE\n"; PCHAR pcFileBuffer; size_t stRealSize; /* 实际的文件内容大小 */ size_t stCopeBytes; /* * 由于预置内存大小为 0 , 所以打开后第一次读取需要手动开辟内存. */ pcFileBuffer = (PCHAR)API_ProcFsNodeBuffer(p_pfsn); if (pcFileBuffer == LW_NULL) { /* 还没有分配内存 */ size_t stNeedBufferSize = 0; PLW_LIST_LINE plineTemp; PLW_PM_ADAPTER pmadapter; __POWERM_LOCK(); for (plineTemp = _G_plinePMAdapter; plineTemp != LW_NULL; plineTemp = _list_line_get_next(plineTemp)) { stNeedBufferSize += 32; } __POWERM_UNLOCK(); stNeedBufferSize += sizeof(cAdapterInfoHdr); if (API_ProcFsAllocNodeBuffer(p_pfsn, stNeedBufferSize)) { _ErrorHandle(ENOMEM); return (0); } pcFileBuffer = (PCHAR)API_ProcFsNodeBuffer(p_pfsn); /* 重新获得文件缓冲区地址 */ stRealSize = bnprintf(pcFileBuffer, stNeedBufferSize, 0, cAdapterInfoHdr); /* 打印头信息 */ __POWERM_LOCK(); for (plineTemp = _G_plinePMAdapter; plineTemp != LW_NULL; plineTemp = _list_line_get_next(plineTemp)) { pmadapter = _LIST_ENTRY(plineTemp, LW_PM_ADAPTER, PMA_lineManage); stRealSize = bnprintf(pcFileBuffer, stNeedBufferSize, stRealSize, "%-14s %u\n", pmadapter->PMA_cName, pmadapter->PMA_uiMaxChan); } __POWERM_UNLOCK(); API_ProcFsNodeSetRealFileSize(p_pfsn, stRealSize); } else { stRealSize = API_ProcFsNodeGetRealFileSize(p_pfsn); } if (oft >= stRealSize) { _ErrorHandle(ENOSPC); return (0); } stCopeBytes = __MIN(stMaxBytes, (size_t)(stRealSize - oft)); /* 计算实际拷贝的字节数 */ lib_memcpy(pcBuffer, (CPVOID)(pcFileBuffer + oft), (UINT)stCopeBytes); return ((ssize_t)stCopeBytes); }
/********************************************************************************************************* ** 函数名称: __procFsPowerInfoRead ** 功能描述: procfs 读一个 pminfo 文件 ** 输 入 : p_pfsn 节点控制块 ** pcBuffer 缓冲区 ** stMaxBytes 缓冲区大小 ** oft 文件指针 ** 输 出 : 实际读取的数目 ** 全局变量: ** 调用模块: *********************************************************************************************************/ static ssize_t __procFsPowerInfoRead (PLW_PROCFS_NODE p_pfsn, PCHAR pcBuffer, size_t stMaxBytes, off_t oft) { REGISTER PCHAR pcFileBuffer; size_t stRealSize; /* 实际的文件内容大小 */ size_t stCopeBytes; /* * 程序运行到这里, 文件缓冲一定已经分配了预置的内存大小. */ pcFileBuffer = (PCHAR)API_ProcFsNodeBuffer(p_pfsn); if (pcFileBuffer == LW_NULL) { _ErrorHandle(ENOMEM); return (0); } stRealSize = API_ProcFsNodeGetRealFileSize(p_pfsn); if (stRealSize == 0) { /* 需要生成文件 */ PCHAR pcSysMode; PCHAR pcPowerLevel; UINT uiPowerLevel; ULONG ulActive; API_PowerMCpuGet(&ulActive, &uiPowerLevel); switch (uiPowerLevel) { case LW_CPU_POWERLEVEL_TOP: pcPowerLevel = "Top"; break; case LW_CPU_POWERLEVEL_FAST: pcPowerLevel = "Fast"; break; case LW_CPU_POWERLEVEL_NORMAL: pcPowerLevel = "Normal"; break; case LW_CPU_POWERLEVEL_SLOW: pcPowerLevel = "Slow"; break; default: pcPowerLevel = "<unknown>"; break; } if (_G_bPowerSavingMode) { pcSysMode = "Power-Saving"; } else { pcSysMode = "Running"; } stRealSize = bnprintf(pcFileBuffer, __PROCFS_BUFFER_SIZE_INFO, 0, "NCPUS : %u\n" "ACTIVE : %u\n" "POWERLevel : %s\n" "SYSStatus : %s\n", (UINT)LW_NCPUS, (UINT)ulActive, pcPowerLevel, pcSysMode); API_ProcFsNodeSetRealFileSize(p_pfsn, stRealSize); } if (oft >= stRealSize) { _ErrorHandle(ENOSPC); return (0); } stCopeBytes = __MIN(stMaxBytes, (size_t)(stRealSize - oft)); /* 计算实际读取的数量 */ lib_memcpy(pcBuffer, (CPVOID)(pcFileBuffer + oft), (UINT)stCopeBytes); return ((ssize_t)stCopeBytes); }
/********************************************************************************************************* ** 函数名称: syslog_r ** 功能描述: submits a message to the Syslog facility. It does this by writing to the file (支持不完整) LOG_DEFAULT_FILE ** 输 入 : priority priority ** data syslog_data ** message message ... ** 输 出 : old mask ** 全局变量: ** 调用模块: API 函数 *********************************************************************************************************/ LW_API void syslog_r (int priority, struct syslog_data *data, const char *message, ...) { #define __PX_SYSLOG_TIMEFMT "%s %2d %02d:%02d:%02d" CHAR cBuffer[LOG_DEFAULT_SIZE]; size_t stLen; time_t time; struct tm tmBuf; va_list valist; if (!data) { errno = EINVAL; return; } if (((unsigned)LOG_FAC(priority) >= LOG_NFACILITIES) || (LOG_MASK(LOG_PRI(priority)) == 0) || ((priority & ~(LOG_PRIMASK | LOG_FACMASK)) != 0)) { return; /* 不发送 */ } if ((data->log_file < 0) && (data->log_stat & LOG_ODELAY)) { /* 是否需要执行一次打开操作 */ openlog(data->log_tag, data->log_file, 0); data->log_file = _G_iSyslogUnix; } if ((priority & LOG_FACMASK) == 0) { priority |= data->log_fac; } time = lib_time(LW_NULL); lib_localtime_r(&time, &tmBuf); /* RFC3164 is the local time */ stLen = bnprintf(cBuffer, sizeof(cBuffer), 0, "<%d>", priority); /* 打印 priority */ stLen = bnprintf(cBuffer, sizeof(cBuffer), stLen, __PX_SYSLOG_TIMEFMT, _G_cMonth[tmBuf.tm_mon], tmBuf.tm_mday, tmBuf.tm_hour, tmBuf.tm_min, tmBuf.tm_sec); /* 打印 时间 */ if (data->log_tag) { stLen = bnprintf(cBuffer, sizeof(cBuffer), stLen, " %s", data->log_tag); } if (data->log_stat & LOG_PID) { if (sizeof(cBuffer) > stLen) { stLen = bnprintf(cBuffer, sizeof(cBuffer), stLen, "[%lx]:", API_ThreadIdSelf()); } } if (message) { if (sizeof(cBuffer) > stLen) { #if __STDC__ va_start(valist, message); #else va_start(valist); #endif stLen = vbnprintf(cBuffer, sizeof(cBuffer), stLen, message, valist); va_end(valist); } } if (data->log_file >= 0) { sendto(data->log_file, cBuffer, stLen, 0, (struct sockaddr *)&_G_sockaddrunLog, _G_sockelenLog); } if (data->log_stat & LOG_CONS) { write(STD_OUT, cBuffer, stLen); } if (data->log_stat & LOG_PERROR) { write(STD_ERR, cBuffer, stLen); } }
/********************************************************************************************************* ** 函数名称: __procFsYaffsPrint ** 功能描述: 打印 yaffs 信息 ** 输 入 : pyaffsDev yaffs 设备 ** pcVolName 设备名 ** pcBuffer 缓冲区 ** stMaxBytes 缓冲区大小 ** stOffset 偏移量 ** 输 出 : 新的偏移量 ** 全局变量: ** 调用模块: *********************************************************************************************************/ static size_t __procFsYaffsPrint (struct yaffs_dev *pyaffsDev, PCHAR pcVolName, PCHAR pcBuffer, size_t stMaxBytes, size_t stOffset) { return (bnprintf(pcBuffer, stMaxBytes, stOffset, "Device : \"%s\"\n" "startBlock......... %d\n" "endBlock........... %d\n" "totalBytesPerChunk. %d\n" "chunkGroupBits..... %d\n" "chunkGroupSize..... %d\n" "nErasedBlocks...... %d\n" "nReservedBlocks.... %d\n" "nCheckptResBlocks.. nil\n" "blocksInCheckpoint. %d\n" "nObjects........... %d\n" "nTnodes............ %d\n" "nFreeChunks........ %d\n" "nPageWrites........ %d\n" "nPageReads......... %d\n" "nBlockErasures..... %d\n" "nErasureFailures... %d\n" "nGCCopies.......... %d\n" "allGCs............. %d\n" "passiveGCs......... %d\n" "nRetriedWrites..... %d\n" "nShortOpCaches..... %d\n" "nRetiredBlocks..... %d\n" "eccFixed........... %d\n" "eccUnfixed......... %d\n" "tagsEccFixed....... %d\n" "tagsEccUnfixed..... %d\n" "cacheHits.......... %d\n" "nDeletedFiles...... %d\n" "nUnlinkedFiles..... %d\n" "nBackgroudDeletions %d\n" "useNANDECC......... %d\n" "isYaffs2........... %d\n\n", pcVolName, pyaffsDev->param.start_block, pyaffsDev->param.end_block, pyaffsDev->param.total_bytes_per_chunk, pyaffsDev->chunk_grp_bits, pyaffsDev->chunk_grp_size, pyaffsDev->n_erased_blocks, pyaffsDev->param.n_reserved_blocks, pyaffsDev->blocks_in_checkpt, pyaffsDev->n_obj, pyaffsDev->n_tnodes, pyaffsDev->n_free_chunks, pyaffsDev->n_page_writes, pyaffsDev->n_page_reads, pyaffsDev->n_erasures, pyaffsDev->n_erase_failures, pyaffsDev->n_gc_copies, pyaffsDev->all_gcs, pyaffsDev->passive_gc_count, pyaffsDev->n_retried_writes, pyaffsDev->param.n_caches, pyaffsDev->n_retired_blocks, pyaffsDev->n_ecc_fixed, pyaffsDev->n_ecc_unfixed, pyaffsDev->n_tags_ecc_fixed, pyaffsDev->n_tags_ecc_unfixed, pyaffsDev->cache_hits, pyaffsDev->n_deleted_files, pyaffsDev->n_unlinked_files, pyaffsDev->n_bg_deletions, pyaffsDev->param.use_nand_ecc, pyaffsDev->param.is_yaffs2)); }
EArr* bnerato2(BN* maxi) { EArr* tab=bneratoInit(maxi); EPr* n=(*tab).begin; EPr* j=malloc(sizeof(EPr)); EPr* r=malloc(sizeof(EPr)); unsigned short int bool=0; n=(*n).forw; free((*n).backw); n=(*n).forw; free((*n).backw); (*n).backw=NULL; if((*tab).begin=n) { printf("Bah begin de tab est bien n LOL"); bnprintf((*(*tab).begin).num); } while((*n).forw!=NULL) { bool=0; if(((*n).isPrime)&&(n!=NULL)) { printf("n vaut là ici maintenant"); bnprintf((*n).num); j=n; r=j; while(j!=NULL) { r=j; printf("r vaut maintenant"); bnprintf((*r).num); printf("\n"); if(bool==0) { printf("bool vaut 0000\n"); if(j==NULL) printf("J est NULL\n"); else bnprintf((*j).num); if(n==NULL) printf("merde, n est null"); printf("Je vais rentrer dans le while...\n"); printf("j, r, n valent \n"); bnprintf((*j).num); printf("\n"); bnprintf((*r).num); printf("\n"); bnprintf((*n).num); printf("\n"); if((isInferior((*j).num,sum((*r).num,minus((*n).num,initialize("1")))))) printf("Je devrais bien y rentrer dans ce foutu while !"); while((j!=NULL)&&(r!=NULL)&&(isInferior((*j).num,sum((*r).num,minus((*n).num,initialize("1")))))) { printf("Dans le while ?"); if(j!=NULL) j=(*j).forw; if(j==NULL) printf("Je suis rentré, j'ai incrémenté j, et j est NULL...\n"); if(j!=NULL) { printf("\n J'avance d'une case et j'ai :"); bnprintf((*j).num); printf(" J'ai avancé d'une case.\n Voici la condition d'arrêt :"); bnprintf(sum((*r).num,minus((*n).num,initialize("1")))); printf("\n"); } } } else { while((j!=NULL)&&(r!=NULL)&&(isInferior((*j).num,sum((*r).num,minus((*n).num,initialize("2")))))) { printf("Je rentre dans le while...\n"); if(j!=NULL) { printf("Je vais incrémenter j..."); j=(*j).forw; printf("\n j est maintenant incrémenté.\n j="); if(j!=NULL) bnprintf((*j).num); else printf("NULL!"); printf("\n"); } if(j!=NULL) { printf("\n J'avance d'une case et j'ai :"); bnprintf((*j).num); printf(" J'ai avancé d'une case.\n Voici la condition d'arrêt :"); bnprintf(sum((*r).num,minus((*n).num,initialize("2")))); printf("\n"); } } } if(j!=NULL&&(*j).isPrime==1) { (*j).isPrime=0; (*(*j).backw).forw=(*j).forw; if((*j).forw!=NULL) { (*(*j).forw).backw=(*j).backw; j=(*j).forw; free((*j).backw); printf("Je libère mon précédent !"); bnprintf((*j).num); printf("c'est ce que je vaux mainteannt\n"); } else { j=(*j).backw; free((*j).forw); (*j).forw=NULL; } bool=1; printf("J'ai passé bool à 1.\n"); } }