Branch: Tag:

1996-12-15

1996-12-15 15:51:09 by Fredrik Hübinette (Hubbe) <hubbe@hubbe.net>

more tests: for sockets

Rev: src/modules/files/socktest.pike:1.1

27:      </doc>   </docgroup> + <docgroup homogen-name='SETJMP' homogen-type='method'> + <method name='SETJMP'/><doc placeholder='true'> + <text> + <p><tt>SETJMP</tt> - catch errors</p> +  + <tt><p>#include "error.h"<br/> +  + </p> + <p>int SETJMP(JMP_BUF <i>buf</i>);<br/> + </p> + </tt> + <p>These macros are wrappers to the setjmp/longjmp routines with some + added support for cleaning up the Pike stack and other things that + might need freeing. What SETJUMP does is that it lets you catch + Pike errors much like the Pike function catch(). When called, + SETJMP returns zero, so the 'failsafe' code is executed. If an error + occurs in that code the processor will jump directly to the SETJMP + again and it will return 'true'. Then the 'error' code will be + executed.</p> + </text> +  + <group><note/><text> + <p>SETJMP is a macro + </p> + <p>'buf' has to be a local variable + </p> + <p>There are some limitations to how you can use local variables in the + same function as setjump/longjump. See setjup(3) for more details.</p> + </text></group> +  + <group><example/><text> + <tt><p>#include "error.h"<br/> +  + </p> + <p>void do_catch()<br/> + {<br/> + <dl><group><text>JMP_BUF buf;<br/> + </text></group></dl> + </p> + <p><dl><group><text>if(SETJMP(buf)) {<br/> + <dl><group><text>/* An error / longjump occured */<br/> + </text></group></dl>} else {<br/> + <dl><group><text>/* Execute failsafe code here */<br/> + </text></group></dl>}<br/> + </text></group></dl> + </p> + <p><dl><group><text>UNSETJMP(foo)<br/> + </text></group></dl>}<br/> + </p> + </tt> + error_handling</text></group> +  + <group><seealso/><text> + <p><ref resolved='c::throw' to='throw'>throw</ref>, <ref resolved='c::error' to='error'>error</ref>, <ref resolved='c::UNSETJMP' to='UNSETJMP'>UNSETJMP</ref>, <ref resolved='c::SET_ONERROR' to='SET_ONERROR'>SET_ONERROR</ref> and <ref resolved='c::UNSET_ONERROR' to='UNSET_ONERROR'>UNSET_ONERROR</ref></p> + </text></group> +  + </doc> + </docgroup> + <docgroup homogen-name='SET_ONERROR' homogen-type='method'> + <method name='SET_ONERROR'/><doc placeholder='true'> + <text> + <p><tt>SET_ONERROR</tt> - call this function if an error occurs</p> +  + <tt><p>#include "error.h"<br/> +  + </p> + <p>void SET_ONERROR(ONERROR <i>tmp</i>, void (*func)(<i>void</i> *), void *<i>arg</i>);<br/> + </p> + </tt> + <p>This function sets an error handler to be called when an error + occurs. When an error occurs the function 'func' is called with + the argument 'arg'. The advantage of this method over using SETJMP + for cleanup handling is that this should be slightly faster and it + does not have problems with undefined local variables.</p> + </text> +  + <group><note/><text> + <p>SET_ONERROR is a macro + </p> + <p>'tmp' has to be a local variable.</p> + </text></group> +  + <group><example/><text> + <tt><p>#include "error.h"<br/> + #include "memory.h"<br/> +  + </p> + <p>void do_something()<br/> + {<br/> + <dl><group><text>ONERROR tmp;<br/> + char *mem=xalloc(4711);<br/> + </text></group></dl> + </p> + <p><dl><group><text>SET_ONERROR(tmp, (void (*)(void *)) free, mem);<br/> + </text></group></dl> + </p> + <p><dl><group><text>/* Do some code that might cause an Pike error */<br/> + </text></group></dl> + </p> + <p><dl><group><text>UNSET_ONERROR(tmp);<br/> + </text></group></dl>}<br/> + </p> + </tt> + error_handling</text></group> +  + <group><seealso/><text> + <p><ref resolved='c::UNSET_ONERROR' to='UNSET_ONERROR'>UNSET_ONERROR</ref> and <ref resolved='c::error' to='error'>error</ref></p> + </text></group> +  + </doc> + </docgroup> + <docgroup homogen-name='UNSETJMP' homogen-type='method'> + <method name='UNSETJMP'/><doc placeholder='true'> + <text> + <p><tt>UNSETJMP</tt> - stop catching error</p> +  + <p>This macro cleans up after calling SETJMP. See the page for SETJMP + for more details.</p> +  + error_handling</text> +  + <group><seealso/><text> + <p><ref resolved='c::SETJMP' to='SETJMP'>SETJMP</ref></p> + </text></group> +  + </doc> + </docgroup> + <docgroup homogen-name='UNSET_ONERROR' homogen-type='method'> + <method name='UNSET_ONERROR'/><doc placeholder='true'> + <text> + <p><tt>UNSET_ONERROR</tt> - cleanup after an SET_ONERROR</p> +  + <p>This function cleans up after a SET_ONERROR call. + See SET_ONERROR for more details.</p> +  + error_handling</text> +  + <group><seealso/><text> + <p><ref resolved='c::SET_ONERROR' to='SET_ONERROR'>SET_ONERROR</ref> and <ref resolved='c::SETJMP' to='SETJMP'>SETJMP</ref></p> + </text></group> +  + </doc> + </docgroup>   <docgroup homogen-name='add_function' homogen-type='method'>   <method name='add_function'/><doc placeholder='true'>   <text>
420:      </doc>   </docgroup> + <docgroup homogen-name='data_types' homogen-type='method'> + <method name='data_types'/><doc placeholder='true'> + <text> + <p><tt>data_types</tt> - Pike internal data types</p> +  + <p>Of course the Pike source uses a lot of data types except for those + that represents mappings, arrays, strings etc. Callbacks, stack frames + and type fields are just the beginning.</p> +  + internals</text> +  + </doc> + </docgroup>   <docgroup homogen-name='end_c_program' homogen-type='method'>   <method name='end_c_program'/><doc placeholder='true'>   <text>
505:   the C function lonjump and continues executing from the most   resent active catch() call.</p>    + error_handling</text> +  + <group><seealso/><text> + <p><ref resolved='c::SET_ONERROR' to='SET_ONERROR'>SET_ONERROR</ref>, <ref resolved='c::fatal' to='fatal'>fatal</ref> and <ref resolved='c::throw' to='throw'>throw</ref></p> + </text></group> +  + </doc> + </docgroup> + <docgroup homogen-name='error_handling' homogen-type='method'> + <method name='error_handling'/><doc placeholder='true'> + <text> + <p><tt>error_handling</tt> - how to error handling works inside Pike</p> +  + <p>Error handling in Pike is implemented with the setjmp/longjmp + functionality. This means that functions that can cause errors + will NOT return if an error occurs. Special care has to be taken + so that no memory is left unfreed if an error occurs. Almost all + functions that can cause Pike code to be executed can cause an + error. Also functions that implements Pike operators / functions + can cause errors. If you are paranoid you should assume that all + functions can cause errors. You may also read the code for the + function to see if there are any calls to error() in it. If the + function is documented in this manual, it will say if the function + can cause errors.</p> +    internals</text>      </doc>
527:   bug with a debugger. Use with extreme caution, an error() might   sometimes be a lot better...</p>    - internal</text> + error_handling</text>      <group><seealso/><text>   <p><ref resolved='c::error' to='error'>error</ref></p>
585:   </matrix>   </text></group></dl></text></group></dl></p>    - internals</text> + data_types</text>      </doc>   </docgroup>
681:      </doc>   </docgroup> + <docgroup homogen-name='hashmem' homogen-type='method'> + <method name='hashmem'/><doc placeholder='true'> + <text> + <p><tt>hashmem</tt> - hash a memory region</p> +  + <tt><p>#include "memory.h"<br/> +  + </p> + <p>unsigned INT32 hashmem(const unsigned char *<i>a</i>,INT32 <i>len</i>,INT32 <i>mlen</i>);<br/> + </p> + </tt> + <p>This function looks at the memory region beginning at 'a' and is 'len' + bytes long and returns a hash value depending on the bytes in that + region. The argument 'mlen' is how many bytes it should actually look + at, larger mlen gives better values but slower hashing.</p> +  + low_level</text> +  + </doc> + </docgroup> + <docgroup homogen-name='init_memsearch' homogen-type='method'> + <method name='init_memsearch'/><doc placeholder='true'> + <text> + <p><tt>init_memsearch</tt> - initialize a memory search struct</p> +  + <tt><p>#include "memory.h"<br/> +  + </p> + <p><matrix> + <r><c> void init_memsearch(struct mem_searcher *s, </c></r> + <r><c> </c><c> </c><c> char *needle, SIZE_T needlelen, SIZE_T max_haystacklen); </c></r> + </matrix> + </p> + </tt> + <p>This function initializes a struct mem_searcher to be used with + the function memory_search. 'needle' is the byte sequence to + search for, and needlelen is how many bytes long the 'needle' is. + The argument 'max_haystacklen' is an approximation of how much + this memory searcher will be used. More time will be spent optimizing + the memory searcher struct if max_haystacklen is large.</p> + </text> +  + <group><note/><text> + <p>The needle is not copied by this function. It must still be available + when memory_search is called.</p> +  + low_level</text></group> +  + <group><seealso/><text> + <p><ref resolved='c::memory_search' to='memory_search'>memory_search</ref></p> + </text></group> +  + </doc> + </docgroup>   <docgroup homogen-name='is_eq' homogen-type='method'>   <method name='is_eq'/><doc placeholder='true'>   <text>
754:      </doc>   </docgroup> + <docgroup homogen-name='low_level' homogen-type='method'> + <method name='low_level'/><doc placeholder='true'> + <text> + <p><tt>low_level</tt> - low level routines supplied by pike</p> +  + <p>These functions are here to help you write fast and portable modules. + Pike itself also uses them for the same purpose.</p> +  + internals</text> +  + </doc> + </docgroup>   <docgroup homogen-name='low_mapping_lookup' homogen-type='method'>   <method name='low_mapping_lookup'/><doc placeholder='true'>   <text>
1014:      </doc>   </docgroup> + <docgroup homogen-name='memory_search' homogen-type='method'> + <method name='memory_search'/><doc placeholder='true'> + <text> + <p><tt>memory_search</tt> - search memory for a sequence of bytes</p> +  + <tt><p><matrix> + <r><c> #include "memory.h" </c></r> + <r><c> </c></r> + <r><c> char *memory_search(struct mem_searcher *s, </c></r> + <r><c> </c><c> </c><c> char *haystack, SIZE_T haystacklen); </c></r> + </matrix> + </p> + </tt> + <p>This function searches through a memory region (called 'haystack') + for a sequence of bytes (called 'needle'). If found, a pointer to + the first occurance of 'needle' in 'haystack' is returned. The needle + is given by calling init_memsearch to initialize a struct mem_searcher + that can then be used with this function.</p> +  + low_level</text> +  + <group><seealso/><text> + <p><ref resolved='c::init_memsearch' to='init_memsearch'>init_memsearch</ref></p> + </text></group> +  + </doc> + </docgroup>   <docgroup homogen-name='mkmapping' homogen-type='method'>   <method name='mkmapping'/><doc placeholder='true'>   <text>
1170:      </doc>   </docgroup> + <docgroup homogen-name='reorder' homogen-type='method'> + <method name='reorder'/><doc placeholder='true'> + <text> + <p><tt>reorder</tt> - re-order an array of memory blocks</p> +  + <tt><p>#include "memory.h"<br/> +  + </p> + <p>void reorder(char *<i>memory</i>, INT32 <i>nitems</i>, INT32 <i>size</i>,INT32 *<i>order</i>);<br/> + </p> + </tt> + <p>This function takes an array of memory blocks and re-organizes them + according to the argument 'order'. 'nitems' tells how many memory + blocks there are, and 'size' tells how big they are in bytes. + 'order' is simply an array of INT32 of size 'nitems' in which each + int tells which memory block from 'memory' should be placed in that + position. In pseudo code, this could be written as: + </p> + <p>mem_copy=copy_memory(memory);<br/> + for(int e=0;e&lt;nitems;e++)<br/> + <dl><group><text>memory[e]=mem_copy[order[e]];<br/> + </text></group></dl></p> +  + low_level</text> +  + </doc> + </docgroup>   <docgroup homogen-name='resize_array' homogen-type='method'>   <method name='resize_array'/><doc placeholder='true'>   <text>
1196:      </doc>   </docgroup> + <docgroup homogen-name='set_close_on_exec' homogen-type='method'> + <method name='set_close_on_exec'/><doc placeholder='true'> + <text> + <p><tt>set_close_on_exec</tt> - set the close-on-exec flag on a filedescriptor</p> +  + <tt><p>#include "fd_control.h"<br/> +  + </p> + <p>void set_close_on_exec(int fd, int onoff)<br/> + </p> + </tt> + <p>This function sets the close-on-exec flag on a filedescriptor. If + onoff is true, the filedescriptor will be closed whenever an exec() + is executed. If it is false, the fildescriptor will remain open.</p> +  + low_level</text> +  + <group><seealso/><text> + <p><ref resolved='c::set_nonblocking' to='set_nonblocking'>set_nonblocking</ref></p> + </text></group> +  + </doc> + </docgroup>   <docgroup homogen-name='set_exit_callback' homogen-type='method'>   <method name='set_exit_callback'/><doc placeholder='true'>   <text>
1246:      </doc>   </docgroup> + <docgroup homogen-name='set_nonblocking' homogen-type='method'> + <method name='set_nonblocking'/><doc placeholder='true'> + <text> + <p><tt>set_nonblocking</tt> - set a filedescriptor nonblocking</p> +  + <tt><p>#include "fd_control.h"<br/> +  + </p> + <p>void set_nonblocking(int fd, int onoff)<br/> + </p> + </tt> + <p>This function sets a filedescriptor in nonblocking mode. Nonblocking + mode means that any read() or write() exits insteads of waits when + no more data can be read/written immediately. If 'onoff' is true, + the fd will be set to nonblocking, otherwise it will be set to + blocking mode.</p> +  + low_level</text> +  + <group><seealso/><text> + <p><ref resolved='c::set_close_on_exec' to='set_close_on_exec'>set_close_on_exec</ref></p> + </text></group> +  + </doc> + </docgroup> + <docgroup homogen-name='set_read_callback' homogen-type='method'> + <method name='set_read_callback'/><doc placeholder='true'> + <text> + <p><tt>set_read_callback</tt> - set 'data available' callback</p> +  + <tt><p>#include "backend.h"<br/> +  + </p> + <p>void set_read_callback(int <i>fd</i>,file_callback <i>cb</i>,void *<i>data</i>);<br/> + </p> + </tt> + <p>This function sets what function should be called when there is + more data to be read from 'fd'. The 'file_callback' should be a + function like this: + </p> + <p>void file_callback(int fd, void *data); + </p> + <p>The arguments are the same as sent to set_read_callback(). + To disable the read callback, call set_read_callback again with + cb and data equal to zero.</p> +  + low_level</text> +  + <group><seealso/><text> + <p><ref to='set_write_callback'>set_write_callback</ref> and <ref resolved='c::set_nonblocking' to='set_nonblocking'>set_nonblocking</ref></p> + </text></group> +  + </doc> + </docgroup> + <docgroup homogen-name='set_read_callback' homogen-type='method'> + <method name='set_read_callback'/><doc placeholder='true'> + <text> + <p><tt>set_read_callback</tt> - set 'buffer available' callback</p> +  + <tt><p>#include "backend.h"<br/> +  + </p> + <p>void set_write_callback(int <i>fd</i>,file_callback <i>cb</i>,void *<i>data</i>);<br/> + </p> + </tt> + <p>This function sets what function should be called when there is + time to write more data to 'fd'. The 'file_callback' should be a + function like this: + </p> + <p>void file_callback(int fd, void *data); + </p> + <p>The arguments are the same as sent to set_write_callback(). + To disable the write callback, call set_write_callback again with + cb and data equal to zero.</p> +  + low_level</text> +  + <group><seealso/><text> + <p><ref resolved='c::set_read_callback' to='set_read_callback'>set_read_callback</ref> and <ref resolved='c::set_nonblocking' to='set_nonblocking'>set_nonblocking</ref></p> + </text></group> +  + </doc> + </docgroup>   <docgroup homogen-name='slice_array' homogen-type='method'>   <method name='slice_array'/><doc placeholder='true'>   <text>
1369:      </doc>   </docgroup> + <docgroup homogen-name='throw' homogen-type='method'> + <method name='throw'/><doc placeholder='true'> + <text> + <p><tt>throw</tt> - throw an exception</p> +  + <tt><p>#include "error.h"<br/> +  + </p> + <p>int throw(void);<br/> + </p> + </tt> + <p>This function calls longjmp and does all the cleanup and popping + the Pike stack etc. etc. This function does not setup any error + message or backtrace like error() does. error() calls this function + after doing all that. Since this function calls longjmp, it does + not return. See SETJMP for more details.</p> +  + error_handling</text> +  + <group><seealso/><text> + <p><ref resolved='c::SETJMP' to='SETJMP'>SETJMP</ref> and <ref resolved='c::error' to='error'>error</ref></p> + </text></group> +  + </doc> + </docgroup>   <docgroup homogen-name='type_field' homogen-type='method'>   <method name='type_field'/><doc placeholder='true'>   <text>
1384:   too many bits though. It seldom pays off to calculate the bit field   explicitly, so if you don't know what types are involved you should   use -1 for the type field.</p> - </text> +     -  + data_types</text> +    <group><seealso/><text>   <p><ref resolved='c::mapping' to='mapping'>mapping</ref>, <ref resolved='c::array' to='array'>array</ref> and <ref resolved='c::svalue' to='svalue'>svalue</ref></p>   </text></group>
1424:   <p>The &amp; and ! operators work as you might expect but are only useful   together.</p>    - internals</text> + data_types</text>      <group><seealso/><text>   <p><ref resolved='c::add_function' to='add_function'>add_function</ref> and <ref to='add_efun'>add_efun</ref></p>
1432:      </doc>   </docgroup> + <docgroup homogen-name='xalloc' homogen-type='method'> + <method name='xalloc'/><doc placeholder='true'> + <text> + <p><tt>xalloc</tt> - fail-safe memory allocation</p> +  + <tt><p>#include "memory.h"<br/> +  + </p> + <p>char *xalloc(long <i>size</i>);<br/> + </p> + </tt> + <p>This function works exactly like the malloc() function, it will + never return NULL. Instead it will try to free up any pike resources + that are not needed any longer and try again. If that doesn't work + either it will call fatal("out of memory\n"); and Pike will dump core. + This type of error handling makes it easier to code, but is not + always what you want.</p> +  + low_level</text> +  + </doc> + </docgroup>   </namespace>   <namespace name='cpp'>   <doc placeholder='true'>