PageRenderTime 59ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/src/libbeye/file_ini.c

#
C | 1977 lines | 1810 code | 114 blank | 53 comment | 475 complexity | 4818dc9e6855b5de45701c31337abd41 MD5 | raw file
Possible License(s): AGPL-1.0

Large files files are truncated, but you can click here to view the full file

  1. /**
  2. * @namespace libbeye
  3. * @file libbeye/file_ini.c
  4. * @brief This file contains implementation of .ini files services.
  5. * @version -
  6. * @remark this source file is part of Binary EYE project (BEYE).
  7. * The Binary EYE (BEYE) is copyright (C) 1995 Nickols_K.
  8. * All rights reserved. This software is redistributable under the
  9. * licence given in the file "Licence.en" ("Licence.ru" in russian
  10. * translation) distributed in the BEYE archive.
  11. * @note Requires POSIX compatible development system
  12. *
  13. * @author Nickols_K
  14. * @since 1995
  15. * @note Development, fixes and improvements
  16. * @bug Fault if more than one ini file is opened at one time
  17. * @todo Reentrance ini library
  18. **/
  19. #include <string.h>
  20. #include <stdlib.h>
  21. #include <stdio.h>
  22. #include <ctype.h>
  23. #include <limits.h>
  24. #include "libbeye/bbio.h"
  25. #include "libbeye/file_ini.h"
  26. #include "libbeye/pmalloc.h"
  27. #define rewind_ini(h) (bioSeek(h,0L,BIO_SEEK_SET))
  28. #if 0
  29. static void dump_BFILE(BFILE *h) {
  30. fprintf(stderr,
  31. "FilePos=%llu\n"
  32. "Flength=%llu\n"
  33. "FileName=%s\n"
  34. "openmode=%u\n"
  35. "optimize=%i\n"
  36. "is_mmf=%i\n"
  37. "primary_mmf=%u\n"
  38. "is_eof=%u\n"
  39. ,h->FilePos
  40. ,h->FLength
  41. ,h->FileName
  42. ,h->openmode
  43. ,h->optimize
  44. ,h->is_mmf
  45. ,h->primary_mmf
  46. ,h->is_eof);
  47. }
  48. #endif
  49. static unsigned char CaseSens = 2; /**< 2 - case 1 - upper 0 - lower */
  50. static FiUserFunc proc;
  51. static pVar FirstVar = NULL;
  52. FiHandler ActiveFile = 0;
  53. bool ifSmarting = true;
  54. const char *fi_Debug_Str = NULL;
  55. /**************************************************************\
  56. * Low level support *
  57. \**************************************************************/
  58. #define __C_EOF 0x1A
  59. #define __FI_MAXFILES 200
  60. unsigned int *FinCurrString;
  61. char ** FiFileNames;
  62. unsigned int FiFilePtr = 0;
  63. char * FiUserMessage = NULL;
  64. const char iniLegalSet[] = " _0123456789"
  65. "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  66. "abcdefghijklmnopqrstuvwxyz";
  67. #define IS_VALID_NAME(name) (strspn(name,iniLegalSet) == strlen(name))
  68. #define IS_SECT(str,ch) (str[0] == ch)
  69. #define FiisSection( str ) (IS_SECT(str,'['))
  70. #define FiisSubSection( str ) (IS_SECT(str,'<'))
  71. #define FiisCommand( str ) (IS_SECT(str,'#'))
  72. #define FiisItem(str) (!(FiisSection(str) || FiisSubSection(str) || FiisCommand(str)))
  73. static char * __NEAR__ __FASTCALL__ GETS(char *str,unsigned num,BGLOBAL h)
  74. {
  75. char *ret;
  76. unsigned i;
  77. char ch,ch1;
  78. ret = str;
  79. for(i = 0;i < num;i++)
  80. {
  81. ch = bioReadByte(h);
  82. if(ch == '\n' || ch == '\r')
  83. {
  84. *str = ch; str++;
  85. ch1 = bioReadByte(h);
  86. if((ch1 == '\n' || ch1 == '\r') && ch != ch1)
  87. {
  88. *str = ch; str++;
  89. }
  90. else
  91. {
  92. if(bioEOF(h))
  93. {
  94. if((signed char)ch1 != -1 && ch1 != __C_EOF)
  95. {
  96. *str = ch1; str++;
  97. }
  98. break;
  99. }
  100. bioSeek(h,-1,SEEK_CUR);
  101. }
  102. break;
  103. }
  104. if(bioEOF(h))
  105. {
  106. if((signed char)ch != -1 && ch != __C_EOF)
  107. {
  108. *str = ch; str++;
  109. }
  110. break;
  111. }
  112. *str = ch; str++;
  113. }
  114. *str = 0;
  115. return ret;
  116. }
  117. void __FASTCALL__ FiAError(int nError,int row,const char *addinfo)
  118. {
  119. int eret = 0;
  120. if(FiError) eret = (*FiError)(nError,row,addinfo);
  121. if(eret == __FI_EXITPROC) exit(255);
  122. }
  123. void __FASTCALL__ FiAErrorCL(int nError) { FiAError(nError,FinCurrString[FiFilePtr-1],NULL); }
  124. static const char * list[] = {
  125. "No errors",
  126. "Can't open file: '%s' (bad '#include' statement?).",
  127. "Too many open files.",
  128. "Memory exhausted.",
  129. "Open 'if' (missing '#endif').",
  130. "Missing 'if' for 'endif' statement.",
  131. "Missing 'if' for 'else' statement.",
  132. "Unknown '#' directive.",
  133. "Syntax error in 'if' statement.",
  134. "Expected open section or subsection, or invalid string.",
  135. "Bad character on line (possible lost comment).",
  136. "Bad variable in 'set' or 'delete' statement.",
  137. "Bad value of variable in 'set' statement.",
  138. "Unrecognized name of variable in 'delete' statement.",
  139. "Undefined variable detected (case sensitivity?).",
  140. "Missing 'if' for 'elif' statement.",
  141. "Open variable on line (use even number of '%' characters).",
  142. "Lost or mismatch character '=' in assigned expression.",
  143. "",
  144. "User error."
  145. };
  146. const char * __FASTCALL__ FiDecodeError(int nError)
  147. {
  148. const char *ret;
  149. nError = abs(nError);
  150. if(nError >= 0 && nError <= abs(__FI_FIUSER)) ret = list[nError];
  151. else ret = "Unknown Error";
  152. return ret;
  153. }
  154. static int __FASTCALL__ StdError(int ne,int row,const char *addinfo)
  155. {
  156. FILE * herr;
  157. const char * what;
  158. char sout[4096];
  159. if((herr = fopen("fi_syserr.$$$","wt")) == NULL) herr = stderr;
  160. fprintf(herr,"About : [.Ini] file run-time support library. Written by Nickols_K\n"
  161. "Detected ");
  162. if(ne != __FI_TOOMANY && FiFilePtr)
  163. {
  164. fprintf(herr,"%s error in : %s",row ? "fatal" : "",FiFileNames[FiFilePtr - 1]);
  165. }
  166. fprintf(herr,"\n");
  167. if(row) fprintf(herr,"At line : %i\n",row);
  168. what = FiDecodeError(ne);
  169. if(addinfo) sprintf(sout,what,addinfo);
  170. else strncpy(sout,what,sizeof(sout));
  171. fprintf(herr,"Message : %s\n",sout);
  172. if(FiUserMessage) fprintf(herr,"User message : %s\n",FiUserMessage);
  173. if(fi_Debug_Str) if(*fi_Debug_Str) fprintf(herr,"Debug info: '%s'\n",fi_Debug_Str);
  174. fclose(herr);
  175. printm("\nError in .ini file.\nFile fi_syser.$$$ created.\n");
  176. return __FI_EXITPROC;
  177. }
  178. int (__FASTCALL__ *FiError)(int nError,int row,const char *) = StdError;
  179. FiHandler __FASTCALL__ FiOpen( const char * filename)
  180. {
  181. char * activeFile;
  182. FiHandler ret;
  183. /* Try to load .ini file entire into memory */
  184. ret = bioOpen(filename,FO_READONLY | SO_DENYWRITE,UINT_MAX,BIO_OPT_USEMMF);
  185. /* Note! All OSes except DOS-DOS386 allows opening of empty filenames as /dev/null */
  186. if(ret == &bNull && filename[0]) FiAError(__FI_BADFILENAME,0,filename);
  187. activeFile = (char *)PMalloc((strlen(filename) + 1));
  188. if(activeFile == NULL) FiAError(__FI_NOTMEM,0,NULL);
  189. strcpy(activeFile,filename);
  190. if(!FiFilePtr)
  191. {
  192. FiFileNames = PMalloc(sizeof(char *));
  193. FinCurrString = PMalloc(sizeof(unsigned int));
  194. }
  195. else
  196. {
  197. FiFileNames = PRealloc(FiFileNames,sizeof(char *)*(FiFilePtr+1));
  198. FinCurrString = PRealloc(FinCurrString,sizeof(unsigned int)*(FiFilePtr+1));
  199. }
  200. if(!FiFileNames || !FinCurrString) FiAError(__FI_NOTMEM,0,NULL);
  201. FiFileNames[FiFilePtr] = activeFile;
  202. FinCurrString[FiFilePtr++] = 0;
  203. if(FiFilePtr > __FI_MAXFILES-1) FiAError(__FI_TOOMANY,0,NULL);
  204. return ret;
  205. }
  206. void __FASTCALL__ FiClose(FiHandler h)
  207. {
  208. PFREE(FiFileNames[FiFilePtr-1]);
  209. if(FiFilePtr)
  210. {
  211. FiFileNames = PRealloc(FiFileNames,sizeof(char *)*(FiFilePtr));
  212. FinCurrString = PRealloc(FinCurrString,sizeof(unsigned int)*(FiFilePtr));
  213. if(!FiFileNames || !FinCurrString) FiAError(__FI_NOTMEM,0,NULL);
  214. FiFilePtr--;
  215. }
  216. else
  217. {
  218. PFREE(FiFileNames);
  219. PFREE(FinCurrString);
  220. }
  221. bioClose(h);
  222. }
  223. static unsigned int __NEAR__ __FASTCALL__ __GetLengthBrStr(const char * src,char obr,char cbr)
  224. {
  225. char *ends;
  226. unsigned ret = 0;
  227. if(*src == obr)
  228. {
  229. src++;
  230. ends = strchr(src,cbr);
  231. if(!ends) goto err;
  232. if(*(ends+1)) FiAErrorCL(__FI_BADCHAR);
  233. ret = ends-src;
  234. }
  235. else
  236. {
  237. err:
  238. FiAErrorCL(__FI_OPENSECT);
  239. }
  240. return ret;
  241. }
  242. static char * __NEAR__ __FASTCALL__ __GetBrStrName(const char * src,char * store,char obr,char cbr)
  243. {
  244. char *ends;
  245. if(*src == obr)
  246. {
  247. unsigned len;
  248. src++;
  249. ends = strchr(src,cbr);
  250. if(!ends) goto err;
  251. if(*(ends+1)) FiAErrorCL(__FI_BADCHAR);
  252. len = ends-src;
  253. memcpy(store,src,len);
  254. store[len] = 0;
  255. }
  256. else
  257. {
  258. err:
  259. FiAErrorCL(__FI_OPENSECT);
  260. }
  261. return store;
  262. }
  263. #define FiGetLengthBracketString( str ) (__GetLengthBrStr(str,'"','"'))
  264. #define FiGetBracketString( str, store) (__GetBrStrName(str,store,'"','"'))
  265. #define FiGetSectionName( src, store) (__GetBrStrName(src,store,'[',']'))
  266. #define FiGetSubSectionName( src, store) (__GetBrStrName(src,store,'<','>'))
  267. #define FiGetLengthSection( src ) (__GetLengthBrStr(src,'[',']'))
  268. #define FiGetLengthSubSection( src ) (__GetLengthBrStr(src,'<','>'))
  269. unsigned int __FASTCALL__ FiGetLengthItem( const char * src )
  270. {
  271. char *sret;
  272. sret = strchr(src,'=');
  273. if(!sret) FiAErrorCL(__FI_NOTEQU);
  274. return sret - src;
  275. }
  276. unsigned int __FASTCALL__ FiGetLengthValue( const char * src )
  277. {
  278. char *sptr;
  279. unsigned len;
  280. len = strlen(src);
  281. sptr = strchr(src,'=');
  282. if(!sptr) FiAErrorCL(__FI_NOTEQU);
  283. return len-(sptr-src+1);
  284. }
  285. char * __FASTCALL__ FiGetValueOfItem(const char * src,char * store)
  286. {
  287. char *from;
  288. from = strchr(src,'=');
  289. if(from) strcpy(store,++from);
  290. else FiAErrorCL(__FI_NOTEQU);
  291. return store;
  292. }
  293. unsigned int __FASTCALL__ FiGetLengthCommandString( const char * src )
  294. {
  295. unsigned i;
  296. i = strspn(src," #");
  297. return strlen(src) - i;
  298. }
  299. char * __FASTCALL__ FiGetItemName(const char * src,char * store)
  300. {
  301. char *sptr;
  302. unsigned len;
  303. sptr = strchr(src,'=');
  304. if(sptr)
  305. {
  306. len = sptr-src;
  307. memcpy(store,src,len);
  308. store[len] = 0;
  309. if(!IS_VALID_NAME(store)) FiAErrorCL(__FI_BADCHAR);
  310. }
  311. return store;
  312. }
  313. char * __FASTCALL__ FiGetCommandString(const char * src,char * store)
  314. {
  315. unsigned i;
  316. i = strspn(src," #");
  317. strcpy(store,&src[i]);
  318. return store;
  319. }
  320. unsigned int __FASTCALL__ FiGetLengthNextWord( STRING * str, const char * illegal_symbols)
  321. {
  322. unsigned int j,i;
  323. i = strspn(&str->str[str->iptr],illegal_symbols);
  324. j = strcspn(&str->str[i+str->iptr],illegal_symbols);
  325. return j;
  326. }
  327. char * __FASTCALL__ FiGetNextWord( STRING * str,const char * illegal_symbols,char * store)
  328. {
  329. unsigned int j;
  330. str->iptr += strspn(&str->str[str->iptr],illegal_symbols);
  331. j = strcspn(&str->str[str->iptr],illegal_symbols);
  332. memcpy(store,&str->str[str->iptr],j);
  333. store[j] = 0;
  334. str->iptr += j;
  335. return store;
  336. }
  337. static unsigned int __FASTCALL__ FiGetLengthNextLegWord( STRING * str, const char * legal_symbols)
  338. {
  339. unsigned int j,i;
  340. i = strcspn(&str->str[str->iptr],legal_symbols);
  341. j = strspn(&str->str[i+str->iptr],legal_symbols);
  342. return j;
  343. }
  344. static char * __FASTCALL__ FiGetNextLegWord( STRING * str,const char * legal_symbols,char * store)
  345. {
  346. unsigned int j;
  347. str->iptr += strcspn(&str->str[str->iptr],legal_symbols);
  348. j = strspn(&str->str[str->iptr],legal_symbols);
  349. memcpy(store,&str->str[str->iptr],j);
  350. store[j] = 0;
  351. str->iptr += j;
  352. return store;
  353. }
  354. /************** BEGIN of Construct section ********************/
  355. /*
  356. These functions protect library from stack overflow in 16-bit mode,
  357. because #include statement does recursion.
  358. */
  359. static char * __NEAR__ __FASTCALL__ __FiCMaxStr( void )
  360. {
  361. char * ret;
  362. ret = (char *)PMalloc(FI_MAXSTRLEN + 1);
  363. if(ret == NULL) FiAError(__FI_NOTMEM,0,NULL);
  364. return ret;
  365. }
  366. static char * __NEAR__ __FASTCALL__ __FiCNWord( STRING *str , const char * illegal_set)
  367. {
  368. char * ret;
  369. unsigned int lword;
  370. lword = FiGetLengthNextWord(str,illegal_set);
  371. ret = (char *)PMalloc(lword + 1);
  372. if(ret == NULL) FiAError(__FI_NOTMEM,0,NULL);
  373. if(lword) FiGetNextWord(str,illegal_set,ret);
  374. else ret[0] = 0;
  375. return ret;
  376. }
  377. static char * __NEAR__ __FASTCALL__ __FiCNLegWord( STRING *str , const char * legal_set)
  378. {
  379. char * ret;
  380. unsigned int lword;
  381. lword = FiGetLengthNextLegWord(str,legal_set);
  382. ret = (char *)PMalloc(lword + 1);
  383. if(ret == NULL) FiAError(__FI_NOTMEM,0,NULL);
  384. if(lword) FiGetNextLegWord(str,legal_set,ret);
  385. else ret[0] = 0;
  386. return ret;
  387. }
  388. static char * __NEAR__ __FASTCALL__ __FiCBString( const char * src )
  389. {
  390. char * ret;
  391. unsigned int lbr;
  392. lbr = FiGetLengthBracketString(src);
  393. ret = (char *)PMalloc(lbr + 1);
  394. if(ret == NULL) FiAError(__FI_NOTMEM,0,NULL);
  395. if(lbr) FiGetBracketString(src,ret);
  396. else ret[0] = 0;
  397. return ret;
  398. }
  399. static char * __NEAR__ __FASTCALL__ __FiCItem( const char * src )
  400. {
  401. char * ret;
  402. unsigned int li;
  403. li = FiGetLengthItem(src);
  404. ret = (char *)PMalloc(li + 1);
  405. if(ret == NULL) FiAError(__FI_NOTMEM,0,NULL);
  406. if(li) FiGetItemName(src,ret);
  407. else ret[0] = 0;
  408. return ret;
  409. }
  410. static char * __NEAR__ __FASTCALL__ __FiCValue( const char * src )
  411. {
  412. char * ret;
  413. unsigned int lv;
  414. lv = FiGetLengthValue(src);
  415. ret = (char *)PMalloc(lv + 1);
  416. if(ret == NULL) FiAError(__FI_NOTMEM,0,NULL);
  417. if(lv) FiGetValueOfItem(src,ret);
  418. else ret[0] = 0;
  419. return ret;
  420. }
  421. static char * __NEAR__ __FASTCALL__ __FiCSection( const char * src )
  422. {
  423. char * ret;
  424. unsigned int ls;
  425. ls = FiGetLengthSection(src);
  426. ret = (char *)PMalloc(ls + 1);
  427. if(ret == NULL) FiAError(__FI_NOTMEM,0,NULL);
  428. if(ls) FiGetSectionName(src,ret);
  429. else ret[0] = 0;
  430. return ret;
  431. }
  432. static char * __NEAR__ __FASTCALL__ __FiCSubSection( const char * src )
  433. {
  434. char * ret;
  435. unsigned int lss;
  436. lss = FiGetLengthSubSection(src);
  437. ret = (char *)PMalloc(lss + 1);
  438. if(ret == NULL) FiAError(__FI_NOTMEM,0,NULL);
  439. if(lss) FiGetSubSectionName(src,ret);
  440. else ret[0] = 0;
  441. return ret;
  442. }
  443. static char * __NEAR__ __FASTCALL__ __FiCCmd( const char * src )
  444. {
  445. char * ret;
  446. unsigned int lc;
  447. lc = FiGetLengthCommandString(src);
  448. ret = (char *)PMalloc(lc + 1);
  449. if(ret == NULL) FiAError(__FI_NOTMEM,0,NULL);
  450. if(lc) FiGetCommandString(src,ret);
  451. else ret[0] = 0;
  452. return ret;
  453. }
  454. /************* END of Construct section *********************/
  455. #if 0 /* Uncomment it later */
  456. void __FASTCALL__ FiSeekTo( FiHandler h, unsigned int nSection, unsigned int nSubSection, unsigned int nItem )
  457. {
  458. unsigned int ns = 0,nss = 0,ni = 0;
  459. bioSeek(h,0L,SEEKF_START);
  460. FinCurrString[FiFilePtr - 1] = 0;
  461. if(nSection)
  462. {
  463. char * buff;
  464. buff = __FiCMaxStr();
  465. while(!bioEOF(h))
  466. {
  467. FiGetNextString(h,buff,FI_MAXSTRLEN,NULL);
  468. if(FiisSection(buff)) ns++;
  469. if(ns < nSection) continue;
  470. }
  471. PFREE(buff);
  472. }
  473. if(nSubSection)
  474. {
  475. char * buff;
  476. buff = __FiCMaxStr();
  477. while(!bioEOF(h))
  478. {
  479. FiGetNextString(h,buff,FI_MAXSTRLEN,NULL);
  480. if(FiisSubSection(buff)) nss++;
  481. if(nss < nSubSection) continue;
  482. }
  483. PFREE(buff);
  484. }
  485. if(nItem)
  486. {
  487. char * buff;
  488. buff = __FiCMaxStr();
  489. while(!bioEOF(h))
  490. {
  491. FiGetNextString(h,buff,FI_MAXSTRLEN,NULL);
  492. if(FiisItem(buff)) ni++;
  493. if(nss < nItem) continue;
  494. }
  495. PFREE(buff);
  496. }
  497. }
  498. int __FASTCALL__ FiSearch(FiHandler h, const char * str )
  499. {
  500. char *tmp,*buff;
  501. tmp = __FiCMaxStr();
  502. buff = __FiCMaxStr();
  503. bioSeek(h,0L,SEEKF_START);
  504. FinCurrString[FiFilePtr - 1] = 0;
  505. while(!bioEOF(h))
  506. {
  507. FiGetNextString(h,buff,FI_MAXSTRLEN,NULL);
  508. if(FiisSection(buff))
  509. {
  510. FiGetSectionName(buff,tmp);
  511. if(strcmp(tmp,str) == 0) { PFREE(tmp); PFREE(buff); return __FI_SECTION;}
  512. }
  513. if(FiisSubSection(buff))
  514. {
  515. FiGetSubSectionName(buff,tmp);
  516. if(strcmp(tmp,str) == 0) { PFREE(buff); PFREE(tmp); return __FI_SUBSECTION; }
  517. }
  518. if(FiisItem(buff))
  519. {
  520. FiGetItemName(buff,tmp);
  521. if(strcmp(tmp,str) == 0) { PFREE(tmp); PFREE(buff); return __FI_ITEM; }
  522. }
  523. }
  524. bioSeek(h,0L,SEEKF_START);
  525. FinCurrString[FiFilePtr - 1] = 0;
  526. PFREE(tmp);
  527. PFREE(buff);
  528. return __FI_NOTFOUND;
  529. }
  530. unsigned int __FASTCALL__ FiGetNumberOfSections( FiHandler h)
  531. {
  532. __fileoff_t curr;
  533. unsigned int eret;
  534. unsigned int save;
  535. char * buff;
  536. eret = 0;
  537. save = FinCurrString[FiFilePtr -1];
  538. curr = bioTell(h);
  539. buff = __FiCMaxStr();
  540. bioSeek(h,0L,SEEKF_START);
  541. while(!bioEOF(h))
  542. {
  543. FiGetNextString(h,buff,FI_MAXSTRLEN,NULL);
  544. if(FiisSection(buff)) eret++;
  545. }
  546. bioSeek(h,curr,SEEKF_START);
  547. FinCurrString[FiFilePtr - 1] = save;
  548. PFREE(buff);
  549. return eret;
  550. }
  551. unsigned int __FASTCALL__ FiGetTotalNumberOfSubSections( FiHandler h )
  552. {
  553. __fileoff_t curr;
  554. unsigned int eret;
  555. unsigned int save;
  556. char * buff;
  557. eret = 0;
  558. curr = bioTell(h);
  559. buff = __FiCMaxStr();
  560. save = FinCurrString[FiFilePtr - 1];
  561. bioSeek(h,0L,SEEKF_START);
  562. while(!bioEOF(h))
  563. {
  564. FiGetNextString(h,buff,FI_MAXSTRLEN,NULL);
  565. if(FiisSubSection(buff)) eret++;
  566. }
  567. bioSeek(h,curr,SEEKF_START);
  568. FinCurrString[FiFilePtr - 1] = save;
  569. PFREE(buff);
  570. return eret;
  571. }
  572. unsigned int __FASTCALL__ FiGetLocalNumberOfSubSections( FiHandler h, unsigned unsigned int nSection )
  573. {
  574. __fileoff_t curr;
  575. unsigned int eret;
  576. unsigned int save;
  577. char * buff;
  578. save = FinCurrString[FiFilePtr - 1];
  579. curr = bioTell(h);
  580. eret = 0;
  581. buff = __FiCMaxStr();
  582. FiSeekTo(h,nSection,0,0);
  583. while(!bioEOF(h))
  584. {
  585. FiGetNextString(h,buff,FI_MAXSTRLEN,NULL);
  586. if(FiisItem(buff)) eret++;
  587. }
  588. bioSeek(h,curr,SEEKF_START);
  589. FinCurrString[FiFilePtr - 1] = save;
  590. PFREE(buff);
  591. return eret;
  592. }
  593. unsigned int __FASTCALL__ FiGetTotalNumberOfItems( FiHandler h)
  594. {
  595. __fileoff_t curr;
  596. unsigned int eret;
  597. unsigned int save;
  598. char * buff;
  599. eret = 0;
  600. curr = bioTell(h);
  601. save = FinCurrString[FiFilePtr - 1];
  602. buff = __FiCMaxStr();
  603. bioSeek(h,0L,SEEKF_START);
  604. while(!bioEOF(h))
  605. {
  606. FiGetNextString(h,buff,FI_MAXSTRLEN,NULL);
  607. if(FiisItem(buff)) eret++;
  608. }
  609. bioSeek(h,curr,SEEKF_START);
  610. FinCurrString[FiFilePtr - 1] = save;
  611. PFREE(buff);
  612. return eret;
  613. }
  614. unsigned int __FASTCALL__ FiGetLocalNumberOfItems( FiHandler h,int nSection, int nSubSection)
  615. {
  616. __fileoff_t curr;
  617. unsigned int eret;
  618. unsigned int save;
  619. char * buff;
  620. save = FinCurrString[FiFilePtr - 1];
  621. curr = bioTell(h);
  622. eret = 0;
  623. buff = __FiCMaxStr();
  624. FiSeekTo(h,nSection,nSubSection,0);
  625. while(!bioEOF(h))
  626. {
  627. FiGetNextString(h,buff,FI_MAXSTRLEN,NULL);
  628. if(FiisItem(buff)) eret++;
  629. }
  630. bioSeek(h,curr,SEEKF_START);
  631. FinCurrString[FiFilePtr - 1] = save;
  632. PFREE(buff);
  633. return eret;
  634. }
  635. #endif
  636. #define FiOpenComment ';'
  637. bool FiAllWantInput = false;
  638. char * __FASTCALL__ FiGetNextString(FiHandler h, char * str,unsigned int size,char *original)
  639. {
  640. unsigned char *sret;
  641. unsigned len;
  642. unsigned char ch;
  643. str[0] = 0;
  644. while(!bioEOF(h))
  645. {
  646. str[0] = 0;
  647. sret = GETS(str,size,h);
  648. len = strlen(str);
  649. while(len)
  650. {
  651. ch = str[len-1];
  652. if(ch == '\n' || ch == '\r') str[--len] = 0;
  653. else break;
  654. }
  655. if(original) strcpy(original,str);
  656. FinCurrString[FiFilePtr - 1]++;
  657. if((sret == NULL && !bioEOF( h ))) FiAError(__FI_BADFILENAME,0,str);
  658. sret = strchr(str,FiOpenComment);
  659. if(sret) *sret = 0;
  660. if(!FiAllWantInput)
  661. {
  662. szTrimTrailingSpace(str);
  663. szTrimLeadingSpace(str);
  664. /* kill all spaces around punctuations */
  665. /*
  666. Correct me: spaces will be sqweezed even inside " " brackets.
  667. But it is language dependent.
  668. For .ini files it is not significant.
  669. */
  670. sret = str;
  671. while((ch=*sret) != 0)
  672. {
  673. if(ispunct(ch)) sret = szKillSpaceAround(str,sret);
  674. sret++;
  675. }
  676. len = strlen(str);
  677. sret = str;
  678. while((ch=*sret) != 0)
  679. {
  680. if(isspace(ch))
  681. {
  682. if(isspace(*(sret+1))) sret = szKillSpaceAround(str,sret);
  683. }
  684. sret++;
  685. }
  686. if(strlen(str)) break; /* loop while comment */
  687. }
  688. }
  689. return str;
  690. }
  691. /*************************************************************\
  692. * Middle level support *
  693. \*************************************************************/
  694. /************* BEGIN of List Var section ********************/
  695. pVar __FASTCALL__ FiConstructVar(const char *v,const char *a)
  696. {
  697. char * str;
  698. pVar vv;
  699. vv = (pVar)PMalloc(sizeof(Var));
  700. if(vv == NULL) FiAError(__FI_NOTMEM,0,NULL);
  701. vv->next = NULL;
  702. vv->prev = NULL;
  703. str = (char *)PMalloc(strlen(v) + 1);
  704. if(str == NULL) FiAError(__FI_NOTMEM,0,NULL);
  705. strcpy(str,v);
  706. vv->variables = str;
  707. str = (char *)PMalloc(strlen(a) + 1);
  708. if(str == NULL) FiAError(__FI_NOTMEM,0,NULL);
  709. strcpy(str,a);
  710. vv->associate = str;
  711. return vv;
  712. }
  713. void __FASTCALL__ FiDeleteVar(pVar pp)
  714. {
  715. PFREE(pp->variables);
  716. PFREE(pp->associate);
  717. PFREE(pp);
  718. }
  719. void __FASTCALL__ FiDeleteAllVar( void )
  720. {
  721. pVar iter;
  722. if(FirstVar)
  723. {
  724. iter = FirstVar;
  725. while( iter!= 0 )
  726. {
  727. pVar temp;
  728. temp = iter->next;
  729. FiDeleteVar(iter);
  730. iter = temp;
  731. }
  732. FirstVar = 0;
  733. }
  734. }
  735. const char * __FASTCALL__ FiExpandVariables(const char * var)
  736. {
  737. char *ret = 0;
  738. pVar iter;
  739. iter = FirstVar;
  740. if(FirstVar != NULL)
  741. {
  742. for(;;)
  743. {
  744. if(strcmp(var,iter->variables) == 0)
  745. {
  746. ret = iter->associate;
  747. break;
  748. }
  749. if(iter->next == NULL) FiAErrorCL(__FI_NODEFVAR);
  750. iter = iter->next;
  751. }
  752. }
  753. return ret;
  754. }
  755. bool __FASTCALL__ FiExpandAllVar(const char * value,char * store)
  756. {
  757. bool ret;
  758. if(ifSmarting && strchr(value,'%'))
  759. {
  760. char tmp[FI_MAXSTRLEN+1];
  761. char isVar,npercent;
  762. unsigned char buffer_ptr,tmp_ptr;
  763. unsigned int i,slen;
  764. npercent = 0;
  765. buffer_ptr = tmp_ptr = isVar = 0;
  766. slen = strlen(value);
  767. for(i = 0;i < slen;i++)
  768. {
  769. char c;
  770. c = value[i];
  771. if(c == '%')
  772. {
  773. npercent++;
  774. isVar = !isVar;
  775. if(!isVar)
  776. {
  777. tmp[tmp_ptr] = '\0';
  778. strcpy(&store[buffer_ptr],FiExpandVariables(tmp));
  779. buffer_ptr = strlen(store);
  780. tmp_ptr = 0;
  781. }
  782. }
  783. else
  784. {
  785. if(isVar) tmp[tmp_ptr++] = c;
  786. else store[buffer_ptr++] = c;
  787. }
  788. }
  789. store[buffer_ptr] = '\0';
  790. if( npercent%2 ) FiAErrorCL(__FI_OPENVAR);
  791. ret = true;
  792. }
  793. else
  794. {
  795. strcpy(store,value);
  796. ret = false;
  797. }
  798. return ret;
  799. }
  800. void __FASTCALL__ FiAddVariables(const char * var,const char * associate)
  801. {
  802. pVar iter,prev;
  803. if(!FirstVar)
  804. {
  805. FirstVar = FiConstructVar(var,associate);
  806. FirstVar->next = NULL;
  807. FirstVar->prev = NULL;
  808. }
  809. else
  810. {
  811. iter = FirstVar;
  812. for(;;)
  813. {
  814. if(strcmp(iter->variables,var) == 0)
  815. {
  816. PFREE(iter->associate);
  817. iter->associate = PMalloc(strlen(associate) + 1);
  818. if(iter->associate == NULL) FiAError(__FI_NOTMEM,0,NULL);
  819. strcpy(iter->associate,associate);
  820. return;
  821. }
  822. if(iter->next == NULL) break;
  823. iter = iter->next;
  824. }
  825. prev = FiConstructVar(var,associate);
  826. iter->next = prev;
  827. prev->prev = iter;
  828. }
  829. }
  830. void __FASTCALL__ FiRemoveVariables(const char * var)
  831. {
  832. pVar iter,p;
  833. if(FirstVar == NULL) return;
  834. iter = FirstVar;
  835. for(;;)
  836. {
  837. if(strcmp(var,iter->variables) == 0)
  838. {
  839. if(iter != FirstVar)
  840. {
  841. p = iter->prev;
  842. p->next = iter->next;
  843. FiDeleteVar(iter);
  844. return;
  845. }
  846. else
  847. {
  848. p = iter->next;
  849. FiDeleteVar(iter);
  850. FirstVar = p;
  851. return;
  852. }
  853. }
  854. if(iter->next == NULL) break;
  855. iter = iter->next;
  856. }
  857. FiAErrorCL(__FI_NOVAR);
  858. }
  859. /*************** END of List Var Section ***************/
  860. bool __FASTCALL__ FiGetConditionStd( const char *condstr)
  861. {
  862. char * var,*user_ass;
  863. char * real_ass;
  864. const char *rvar;
  865. STRING str;
  866. bool ret;
  867. char cond[3];
  868. str.iptr = 0;
  869. str.str = condstr;
  870. user_ass = __FiCMaxStr();
  871. real_ass = __FiCMaxStr();
  872. var = __FiCNWord(&str," !=");
  873. FiExpandAllVar(var,real_ass);
  874. PFREE(var);
  875. rvar = FiExpandVariables(real_ass);
  876. cond[0] = str.str[str.iptr++];
  877. cond[1] = str.str[str.iptr++];
  878. cond[2] = '\0';
  879. var = __FiCNWord(&str," ");
  880. FiExpandAllVar(var,user_ass);
  881. PFREE(var);
  882. if(str.str[str.iptr]) FiAErrorCL(__FI_BADCHAR);
  883. ret = false;
  884. if(strcmp(cond,"==") == 0) ret = (strcmp(user_ass,rvar) == 0);
  885. else
  886. if(strcmp(cond,"!=") == 0) ret = (strcmp(user_ass,rvar) != 0);
  887. else
  888. FiAErrorCL(__FI_BADCOND);
  889. PFREE(user_ass);
  890. PFREE(real_ass);
  891. return ret;
  892. }
  893. bool __FASTCALL__ FiCommandProcessorStd( const char * cmd )
  894. {
  895. char *word,*a,*v;
  896. const char *fdeb_save;
  897. STRING str;
  898. static bool cond_ret = true;
  899. str.iptr = 0;
  900. str.str = cmd;
  901. word = __FiCNLegWord(&str,&iniLegalSet[1]);
  902. strlwr(word);
  903. if(strcmp(word,"include") == 0)
  904. {
  905. char * bracket;
  906. char _v[FI_MAXSTRLEN+1];
  907. char pfile[FILENAME_MAX+1],*pfp,*pfp2;
  908. bracket = __FiCBString(&str.str[str.iptr]);
  909. FiExpandAllVar(bracket,_v);
  910. fdeb_save = fi_Debug_Str;
  911. /* make path if no path specified */
  912. strcpy(pfile,FiFileNames[FiFilePtr-1]);
  913. pfp=strrchr(pfile,'\\');
  914. pfp2=strrchr(pfile,'/');
  915. pfp=max(pfp,pfp2);
  916. if(pfp && !(strchr(_v,'\\') || strchr(_v,'/'))) strcpy(pfp+1,_v);
  917. else strcpy(pfile,_v);
  918. (*FiFileProcessor)(pfile);
  919. fi_Debug_Str = fdeb_save;
  920. PFREE(bracket);
  921. goto Exit_CP;
  922. }
  923. else
  924. if(strcmp(word,"set") == 0)
  925. {
  926. v = __FiCNLegWord(&str,&iniLegalSet[1]);
  927. if(str.str[str.iptr] != '=') FiAErrorCL(__FI_NOTEQU);
  928. str.iptr++;
  929. a = __FiCNWord(&str," ");
  930. if(v[0] == '\0' || v == NULL ) FiAErrorCL(__FI_BADVAR);
  931. if(a[0] == '\0' || a == NULL ) FiAErrorCL(__FI_BADVAL);
  932. FiAddVariables(v,a);
  933. PFREE(a);
  934. PFREE(v);
  935. if(str.str[str.iptr]) FiAErrorCL(__FI_BADCHAR);
  936. goto Exit_CP;
  937. }
  938. else
  939. if(strcmp(word,"delete") == 0)
  940. {
  941. v = __FiCNLegWord(&str,&iniLegalSet[1]);
  942. a = __FiCMaxStr();
  943. FiExpandAllVar(v,a);
  944. if(a[0] == '\0' || a == NULL) FiAErrorCL(__FI_BADVAR);
  945. FiRemoveVariables(a);
  946. PFREE(v);
  947. PFREE(a);
  948. if(str.str[str.iptr]) FiAErrorCL(__FI_BADCHAR);
  949. goto Exit_CP;
  950. }
  951. else
  952. if(strcmp(word,"reset") == 0)
  953. {
  954. if(str.str[str.iptr]) FiAErrorCL(__FI_BADCHAR);
  955. FiDeleteAllVar();
  956. goto Exit_CP;
  957. }
  958. else
  959. if(strcmp(word,"case") == 0)
  960. {
  961. if(str.str[str.iptr]) FiAErrorCL(__FI_BADCHAR);
  962. CaseSens = 2;
  963. goto Exit_CP;
  964. }
  965. else
  966. if(strcmp(word,"smart") == 0)
  967. {
  968. if(str.str[str.iptr]) FiAErrorCL(__FI_BADCHAR);
  969. ifSmarting = true;
  970. goto Exit_CP;
  971. }
  972. else
  973. if(strcmp(word,"nosmart") == 0)
  974. {
  975. if(str.str[str.iptr]) FiAErrorCL(__FI_BADCHAR);
  976. ifSmarting = false;
  977. goto Exit_CP;
  978. }
  979. else
  980. if(strcmp(word,"uppercase") == 0)
  981. {
  982. if(str.str[str.iptr]) FiAErrorCL(__FI_BADCHAR);
  983. CaseSens = 1;
  984. goto Exit_CP;
  985. }
  986. else
  987. if(strcmp(word,"lowercase") == 0)
  988. {
  989. if(str.str[str.iptr]) FiAErrorCL(__FI_BADCHAR);
  990. CaseSens = 0;
  991. goto Exit_CP;
  992. }
  993. else
  994. if(strcmp(word,"error") == 0)
  995. {
  996. a = __FiCMaxStr();
  997. FiExpandAllVar(&str.str[str.iptr+1],a);
  998. FiUserMessage = a;
  999. FiAErrorCL(__FI_FIUSER);
  1000. }
  1001. else
  1002. if(strcmp(word,"else") == 0) FiAErrorCL(__FI_ELSESTAT);
  1003. else
  1004. if(strcmp(word,"endif") == 0) FiAErrorCL(__FI_IFNOTFOUND);
  1005. else
  1006. if(strcmp(word,"elif") == 0) FiAErrorCL(__FI_ELIFSTAT);
  1007. else
  1008. if(strcmp(word,"if") == 0)
  1009. {
  1010. char *sstore;
  1011. unsigned int nsave;
  1012. bool Condition,BeenElse;
  1013. int nLabel;
  1014. sstore = __FiCMaxStr();
  1015. nsave = FinCurrString[FiFilePtr - 1];
  1016. cond_ret = Condition = (*FiGetCondition)(&cmd[str.iptr]);
  1017. nLabel = 1;
  1018. BeenElse = false;
  1019. while(!bioEOF(ActiveFile))
  1020. {
  1021. FiGetNextString(ActiveFile,sstore,FI_MAXSTRLEN,NULL);
  1022. if(sstore[0] == '\0') { PFREE(sstore); goto Exit_CP; }
  1023. if(FiisCommand(sstore))
  1024. {
  1025. STRING cStr;
  1026. a = __FiCCmd(sstore);
  1027. if(CaseSens == 1) strupr(a);
  1028. if(CaseSens == 0) strlwr(a);
  1029. cStr.iptr = 0;
  1030. cStr.str = a;
  1031. v = __FiCNWord(&cStr," ");
  1032. strlwr(v);
  1033. if(strcmp(v,"if") == 0 && !Condition) nLabel++;
  1034. if(strcmp(v,"endif") == 0 )
  1035. {
  1036. nLabel--;
  1037. if(nLabel == 0)
  1038. {
  1039. PFREE(sstore);
  1040. PFREE(a);
  1041. PFREE(v);
  1042. goto Exit_CP;
  1043. }
  1044. if(nLabel < 0) FiAErrorCL(__FI_IFNOTFOUND);
  1045. }
  1046. if(strcmp(v,"else") == 0 && nLabel == 1)
  1047. {
  1048. if( BeenElse ) FiAErrorCL(__FI_ELSESTAT);
  1049. if( nLabel == 1 ) cond_ret = Condition = (Condition ? false : true);
  1050. if( nLabel == 1 ) BeenElse = true;
  1051. PFREE(v);
  1052. PFREE(a);
  1053. continue;
  1054. }
  1055. if(strcmp(v,"elif") == 0 && nLabel == 1)
  1056. {
  1057. if( BeenElse ) FiAErrorCL(__FI_ELIFSTAT);
  1058. if( nLabel == 1 ) cond_ret = Condition = (*FiGetCondition)(&a[cStr.iptr]);
  1059. if( nLabel == 1 ) BeenElse = true;
  1060. PFREE(v);
  1061. PFREE(a);
  1062. continue;
  1063. }
  1064. if(Condition) (*FiCommandProcessor)(a);
  1065. PFREE(v);
  1066. PFREE(a);
  1067. }
  1068. else { if(Condition) (*FiStringProcessor)(sstore); }
  1069. }
  1070. PFREE(sstore)
  1071. FiAError(__FI_OPENCOND,nsave,NULL);
  1072. }
  1073. FiAErrorCL(__FI_UNRECOGN);
  1074. Exit_CP:
  1075. PFREE(word);
  1076. return cond_ret;
  1077. }
  1078. static char * curr_sect = NULL;
  1079. static char * curr_subsect = NULL;
  1080. bool __FASTCALL__ FiStringProcessorStd(char * curr_str)
  1081. {
  1082. char *item,*val;
  1083. if(FiisCommand(curr_str))
  1084. {
  1085. item = __FiCCmd(curr_str);
  1086. (*FiCommandProcessor)(item);
  1087. PFREE(item);
  1088. return false;
  1089. }
  1090. else
  1091. if(FiisSection(curr_str))
  1092. {
  1093. if(curr_sect) PFREE(curr_sect);
  1094. if(curr_subsect) PFREE(curr_subsect);
  1095. curr_sect = __FiCSection(curr_str);
  1096. return false;
  1097. }
  1098. else
  1099. if(FiisSubSection(curr_str))
  1100. {
  1101. if(curr_subsect) PFREE(curr_subsect);
  1102. curr_subsect = __FiCSubSection(curr_str);
  1103. return false;
  1104. }
  1105. else
  1106. if(FiisItem(curr_str))
  1107. {
  1108. char buffer[FI_MAXSTRLEN+1];
  1109. bool retval;
  1110. IniInfo info;
  1111. FiExpandAllVar(curr_str,buffer);
  1112. item = __FiCItem(buffer);
  1113. retval = false;
  1114. if(item[0])
  1115. {
  1116. val = __FiCValue(buffer);
  1117. if(curr_sect) info.section = curr_sect;
  1118. else info.section = "";
  1119. if(curr_subsect) info.subsection = curr_subsect;
  1120. else info.subsection = "";
  1121. info.item = item;
  1122. info.value = val;
  1123. retval = (*proc)(&info);
  1124. PFREE(val);
  1125. }
  1126. else FiAErrorCL(__FI_BADCHAR);
  1127. PFREE(item);
  1128. return retval;
  1129. }
  1130. return false;
  1131. }
  1132. void __FASTCALL__ FiFileProcessorStd(const char * filename)
  1133. {
  1134. char * work_str, * ondelete;
  1135. FiHandler h;
  1136. FiHandler oldh;
  1137. bool done;
  1138. oldh = ActiveFile;
  1139. h = FiOpen(filename);
  1140. ActiveFile = h;
  1141. work_str = __FiCMaxStr();
  1142. fi_Debug_Str = ondelete = work_str;
  1143. while(!bioEOF(h))
  1144. {
  1145. FiGetNextString(h,work_str,FI_MAXSTRLEN,NULL);
  1146. if(!work_str || !work_str[0]) break;
  1147. if(CaseSens == 1) strupr(work_str);
  1148. if(CaseSens == 0) strlwr(work_str);
  1149. done = (*FiStringProcessor)(work_str);
  1150. if(done) break;
  1151. }
  1152. FiClose(h);
  1153. if(work_str) PFREE(work_str)
  1154. else PFREE(ondelete)
  1155. ActiveFile = oldh;
  1156. }
  1157. void __FASTCALL__ FiProgress(const char * filename,FiUserFunc usrproc)
  1158. {
  1159. if(!usrproc) return;
  1160. proc = usrproc;
  1161. (*FiFileProcessor)(filename);
  1162. proc = NULL;
  1163. if(curr_sect) PFREE(curr_sect);
  1164. if(curr_subsect) PFREE(curr_subsect);
  1165. FiDeleteAllVar();
  1166. }
  1167. static void __FASTCALL__ hlFiFileProcessorStd(hIniProfile *ini)
  1168. {
  1169. char * work_str, * ondelete;
  1170. FiHandler oldh;
  1171. bool done;
  1172. oldh = ActiveFile;
  1173. ActiveFile = ini->handler;
  1174. work_str = __FiCMaxStr();
  1175. fi_Debug_Str = ondelete = work_str;
  1176. rewind_ini(ini->handler);
  1177. while(!bioEOF(ini->handler))
  1178. {
  1179. FiGetNextString(ini->handler,work_str,FI_MAXSTRLEN,NULL);
  1180. if(!work_str || !work_str[0]) break;
  1181. if(CaseSens == 1) strupr(work_str);
  1182. if(CaseSens == 0) strlwr(work_str);
  1183. done = (*FiStringProcessor)(work_str);
  1184. if(done) break;
  1185. }
  1186. if(work_str) PFREE(work_str)
  1187. else PFREE(ondelete)
  1188. ActiveFile = oldh;
  1189. }
  1190. void __FASTCALL__ hlFiProgress(hIniProfile *ini,FiUserFunc usrproc)
  1191. {
  1192. if(!usrproc) return;
  1193. proc = usrproc;
  1194. hlFiFileProcessorStd(ini);
  1195. proc = NULL;
  1196. if(curr_sect) PFREE(curr_sect);
  1197. if(curr_subsect) PFREE(curr_subsect);
  1198. FiDeleteAllVar();
  1199. }
  1200. void (__FASTCALL__ *FiFileProcessor)(const char *fname) = FiFileProcessorStd;
  1201. bool (__FASTCALL__ *FiStringProcessor)(char * curr_str) = FiStringProcessorStd;
  1202. bool (__FASTCALL__ *FiCommandProcessor)(const char * cmd) = FiCommandProcessorStd;
  1203. bool (__FASTCALL__ *FiGetCondition)( const char *condstr) = FiGetConditionStd;
  1204. /*****************************************************************\
  1205. * High level support *
  1206. \******************************************************************/
  1207. static hIniProfile *opening;
  1208. #define IC_STRING 0x0001
  1209. typedef struct tag_ini_Cache
  1210. {
  1211. unsigned flags;
  1212. char * item;
  1213. union
  1214. {
  1215. linearArray *leaf;
  1216. char *value;
  1217. }v;
  1218. }ini_cache;
  1219. static tCompare __FASTCALL__ __full_compare_cache(const void __HUGE__ *v1,const void __HUGE__ *v2)
  1220. {
  1221. const ini_cache __HUGE__ *c1, __HUGE__ *c2;
  1222. int iflg;
  1223. tCompare i_ret;
  1224. c1 = (const ini_cache __HUGE__ *)v1;
  1225. c2 = (const ini_cache __HUGE__ *)v2;
  1226. iflg = __CmpLong__(c1->flags,c2->flags);
  1227. i_ret = strcmp(c1->item,c2->item);
  1228. return i_ret ? i_ret : iflg;
  1229. }
  1230. #define __compare_cache __full_compare_cache
  1231. static bool __NEAR__ __FASTCALL__ __addCache(const char *section,const char *subsection,
  1232. const char *item,const char *value)
  1233. {
  1234. void __HUGE__ *found;
  1235. ini_cache __HUGE__ *it;
  1236. ini_cache ic;
  1237. ic.item = section;
  1238. ic.flags = 0;
  1239. if(!(found =la_Find((linearArray *)opening->cache,&ic,__full_compare_cache)))
  1240. {
  1241. ic.item = PMalloc(strlen(section)+1);
  1242. if(!ic.item) { opening->flags &= ~HINI_FULLCACHED; return true; }
  1243. strcpy(ic.item,section);
  1244. if(!(ic.v.leaf = la_Build(0,sizeof(ini_cache),0)))
  1245. {
  1246. PFree(ic.item);
  1247. opening->flags &= ~HINI_FULLCACHED;
  1248. return true;
  1249. }
  1250. ic.flags = 0;
  1251. if(!(la_AddData((linearArray *)opening->cache,&ic,NULL)))
  1252. {
  1253. PFree(ic.item);
  1254. la_Destroy(ic.v.leaf);
  1255. opening->flags &= ~HINI_FULLCACHED;
  1256. return true;
  1257. }
  1258. opening->flags |= HINI_UPDATED;
  1259. la_Sort((linearArray *)opening->cache,__compare_cache);
  1260. found = la_Find((linearArray *)opening->cache,&ic,__full_compare_cache);
  1261. goto do_subsect;
  1262. }
  1263. else
  1264. {
  1265. do_subsect:
  1266. it = (ini_cache __HUGE__ *)found;
  1267. ic.item = subsection;
  1268. if(!(found=la_Find(it->v.leaf,&ic,__full_compare_cache)))
  1269. {
  1270. ic.item = PMalloc(strlen(subsection)+1);
  1271. if(!ic.item) { opening->flags &= ~HINI_FULLCACHED; return true; }
  1272. strcpy(ic.item,subsection);
  1273. if(!(ic.v.leaf = la_Build(0,sizeof(ini_cache),0)))
  1274. {
  1275. PFree(ic.item);
  1276. opening->flags &= ~HINI_FULLCACHED;
  1277. return true;
  1278. }
  1279. ic.flags = 0;
  1280. if(!(la_AddData(it->v.leaf,&ic,NULL)))
  1281. {
  1282. PFree(ic.item);
  1283. la_Destroy(ic.v.leaf);
  1284. opening->flags &= ~HINI_FULLCACHED;
  1285. return true;
  1286. }
  1287. opening->flags |= HINI_UPDATED;
  1288. la_Sort(it->v.leaf,__compare_cache);
  1289. found = la_Find(it->v.leaf,&ic,__full_compare_cache);
  1290. goto do_item;
  1291. }
  1292. else
  1293. {
  1294. do_item:
  1295. it = (ini_cache __HUGE__ *)found;
  1296. ic.item = item;
  1297. ic.flags = IC_STRING;
  1298. if(!(found=la_Find(it->v.leaf,&ic,__full_compare_cache)))
  1299. {
  1300. ic.item = PMalloc(strlen(item)+1);
  1301. if(!ic.item) { opening->flags &= ~HINI_FULLCACHED; return true; }
  1302. strcpy(ic.item,item);
  1303. ic.v.value = PMalloc(strlen(value)+1);
  1304. if(!ic.v.value) { PFree(ic.item); opening->flags &= ~HINI_FULLCACHED; return true; }
  1305. strcpy(ic.v.value,value);
  1306. if(!(la_AddData(it->v.leaf,&ic,NULL)))
  1307. {
  1308. PFree(ic.item);
  1309. PFree(ic.v.value);
  1310. opening->flags &= ~HINI_FULLCACHED;
  1311. return true;
  1312. }
  1313. opening->flags |= HINI_UPDATED;
  1314. la_Sort(it->v.leaf,__compare_cache);
  1315. }
  1316. else
  1317. {
  1318. /* item already exists. Try replace it */
  1319. it = (ini_cache __HUGE__ *)found;
  1320. if(strcmp(it->v.value,value) != 0)
  1321. {
  1322. char *newval,*oldval;
  1323. newval = PMalloc(strlen(value)+1);
  1324. if(!newval)
  1325. {
  1326. opening->flags &= ~HINI_FULLCACHED;
  1327. return true;
  1328. }
  1329. strcpy(newval,value);
  1330. oldval = it->v.value;
  1331. it->v.value = newval;
  1332. PFree(oldval);
  1333. opening->flags |= HINI_UPDATED;
  1334. }
  1335. }
  1336. }
  1337. }
  1338. return false;
  1339. }
  1340. static bool __FASTCALL__ __buildCache(IniInfo *ini)
  1341. {
  1342. return __addCache(ini->section,ini->subsection,
  1343. ini->item,ini->value);
  1344. }
  1345. static void __FASTCALL__ __iter_destroy(void __HUGE__ *it);
  1346. #define __destroyCache(it) (la_IterDestroy(it,__iter_destroy))
  1347. static void __FASTCALL__ __iter_destroy(void __HUGE__ *it)
  1348. {
  1349. ini_cache __HUGE__ *ic;
  1350. ic = (ini_cache __HUGE__ *)it;
  1351. if(ic->flags & IC_STRING)
  1352. {
  1353. PFree(ic->item);
  1354. PFree(ic->v.value);
  1355. }
  1356. else
  1357. {
  1358. PFree(ic->item);
  1359. la_IterDestroy(ic->v.leaf,__iter_destroy);
  1360. }
  1361. }
  1362. static unsigned ret;
  1363. static unsigned buf_len;
  1364. static char *buf_ptr;
  1365. static const char *sect,* subsect,* item;
  1366. static bhandle_t __NEAR__ __FASTCALL__ make_temp(const char *path,char *name_ptr)
  1367. {
  1368. char *fullname, *nptr;
  1369. unsigned i,len;
  1370. bhandle_t handle;
  1371. fullname = PMalloc((strlen(path)+1)*2);
  1372. if(!fullname) return NULL_HANDLE;
  1373. strcpy(fullname,path);
  1374. len = strlen(fullname);
  1375. if(fullname[len-4] == '.') nptr = &fullname[len-4];
  1376. else nptr = &fullname[len];
  1377. handle = NULL_HANDLE;
  1378. for(i = 0;i < 100;i++)
  1379. {
  1380. /*
  1381. in this loop we are change only extension:
  1382. file.tmp file.t1 ... file.t99
  1383. (it's only for compatibilities between different OS FS)
  1384. */
  1385. sprintf(nptr,".t%i",i);
  1386. handle = __OsOpen(fullname,FO_READONLY | SO_DENYNONE);
  1387. if(handle == NULL_HANDLE) handle = __OsOpen(fullname,FO_READONLY | SO_COMPAT);
  1388. if(handle == NULL_HANDLE)
  1389. {
  1390. handle = __OsCreate(fullname);
  1391. if(handle != NULL_HANDLE)
  1392. {
  1393. strcpy(name_ptr,fullname);
  1394. goto bye;
  1395. }
  1396. }
  1397. }
  1398. bye:
  1399. return handle;
  1400. }
  1401. static bool __FASTCALL__ MyCallback(IniInfo * ini)
  1402. {
  1403. int cond;
  1404. cond = 0;
  1405. if(sect) cond = strcmp(ini->section,sect) == 0;
  1406. if(subsect) cond &= strcmp(ini->subsection,subsect) == 0;
  1407. if(item) cond &= strcmp(ini->item,item) == 0;
  1408. if(cond)
  1409. {
  1410. ret = min(strlen(ini->value),buf_len);
  1411. strncpy(buf_ptr,ini->value,buf_len);
  1412. return true;
  1413. }
  1414. return false;
  1415. }
  1416. static int __NEAR__ __FASTCALL__ out_sect(FILE * handle,const char *section)
  1417. {
  1418. fprintf(handle,"[ %s ]\n",section);
  1419. return 2;
  1420. }
  1421. static int __NEAR__ __FASTCALL__ out_subsect(FILE * handle,const char *subsection)
  1422. {
  1423. fprintf(handle," < %s >\n",subsection);
  1424. return 2;
  1425. }
  1426. static void __NEAR__ __FASTCALL__ out_item(FILE * handle,unsigned nled,const char *_item,const char *value)
  1427. {
  1428. char *sm_char;
  1429. unsigned i;
  1430. sm_char = strchr(value,'%');
  1431. if(sm_char && ifSmarting)
  1432. {
  1433. fprintf(handle,"#nosmart\n");
  1434. }
  1435. for(i = 0;i < nled;i++)
  1436. {
  1437. fprintf(handle," ");
  1438. }
  1439. fprintf(handle,"%s = ",_item);
  1440. fwrite(value,strlen(value),1,handle);
  1441. fprintf(handle,"\n");
  1442. if(sm_char && ifSmarting)
  1443. {
  1444. fprintf(handle,"#smart\n");
  1445. }
  1446. }
  1447. hIniProfile * __FASTCALL__ iniOpenFile(const char *fname,bool *has_error)
  1448. {
  1449. hIniProfile *_ret;
  1450. unsigned fname_size;
  1451. _ret = PMalloc(sizeof(hIniProfile));
  1452. if(has_error) *has_error = true;
  1453. if(_ret)
  1454. {
  1455. fname_size = strlen(fname)+1;
  1456. _ret->fname = PMalloc(fname_size);
  1457. if(_ret->fname) strcpy(_ret->fname,fname);
  1458. else
  1459. {
  1460. PFree(_ret);
  1461. return NULL;
  1462. }
  1463. if(__IsFileExists(_ret->fname)) _ret->handler = FiOpen(fname);
  1464. else _ret->handler = &bNull;
  1465. }
  1466. opening = _ret;
  1467. _ret->flags |= HINI_FULLCACHED;
  1468. _ret->cache = (void *)la_Build(0,sizeof(ini_cache),NULL);
  1469. if(_ret->cache)
  1470. {
  1471. hlFiProgress(_ret,__buildCache);
  1472. _ret->flags &= ~HINI_UPDATED;
  1473. }
  1474. else _ret->flags = 0;
  1475. if(has_error) *has_error = _ret->handler == &bNull;
  1476. return _ret;
  1477. }
  1478. static bool __NEAR__ __FASTCALL__ __flushCache(hIniProfile *ini);
  1479. void __FASTCALL__ iniCloseFile(hIniProfile *ini)
  1480. {
  1481. if(ini)
  1482. {
  1483. if(ini->cache)
  1484. {
  1485. __flushCache(ini);
  1486. __destroyCache((linearArray *)ini->cache);
  1487. }
  1488. if(ini->handler != &bNull) FiClose(ini->handler);
  1489. PFree(ini->fname);
  1490. PFree(ini);
  1491. }
  1492. }
  1493. unsigned __FASTCALL__ iniReadProfileString(hIniProfile *ini,const char *section,const char *subsection,
  1494. const char *_item,const char *def_value,char *buffer,
  1495. unsigned cbBuffer)
  1496. {
  1497. if(!buffer) return 0;
  1498. ret = 1;
  1499. buf_len = cbBuffer;
  1500. buf_ptr = buffer;
  1501. sect = section;
  1502. subsect = subsection;
  1503. item = _item;
  1504. if(cbBuffer) strncpy(buffer,def_value,cbBuffer);
  1505. else buffer[0] = 0;
  1506. if(ini)
  1507. {
  1508. if(ini->handler != &bNull)
  1509. {
  1510. bool v_found;
  1511. v_found = false;
  1512. if(ini->cache)
  1513. {
  1514. ini_cache ic;
  1515. void __HUGE__ *found,__HUGE__ *foundi,__HUGE__ *foundv;
  1516. ini_cache __HUGE__ *fi;
  1517. ic.item = section;
  1518. ic.flags = 0;
  1519. if((found=la_Find(ini->cache,&ic,__full_compare_cache))!=NULL)
  1520. {
  1521. ic.item=subsection;
  1522. fi = (ini_cache __HUGE__ *)found;
  1523. if((foundi=la_Find(fi->v.leaf,&ic,__full_compare_cache))!=NULL)
  1524. {
  1525. ic.item = _item;
  1526. ic.flags = IC_STRING;
  1527. fi = (ini_cache __HUGE__ *)foundi;
  1528. if((foundv=la_Find(fi->v.leaf,&ic,__full_compare_cache))!=NULL)
  1529. {
  1530. fi = (ini_cache __HUGE__ *)foundv;
  1531. strncpy(buffer,fi->v.value,cbBuffer);
  1532. ret = min(strlen(fi->v.value),cbBuffer);
  1533. v_found = true;
  1534. }
  1535. }
  1536. }
  1537. }
  1538. if(!v_found && (ini->flags & HINI_FULLCACHED) != HINI_FULLCACHED) hlFiProgress(ini,MyCallback);
  1539. }
  1540. }
  1541. buffer[cbBuffer-1] = 0;
  1542. return ret;
  1543. }
  1544. #define HINI_HEADER "; This file was generated automatically by BEYELIB.\n; WARNING: Any changes made by hands may be lost the next time you run the program.\n"
  1545. static FILE * __NEAR__ __FASTCALL__ __makeIni(hIniProfile *ini)
  1546. {
  1547. FILE *hout;
  1548. hout = fopen(ini->fname,"wt");
  1549. if(hout != NULL)
  1550. {
  1551. fprintf(hout,HINI_HEADER);
  1552. }
  1553. return hout;
  1554. }
  1555. static bool __NEAR__ __FASTCALL__ __createIni(hIniProfile *ini,
  1556. const char *_section,
  1557. const char *_subsection,
  1558. const char *_item,
  1559. const char *_value)
  1560. {
  1561. FILE *hout;
  1562. unsigned nled;
  1563. bool _ret;
  1564. hout = __makeIni(ini);
  1565. _ret = true;
  1566. if(hout == NULL) _ret = false;
  1567. else
  1568. {
  1569. nled = 0;
  1570. if(_section)
  1571. {
  1572. nled += out_sect(hout,_section);
  1573. }
  1574. if(_subsection)
  1575. {
  1576. nled += out_subsect(hout,_subsection);
  1577. }
  1578. if(_item)
  1579. {
  1580. out_item(hout,nled,_item,_value);
  1581. }
  1582. fclose(hout);
  1583. }
  1584. return _ret;
  1585. }
  1586. static bool __NEAR__ __FASTCALL__ __directWriteProfileString(hIniProfile *ini,
  1587. const char *_section,
  1588. const char *_subsection,
  1589. const char *_item,
  1590. const char *_value)
  1591. {
  1592. FILE * tmphandle;
  1593. char *tmpname, *prev_val;
  1594. char * workstr, *wstr2;
  1595. char *original;
  1596. unsigned nled,prev_val_size;
  1597. bhandle_t hsrc;
  1598. bool _ret,need_write,s_ok,ss_ok,i_ok,done,sb_ok,ssb_ok,written,Cond,if_on;
  1599. /* test for no change of value */
  1600. prev_val_size = strlen(_value)+2;
  1601. prev_val = PMalloc(prev_val_size);
  1602. need_write = true;
  1603. if(!ini) return false;
  1604. if(prev_val && ini->handler != &bNull)
  1605. {
  1606. const char *def_val;
  1607. if(strcmp(_value,"y") == 0) def_val = "n";
  1608. else def_val = "y";
  1609. iniReadProfileString(ini,_section,_subsection,_item,def_val,prev_val,prev_val_size);
  1610. if(strcmp(prev_val,_value) == 0) need_write = false;
  1611. PFree(prev_val);
  1612. }
  1613. if(!need_write) return true;
  1614. tmpname = PMalloc((strlen(ini->fname)+1)*2);
  1615. if(!tmpname) return false;
  1616. if(ini->handler == &bNull) /* if file does not exist make it. */
  1617. {
  1618. _ret = __createIni(ini,_section,_subsection,_item,_value);
  1619. if(_ret) ini->handler = FiOpen(ini->fname);
  1620. goto Exit_WS;
  1621. }
  1622. bioSeek(ini->handler,0L,BIO_SEEK_SET);
  1623. ActiveFile = ini->handler;
  1624. hsrc = make_temp(ini->fname,tmpname);
  1625. if(hsrc == NULL_HANDLE) { _ret = false; goto Exit_WS; }
  1626. __OsClose(hsrc);
  1627. tmphandle = fopen(tmpname,"wt");
  1628. if(tmphandle == NULL) { _ret = false; goto Exit_WS; }
  1629. fprintf(tmphandle,HINI_HEADER);
  1630. workstr = __FiCMaxStr();
  1631. wstr2 = __FiCMaxStr();
  1632. original = __FiCMaxStr();
  1633. if(!workstr || !wstr2 || !original)
  1634. {
  1635. fclose(tmphandle);
  1636. __OsDelete(tmpname);
  1637. if(workstr) PFREE(workstr);
  1638. if(wstr2) PFREE(wstr2);
  1639. if(original) PFREE(original);
  1640. _ret = false;
  1641. goto Exit_WS;
  1642. }
  1643. sb_ok = ssb_ok = s_ok = ss_ok = i_ok = done = false;
  1644. nled = 0;
  1645. if(!_section) { s_ok = sb_ok = true; if(!_subsection) ss_ok = ssb_ok = true; }
  1646. wstr2[0] = 1;
  1647. Cond = true;
  1648. if_on = false;
  1649. while(1)
  1650. {
  1651. written = false;
  1652. FiGetNextString(ini->handler,workstr,FI_MAXSTRLEN,original);
  1653. if(workstr[0] == 0) break;
  1654. if(FiisCommand(workstr))
  1655. {
  1656. char *cstr;
  1657. cstr = __FiCCmd(workstr);
  1658. if(strncmp(cstr,"if",2) == 0 ||
  1659. strncmp(cstr,"elif",4) == 0 ||
  1660. strncmp(cstr,"else",4) == 0 )
  1661. if_on = true;
  1662. if(strncmp(cstr,"endif",5) == 0) if_on = false;
  1663. PFREE(cstr);
  1664. }
  1665. if(Cond)
  1666. {
  1667. if(FiisSection(workstr))
  1668. {
  1669. if(_section)
  1670. {
  1671. FiGetSectionName(workstr,wstr2);
  1672. if(strcmp(_section,wstr2) == 0)
  1673. {
  1674. s_ok = sb_ok = true;
  1675. nled = 2;
  1676. ss_ok = ssb_ok = !_subsection;
  1677. }
  1678. else s_ok = false;
  1679. }
  1680. else s_ok = false;
  1681. }
  1682. else
  1683. if(FiisSubSection(workstr))
  1684. {
  1685. if(_subsection)
  1686. {
  1687. FiGetSubSectionName(workstr,wstr2);
  1688. if(strcmp(_subsection,wstr2) == 0)
  1689. {
  1690. ss_ok = ssb_ok = true;
  1691. nled = 4;
  1692. }
  1693. else ss_ok = false;
  1694. }
  1695. else ss_ok = false;
  1696. }
  1697. else
  1698. if(FiisItem(workstr))
  1699. {
  1700. FiGetItemName(workstr,wstr2);
  1701. if(strcmp(_item,wstr2) == 0) i_ok = true;
  1702. if(i_ok && s_ok && ss_ok)
  1703. {
  1704. if(!done || if_on)
  1705. {
  1706. out_item(tmphandle,nled,_item,_value);
  1707. written = true;
  1708. done = true;
  1709. }
  1710. }
  1711. else i_ok = false;
  1712. }
  1713. /**********************************************/
  1714. if(sb_ok && !s_ok)
  1715. {
  1716. if(!done)
  1717. {
  1718. if(!ssb_ok && !ss_ok && _subsection) { nled += 2; out_subsect(tmphandle,_subsection); }
  1719. out_item(tmphandle,nled,_item,_value);
  1720. written = false;
  1721. done = true;
  1722. }
  1723. }
  1724. if(s_ok && ssb_ok && !ss_ok)
  1725. {
  1726. if(!done)
  1727. {
  1728. out_item(tmphandle,nled,_item,_value);
  1729. written = false;
  1730. done = true;
  1731. }
  1732. }
  1733. }
  1734. if(!written) fprintf(tmphandle,"%s\n",original);
  1735. }
  1736. /************ this is end of loop *************/
  1737. if(!done)
  1738. {
  1739. if(!sb_ok && _section)
  1740. {
  1741. nled = out_sect(tmphandle,_section);
  1742. if(_subsection)
  1743. {
  1744. ssb_ok = true;
  1745. nled+=out_subsect(tmphandle,_subsection);
  1746. }
  1747. }
  1748. if(!ssb_ok && _subsection)
  1749. {
  1750. nled+=out_subsect(tmphandle,_subsection);
  1751. }
  1752. out_item(tmphandle,nled,_item,_value);
  1753. done = true;
  1754. }
  1755. fclose(tmphandle);
  1756. FiClose(ini->handler);
  1757. __OsDelete(ini->fname);
  1758. __OsRename(tmpname,ini->fname);
  1759. ini->handler = FiOpen(ini->fname);
  1760. PFREE(workstr);
  1761. PFREE(wstr2);
  1762. PFREE(original);
  1763. _ret = true;
  1764. Exit_WS:
  1765. PFREE(tmpname);
  1766. return _ret;
  1767. }
  1768. static char *__partSect,*__partSubSect;
  1769. static hIniProfile *part_ini_profile;
  1770. static void __FASTCALL__ part_flush_item(void __HUGE__ *data)
  1771. {
  1772. ini_cache __HUGE__ *it;
  1773. it = (ini_cache __HUGE__ *)data;
  1774. __directWriteProfileString(part_ini_profile,
  1775. __partSect,
  1776. __partSubSect,
  1777. it->item,
  1778. it->v.value);
  1779. }
  1780. static void __FASTCALL__ part_flush_subsect(void __HUGE__ *data)
  1781. {
  1782. ini_cache __HUGE__ *it;
  1783. it = (ini_cache __HUGE__ *)data;
  1784. __partSubSect = it->item;
  1785. la_ForEach(it->v.leaf,part_flush_item);
  1786. }
  1787. static void __FASTCALL__ part_flush_sect(void __HUGE__ *data)
  1788. {
  1789. ini_cache __HUGE__ *it;
  1790. it = (ini_cache __HUGE__ *)data;
  1791. __partSect = it->item;
  1792. la_ForEach(it->v.leaf,part_flush_subsect);
  1793. }
  1794. static void __NEAR__ __FASTCALL__ __flushPartialCache(hIniProfile *ini)
  1795. {
  1796. part_ini_profile = ini;
  1797. la_ForEach((linearArray *)ini->cache,part_flush_sect);
  1798. }
  1799. bool __FASTCALL__ iniWriteProfileString(hIniProfile *ini, const char *_section,
  1800. const char *_subsection,
  1801. const char *_item, const char *_value)
  1802. {
  1803. bool _ret;
  1804. opening = ini;
  1805. _ret = false;
  1806. if(ini->cache)
  1807. {
  1808. if((ini->flags & HINI_FULLCACHED) != HINI_FULLCACHED) goto flush_it;
  1809. if(__addCache(_section,_subsection,_item,_value) != 0)
  1810. {
  1811. flush_it:
  1812. __flushPartialCache(ini);
  1813. __destroyCache((linearArray *)ini->cache);
  1814. ini->cache = 0;
  1815. goto do_def;
  1816. }
  1817. }
  1818. else
  1819. {
  1820. do_def:
  1821. _ret = __directWriteProfileString(ini,_section,_subsection,_item,_value);
  1822. }
  1823. return _ret;
  1824. }
  1825. static int __nled;
  1826. static FILE * flush_handler = NULL;
  1827. static void __FASTCALL__ flush_item(void __HUGE__ *data)
  1828. {
  1829. ini_cache __HUGE__ *it;
  1830. it = (ini_cache __HUGE__ *)data;
  1831. out_item(flush_handler,__nled,it->item,it->v.value);
  1832. }
  1833. static void __FASTCALL__ flush_subsect(void __HUGE__ *data)
  1834. {
  1835. ini_cache __HUGE__ *it;
  1836. int _has_led;
  1837. it = (ini_cache __HUGE__ *)data;
  1838. _has_led = __nled;
  1839. if(strlen(it->item)) __nled += out_subsect(flush_handler,it->item);
  1840. la_ForEach(it->v.leaf,flush_item);
  1841. __nled = _has_led;
  1842. }
  1843. static void __FASTCALL__ flush_sect(void __HUGE__ *data)
  1844. {
  1845. ini_cache __HUGE__ *it;
  1846. it = (ini_cache __HUGE__ *)data;
  1847. __nled = 0;
  1848. if(strlen(it->item)) __nled += out_sect(flush_handler,it->item);
  1849. la_ForEach(it->v.leaf,flush_sub

Large files files are truncated, but you can click here to view the full file