Subversion Repositories Kolibri OS

Rev

Rev 845 | Rev 988 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;================================================================================================;;
  2. ;;//// libini.asm //// (c) mike.dld, 2006-2008 ///////////////////////////////////////////////////;;
  3. ;;================================================================================================;;
  4. ;;                                                                                                ;;
  5. ;; This file is part of Common development libraries (Libs-Dev).                                  ;;
  6. ;;                                                                                                ;;
  7. ;; Libs-Dev is free software: you can redistribute it and/or modify it under the terms of the GNU ;;
  8. ;; General Public License as published by the Free Software Foundation, either version 3 of the   ;;
  9. ;; License, or (at your option) any later version.                                                ;;
  10. ;;                                                                                                ;;
  11. ;; Libs-Dev is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without  ;;
  12. ;; even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU  ;;
  13. ;; General Public License for more details.                                                       ;;
  14. ;;                                                                                                ;;
  15. ;; You should have received a copy of the GNU General Public License along with Libs-Dev. If not, ;;
  16. ;; see <http://www.gnu.org/licenses/>.                                                            ;;
  17. ;;                                                                                                ;;
  18. ;;================================================================================================;;
  19. ;;                                                                                                ;;
  20. ;; 2008-08-06 (mike.dld)                                                                          ;;
  21. ;;   changes:                                                                                     ;;
  22. ;;     - split private procs into libini_p.asm, added comments                                    ;;
  23. ;; 2008-02-07 (mike.dld)                                                                          ;;
  24. ;;   changes:                                                                                     ;;
  25. ;;     - renamed all *.aux.* to *._.* to match overall libraries design                           ;;
  26. ;; 2007-09-26 (mike.dld)                                                                          ;;
  27. ;;   bug-fixes:                                                                                   ;;
  28. ;;     - value was not correctly trimmed (reported by diamond)                                    ;;
  29. ;; 2007-08-01 (mike.dld)                                                                          ;;
  30. ;;   bug-fixes:                                                                                   ;;
  31. ;;     - serious defect in ini.set_str causing displaced write operations                         ;;
  32. ;;       (reported by diamond)                                                                    ;;
  33. ;;     - another serious defect in ini.enum_keys introduced with refactoring                      ;;
  34. ;;   changes:                                                                                     ;;
  35. ;;     - callback for enum_keys now takes additional parameter - key value                        ;;
  36. ;;     - handling trailing spaces in section/key/value                                            ;;
  37. ;; 2007-05-19 (mike.dld)                                                                          ;;
  38. ;;   bug-fixes:                                                                                   ;;
  39. ;;     - last char still wasn't read correctly                                                    ;;
  40. ;;     - digits of number were reversed when using ini.set_int                                    ;;
  41. ;;     - now using 'ini.aux.unget_char' instead of dangerous 'dec esi'                            ;;
  42. ;;   changes:                                                                                     ;;
  43. ;;     - all non-public functions now start with ini.aux.*                                        ;;
  44. ;;     - added ini.enum_sections and ini.enum_keys                                                ;;
  45. ;;     - removed ini.query_sec (use ini.enum_* instead)                                           ;;
  46. ;;                                                                                                ;;
  47. ;;================================================================================================;;
  48.  
  49. format MS COFF
  50.  
  51. public @EXPORT as 'EXPORTS'
  52.  
  53. include '../../../../proc32.inc'
  54. include '../../../../macros.inc'
  55. include '../libio/libio.inc'
  56. purge section ; mov,add,sub
  57.  
  58. include 'libini_p.inc'
  59.  
  60. section '.flat' code readable align 16
  61.  
  62. include 'libini_p.asm'
  63.  
  64. ;;================================================================================================;;
  65. proc ini.enum_sections _f_name, _callback ;///////////////////////////////////////////////////////;;
  66. ;;------------------------------------------------------------------------------------------------;;
  67. ;? Enumerate sections, calling callback function for each of them                                 ;;
  68. ;;------------------------------------------------------------------------------------------------;;
  69. ;> _f_name = ini filename <asciiz>                                                                ;;
  70. ;> _callback = callback function address: func(f_name, sec_name), where                           ;;
  71. ;>   f_name = ini filename (as passed to the function) <asciiz>                                   ;;
  72. ;>   sec_name = section name found <asciiz>                                                       ;;
  73. ;;------------------------------------------------------------------------------------------------;;
  74. ;< eax = -1 (error) / 0                                                                           ;;
  75. ;;================================================================================================;;
  76. locals
  77.   f       IniFile
  78.   f_addr  dd ?
  79.   sec_buf dd ?
  80. endl
  81.  
  82.         push    ebx esi edi
  83.  
  84.         cld
  85.  
  86.         invoke  mem.alloc, ini.MAX_NAME_LEN
  87.         or      eax, eax
  88.         jz      .exit_error.2
  89.         mov     [sec_buf], eax
  90.  
  91.         xor     eax, eax
  92.         mov     [f.fh], eax
  93.         mov     [f.buf], eax
  94.         invoke  file.open, [_f_name], O_READ
  95.         cmp     eax, 32
  96.         jb      .exit_error
  97.         mov     [f.fh], eax
  98.         invoke  mem.alloc, ini.MEM_SIZE
  99.         or      eax, eax
  100.         jz      .exit_error
  101.         mov     [f.buf], eax
  102.         lea     ebx, [f]
  103.         mov     [f_addr], ebx
  104.  
  105.         invoke  file.seek, [f.fh], 0, SEEK_SET
  106.         stdcall libini._.preload_block, [f_addr]
  107.  
  108.   .next_section:
  109.         stdcall libini._.find_next_section, [f_addr]
  110.         or      eax, eax
  111.         jnz     .exit_error
  112.  
  113.         stdcall libini._.get_char, [f_addr]
  114.         stdcall libini._.skip_spaces, [f_addr]
  115. ;       inc     esi
  116. ;       dec     [f.cnt]
  117.         mov     edi, [sec_buf]
  118.     @@: stdcall libini._.get_char, [f_addr]
  119.         cmp     al, ']'
  120.         je      @f
  121.         or      al, al
  122.         jz      .exit_ok
  123.         cmp     al, 13
  124.         je      .next_section
  125.         cmp     al, 10
  126.         je      .next_section
  127.         stosb
  128.         jmp     @b
  129.     @@: xor     al, al
  130.         stosb
  131.         add     edi, -2
  132.     @@: cmp     byte[edi], 32
  133.         ja      @f
  134.         mov     byte[edi], 0
  135.         dec     edi
  136.         jmp     @b
  137.     @@:
  138.         pushad
  139.         mov     eax, [f_addr]
  140.         stdcall [_callback], [_f_name], [sec_buf]
  141.         or      eax, eax
  142.         popad
  143.         jnz     .next_section
  144.  
  145.   .exit_ok:
  146.         invoke  file.close, [f.fh]
  147.         invoke  mem.free, [f.buf]
  148.         invoke  mem.free, [sec_buf]
  149.         xor     eax, eax
  150.         pop     edi esi ebx
  151.         ret
  152.  
  153.   .exit_error:
  154.         invoke  file.close, [f.fh]
  155.         invoke  mem.free, [f.buf]
  156.         invoke  mem.free, [sec_buf]
  157.   .exit_error.2:
  158.         or      eax, -1
  159.         pop     edi esi ebx
  160.         ret
  161. endp
  162.  
  163. ;;================================================================================================;;
  164. proc ini.enum_keys _f_name, _sec_name, _callback ;////////////////////////////////////////////////;;
  165. ;;------------------------------------------------------------------------------------------------;;
  166. ;? Enumerate keys within a section, calling callback function for each of them                    ;;
  167. ;;------------------------------------------------------------------------------------------------;;
  168. ;> _f_name = ini filename <asciiz>                                                                ;;
  169. ;> _sec_name = section name <asciiz>                                                              ;;
  170. ;> _callback = callback function address: func(f_name, sec_name, key_name, key_value), where      ;;
  171. ;>   f_name = ini filename (as passed to the function) <asciiz>                                   ;;
  172. ;>   sec_name = section name (as passed to the function) <asciiz>                                 ;;
  173. ;>   key_name = key name found <asciiz>                                                           ;;
  174. ;>   key_value = value of key found <asciiz>                                                      ;;
  175. ;;------------------------------------------------------------------------------------------------;;
  176. ;< eax = -1 (error) / 0                                                                           ;;
  177. ;;================================================================================================;;
  178. locals
  179.   f       IniFile
  180.   f_addr  dd ?
  181.   key_buf dd ?
  182.   val_buf dd ?
  183. endl
  184.  
  185.         push    ebx esi edi
  186.  
  187.         cld
  188.  
  189.         invoke  mem.alloc, ini.MAX_NAME_LEN
  190.         or      eax, eax
  191.         jz      .exit_error.3
  192.         mov     [key_buf], eax
  193.         invoke  mem.alloc, ini.MAX_VALUE_LEN
  194.         or      eax, eax
  195.         jz      .exit_error.2
  196.         mov     [val_buf], eax
  197.  
  198.         xor     eax, eax
  199.         mov     [f.fh], eax
  200.         mov     [f.buf], eax
  201.         invoke  file.open, [_f_name], O_READ
  202.         cmp     eax, 32
  203.         jb      .exit_error
  204.         mov     [f.fh], eax
  205.         invoke  mem.alloc, ini.MEM_SIZE
  206.         or      eax, eax
  207.         jz      .exit_error
  208.         mov     [f.buf], eax
  209.         lea     ebx, [f]
  210.         mov     [f_addr], ebx
  211.         stdcall libini._.find_section, ebx, [_sec_name]
  212.         or      eax, eax
  213.         jnz     .exit_error
  214.  
  215.   .next_key:
  216.         stdcall libini._.skip_line, [f_addr]
  217.         stdcall libini._.skip_nonblanks, [f_addr]
  218.         or      al, al
  219.         jz      .exit_error
  220.         cmp     al, '['
  221.         je      .exit_error
  222.         mov     edi, [key_buf]
  223.     @@: stdcall libini._.get_char, [f_addr]
  224.         or      al, al
  225.         jz      .exit_error
  226.         cmp     al, '='
  227.         je      @f
  228.         stosb
  229.         jmp     @b
  230.     @@:
  231.         xor     al, al
  232.         stosb
  233.         add     edi, -2
  234.     @@: cmp     byte[edi], 32
  235.         ja      @f
  236.         mov     byte[edi], 0
  237.         dec     edi
  238.         jmp     @b
  239.     @@: stdcall libini._.low.read_value, [f_addr], [val_buf], ini.MAX_VALUE_LEN
  240.         pushad
  241.         stdcall [_callback], [_f_name], [_sec_name], [key_buf], [val_buf]
  242.         or      eax, eax
  243.         popad
  244.         jnz     .next_key
  245.  
  246.     @@: invoke  file.close, [f.fh]
  247.         invoke  mem.free, [f.buf]
  248.         xor     eax, eax
  249.         stosb
  250.         pop     edi esi ebx
  251.         ret
  252.  
  253.   .exit_error:
  254.         invoke  file.close, [f.fh]
  255.         invoke  mem.free, [f.buf]
  256.         invoke  mem.free, [val_buf]
  257.   .exit_error.2:
  258.         invoke  mem.free, [key_buf]
  259.   .exit_error.3:
  260.         or      eax, -1
  261.         pop     edi esi ebx
  262.         ret
  263. endp
  264.  
  265. ;;================================================================================================;;
  266. proc ini.get_str _f_name, _sec_name, _key_name, _buffer, _buf_len, _def_val ;/////////////////////;;
  267. ;;------------------------------------------------------------------------------------------------;;
  268. ;? Read string                                                                                    ;;
  269. ;;------------------------------------------------------------------------------------------------;;
  270. ;> _f_name = ini filename <asciiz>                                                                ;;
  271. ;> _sec_name = section name <asciiz>                                                              ;;
  272. ;> _key_name = key name <asciiz>                                                                  ;;
  273. ;> _buffer = destination buffer address <byte*>                                                   ;;
  274. ;> _buf_len = buffer size (maximum bytes to read) <dword>                                         ;;
  275. ;> _def_val = default value to return if no key, section or file found <asciiz>                   ;;
  276. ;;------------------------------------------------------------------------------------------------;;
  277. ;< eax = -1 (error) / 0                                                                           ;;
  278. ;< [_buffer] = [_def_val] (error) / found key value <asciiz>                                      ;;
  279. ;;================================================================================================;;
  280. locals
  281.   f      IniFile
  282.   f_addr dd ?
  283. endl
  284.  
  285.         push    ebx esi edi
  286.  
  287.         xor     eax, eax
  288.         mov     [f.fh], eax
  289.         mov     [f.buf], eax
  290.         invoke  file.open, [_f_name], O_READ
  291.         cmp     eax, 32
  292.         jb      .exit_error
  293.         mov     [f.fh], eax
  294.         invoke  mem.alloc, ini.MEM_SIZE
  295.         or      eax, eax
  296.         jz      .exit_error
  297.         mov     [f.buf], eax
  298.         lea     ebx, [f]
  299.         mov     [f_addr], ebx
  300.         stdcall libini._.find_section, ebx, [_sec_name]
  301.         or      eax, eax
  302.         jnz     .exit_error
  303.  
  304.         stdcall libini._.find_key, ebx, [_key_name]
  305.         or      eax, eax
  306.         jnz     .exit_error
  307.  
  308.         stdcall libini._.low.read_value, [f_addr], [_buffer], [_buf_len]
  309. ;       mov     edi, [_buffer]
  310. ;   @@: dec     [_buf_len]
  311. ;       jz      @f
  312. ;       stdcall ini.aux.get_char, [f_addr]
  313. ;       or      al, al
  314. ;       jz      @f
  315. ;       cmp     al, 13
  316. ;       je      @f
  317. ;       cmp     al, 10
  318. ;       je      @f
  319. ;       stosb
  320. ;       jmp     @b
  321.     @@: invoke  file.close, [f.fh]
  322.         invoke  mem.free, [f.buf]
  323.         xor     eax, eax
  324.         stosb
  325.         pop     edi esi ebx
  326.         ret
  327.  
  328.   .exit_error:
  329.         invoke  file.close, [f.fh]
  330.         invoke  mem.free, [f.buf]
  331.         mov     esi, [_def_val]
  332.         mov     edi, [_buffer]
  333.     @@: lodsb
  334.         stosb
  335.         or      al, al
  336.         jnz     @b
  337.         or      eax, -1
  338.         pop     edi esi ebx
  339.         ret
  340. endp
  341.  
  342. ;;================================================================================================;;
  343. proc ini.set_str _f_name, _sec_name, _key_name, _buffer, _buf_len ;///////////////////////////////;;
  344. ;;------------------------------------------------------------------------------------------------;;
  345. ;? Write string                                                                                   ;;
  346. ;;------------------------------------------------------------------------------------------------;;
  347. ;> _f_name = ini filename <asciiz>                                                                ;;
  348. ;> _sec_name = section name <asciiz>                                                              ;;
  349. ;> _key_name = key name <asciiz>                                                                  ;;
  350. ;> _buffer = source buffer address <byte*>                                                        ;;
  351. ;> _buf_len = buffer size (bytes to write) <dword>                                                ;;
  352. ;;------------------------------------------------------------------------------------------------;;
  353. ;< eax = -1 (error) / 0                                                                           ;;
  354. ;;================================================================================================;;
  355. locals
  356.   f      IniFile
  357.   f_addr dd ?
  358. endl
  359.  
  360.         push    ebx esi edi
  361.  
  362.         xor     eax, eax
  363.         mov     [f.fh], eax
  364.         mov     [f.buf], eax
  365.         invoke  file.open, [_f_name], O_READ + O_WRITE + O_CREATE
  366.         cmp     eax, 32
  367.         jb      .exit_error
  368.         mov     [f.fh], eax
  369.         invoke  mem.alloc, ini.MEM_SIZE
  370.         or      eax, eax
  371.         jz      .exit_error
  372.         mov     [f.buf], eax
  373.         lea     ebx, [f]
  374.         mov     [f_addr], ebx
  375.  
  376.         stdcall libini._.find_section, ebx, [_sec_name]
  377.         or      eax, eax
  378.         jnz     .create_section
  379.  
  380.         stdcall libini._.find_key, ebx, [_key_name]
  381.         or      eax, eax
  382.         jnz     .create_key
  383.  
  384.   .modify_key:
  385.         stdcall libini._.get_value_length, [f_addr]
  386.         sub     eax, [_buf_len]
  387.         stdcall libini._.shift_content, [f_addr], eax
  388.  
  389.   .modify_key.ex:
  390.         invoke  file.tell, [f.fh]
  391.         sub     eax, [f.cnt]
  392. ;       dec     eax
  393.         invoke  file.seek, [f.fh], eax, SEEK_SET
  394.         invoke  file.write, [f.fh], [_buffer], [_buf_len]
  395.  
  396.         pop     edi esi ebx
  397.         xor     eax, eax
  398.         ret
  399.  
  400.   .create_key:
  401.         mov     edi, [f.buf]
  402.         add     edi, ini.BLOCK_SIZE
  403.         push    edi
  404.  
  405.   .create_key.ex:
  406. ;       mov     word[edi], 0x0A0D
  407. ;       add     edi,2
  408.         mov     esi, [_key_name]
  409.         call    libini._.string_copy
  410.         mov     byte[edi], '='
  411.         inc     edi
  412.         mov     esi, [_buffer]
  413.         mov     ecx, [_buf_len]
  414.         rep     movsb
  415.         mov     word[edi], 0x0A0D
  416.         add     edi, 2
  417.         mov     eax, edi
  418.  
  419.         pop     edi
  420.         sub     eax, edi
  421.         mov     [_buffer], edi
  422.         mov     [_buf_len], eax
  423.         neg     eax
  424.         stdcall libini._.shift_content, [f_addr], eax
  425.  
  426.         jmp     .modify_key.ex
  427.  
  428.   .create_section:
  429.         mov     edi, [f.buf]
  430.         add     edi, ini.BLOCK_SIZE
  431.         push    edi
  432.  
  433.         mov     esi, [_sec_name]
  434. ;       mov     dword[edi], 0x0A0D + ('[' shl 16)
  435. ;       add     edi, 3
  436.         mov     byte[edi], '['
  437.         inc     edi
  438.         call    libini._.string_copy
  439. ;       mov     byte[edi], ']'
  440. ;       inc     edi
  441.         mov     dword[edi], ']' + (0x0A0D shl 8)
  442.         add     edi, 3
  443.  
  444.         jmp     .create_key.ex
  445.  
  446.   .exit_error:
  447.         pop     edi esi ebx
  448.         or      eax, -1
  449.         ret
  450. endp
  451.  
  452. ;;================================================================================================;;
  453. proc ini.get_int _f_name, _sec_name, _key_name, _def_val ;////////////////////////////////////////;;
  454. ;;------------------------------------------------------------------------------------------------;;
  455. ;? Read integer                                                                                   ;;
  456. ;;------------------------------------------------------------------------------------------------;;
  457. ;> _f_name = ini filename <asciiz>                                                                ;;
  458. ;> _sec_name = section name <asciiz>                                                              ;;
  459. ;> _key_name = key name <asciiz>                                                                  ;;
  460. ;> _def_val = default value to return if no key, section or file found <dword>                    ;;
  461. ;;------------------------------------------------------------------------------------------------;;
  462. ;< eax = [_def_val] (error) / found key value <dword>                                             ;;
  463. ;;================================================================================================;;
  464. locals
  465.   f      IniFile
  466.   f_addr dd ?
  467. endl
  468.  
  469.         push    ebx esi edi
  470.  
  471.         xor     eax, eax
  472.         mov     [f.fh], eax
  473.         mov     [f.buf], eax
  474.         invoke  file.open, [_f_name], O_READ
  475.         cmp     eax, 32
  476.         jb      .exit_error
  477.         mov     [f.fh], eax
  478.         invoke  mem.alloc, ini.MEM_SIZE
  479.         or      eax, eax
  480.         jz      .exit_error
  481.         mov     [f.buf], eax
  482.         lea     ebx, [f]
  483.         mov     [f_addr], ebx
  484.         stdcall libini._.find_section, ebx, [_sec_name]
  485.         or      eax, eax
  486.         jnz     .exit_error
  487.  
  488.         stdcall libini._.find_key, ebx, [_key_name]
  489.         or      eax, eax
  490.         jnz     .exit_error
  491.  
  492.         stdcall libini._.skip_nonblanks, [f_addr]
  493.         xor     eax, eax
  494.         xor     ebx, ebx
  495.         xor     edx, edx
  496.         stdcall libini._.get_char, [f_addr]
  497.         cmp     al, '-'
  498.         jne     .lp1
  499.         inc     bh
  500.     @@: stdcall libini._.get_char, [f_addr]
  501.   .lp1: cmp     al, '0'
  502.         jb      @f
  503.         cmp     al, '9'
  504.         ja      @f
  505.         inc     bl
  506.         add     eax, -'0'
  507.         imul    edx, 10
  508.         add     edx, eax
  509.         jmp     @b
  510.     @@:
  511.         or      bl, bl
  512.         jz      .exit_error
  513.         or      bh, bh
  514.         jz      @f
  515.         neg     edx
  516.     @@: invoke  file.close, [f.fh]
  517.         invoke  mem.free, [f.buf]
  518.         mov     eax, edx
  519.         pop     edi esi ebx
  520.         ret
  521.  
  522.   .exit_error:
  523.         invoke  file.close, [f.fh]
  524.         invoke  mem.free, [f.buf]
  525.         mov     eax, [_def_val]
  526.         pop     edi esi ebx
  527.         ret
  528. endp
  529.  
  530. ;;================================================================================================;;
  531. proc ini.set_int _f_name, _sec_name, _key_name, _val ;////////////////////////////////////////////;;
  532. ;;------------------------------------------------------------------------------------------------;;
  533. ;? Write integer                                                                                  ;;
  534. ;;------------------------------------------------------------------------------------------------;;
  535. ;> _f_name = ini filename <asciiz>                                                                ;;
  536. ;> _sec_name = section name <asciiz>                                                              ;;
  537. ;> _key_name = key name <asciiz>                                                                  ;;
  538. ;> _val = value <dword>                                                                           ;;
  539. ;;------------------------------------------------------------------------------------------------;;
  540. ;< eax = -1 (error) / 0                                                                           ;;
  541. ;;================================================================================================;;
  542. locals
  543.   buf rb 16
  544. endl
  545.  
  546.         push    ecx edx edi
  547.  
  548.         lea     edi, [buf]
  549.         add     edi, 15
  550.         mov     eax, [_val]
  551.         or      eax, eax
  552.         jns     @f
  553.         mov     byte[edi], '-'
  554.         neg     eax
  555.         inc     edi
  556.     @@: mov     ecx, 10
  557.     @@: xor     edx, edx
  558.         idiv    ecx
  559.         add     dl, '0'
  560.         mov     [edi], dl
  561.         dec     edi
  562.         or      eax, eax
  563.         jnz     @b
  564.         lea     eax, [buf]
  565.         add     eax, 15
  566.         sub     eax, edi
  567.         inc     edi
  568.  
  569.         stdcall ini.set_str, [_f_name], [_sec_name], [_key_name], edi, eax
  570.  
  571.         pop     edi edx ecx
  572.         ret
  573. endp
  574.  
  575.  
  576. ;;================================================================================================;;
  577. ;;////////////////////////////////////////////////////////////////////////////////////////////////;;
  578. ;;================================================================================================;;
  579. ;! Imported functions section                                                                     ;;
  580. ;;================================================================================================;;
  581. ;;////////////////////////////////////////////////////////////////////////////////////////////////;;
  582. ;;================================================================================================;;
  583.  
  584.  
  585. align 16
  586. @IMPORT:
  587.  
  588. library \
  589.         libio , 'libio.obj'
  590.  
  591. import  libio                       , \
  592.         file.size   , 'file.size'   , \
  593.         file.open   , 'file.open'   , \
  594.         file.read   , 'file.read'   , \
  595.         file.write  , 'file.write'  , \
  596.         file.seek   , 'file.seek'   , \
  597.         file.eof?   , 'file.eof?'   , \
  598.         file.seteof , 'file.seteof' , \
  599.         file.tell   , 'file.tell'   , \
  600.         file.close  , 'file.close'
  601.  
  602.  
  603. ;;================================================================================================;;
  604. ;;////////////////////////////////////////////////////////////////////////////////////////////////;;
  605. ;;================================================================================================;;
  606. ;! Exported functions section                                                                     ;;
  607. ;;================================================================================================;;
  608. ;;////////////////////////////////////////////////////////////////////////////////////////////////;;
  609. ;;================================================================================================;;
  610.  
  611.  
  612. align 16
  613. @EXPORT:
  614.  
  615. export                                            \
  616.         libini._.init     , 'lib_init'          , \
  617.         0x00040005        , 'version'           , \
  618.         ini.enum_sections , 'ini.enum_sections' , \
  619.         ini.enum_keys     , 'ini.enum_keys'     , \
  620.         ini.get_str       , 'ini.get_str'       , \
  621.         ini.get_int       , 'ini.get_int'       , \
  622.         ini.set_str       , 'ini.set_str'       , \
  623.         ini.set_int       , 'ini.set_int'
  624.