[Chicken-users] another proposal to modify runtime.c
I can't resist to propose another minor code improvement. For this one I even recall where I learned the trick: early in my CS studies, we been taken to analyse how we could do better than the straight forward implementation of double linked lists. (Which would be the implementation of e.g., the finalizer_list in runtime.c) The idea is: unlinking requires too many conditionals. The solution would be: you don't want to keep a pointer to the list elements (which in case of the empty list would be NULL) as root. Instead you use a static list node (thereby wasting the unused memory for the payload). As end-of-list marker you don't use NULL, but the address of that root node. You initialize the root nodes previous and next to the address of the root node. Now you can save all those conditionals. Unlinking is turned into two straight forward updates of the previous and next pointers handing on the corresponding fields of the node. Saves a few line, conditional and looks IMHO more clever. Though I'm biased by the abovementioned history. Find the diff attached. /Jörg Index: runtime.c === --- runtime.c +++ runtime.c @@ -441,11 +441,11 @@ pending_finalizer_count, callback_returned_flag; static C_TLS WEAK_TABLE_ENTRY *weak_item_table; static C_TLS C_GC_ROOT *gc_root_list = NULL; static C_TLS FINALIZER_NODE - *finalizer_list, + finalizer_list, *finalizer_free_list, **pending_finalizer_indices; static C_TLS void *current_module_handle; static C_TLS int flonum_print_precision = FLONUM_PRINT_PRECISION; static C_TLS HDUMP_BUCKET **hdump_table; @@ -638,11 +638,11 @@ if((weak_item_table = (WEAK_TABLE_ENTRY *)C_calloc(WEAK_TABLE_SIZE, sizeof(WEAK_TABLE_ENTRY))) == NULL) return 0; } /* Initialize finalizer lists: */ - finalizer_list = NULL; + finalizer_list.next = finalizer_list.previous = finalizer_list; finalizer_free_list = NULL; pending_finalizer_indices = (FINALIZER_NODE **)C_malloc(C_max_pending_finalizers * sizeof(FINALIZER_NODE *)); if(pending_finalizer_indices == NULL) return 0; @@ -2802,11 +2802,11 @@ if(gc_report_flag) C_dbg(C_text(GC), C_text(%d finalized item(s) still pending\n), j); j = fcount = 0; - for(flist = finalizer_list; flist != NULL; flist = flist-next) { + for(flist = finalizer_list.next; flist != finalizer_list; flist = flist-next) { mark(flist-item); mark(flist-finalizer); ++fcount; } @@ -2820,19 +2820,19 @@ } else { j = fcount = 0; /* move into pending */ - for(flist = finalizer_list; flist != NULL; flist = flist-next) { + for(flist = finalizer_list.next; flist != finalizer_list; flist = flist-next) { if(j C_max_pending_finalizers) { if(!is_fptr(C_block_header(flist-item))) pending_finalizer_indices[ j++ ] = flist; } } /* mark */ - for(flist = finalizer_list; flist != NULL; flist = flist-next) { + for(flist = finalizer_list.next; flist != finalizer_list; flist = flist-next) { mark(flist-item); mark(flist-finalizer); } /* mark finalizable GC roots: */ @@ -2864,14 +2864,12 @@ for(i = 0; i pending_finalizer_count; ++i) { flist = pending_finalizer_indices[ i ]; C_set_block_item(last, 1 + i * 2, flist-item); C_set_block_item(last, 2 + i * 2, flist-finalizer); - if(flist-previous != NULL) flist-previous-next = flist-next; - else finalizer_list = flist-next; - - if(flist-next != NULL) flist-next-previous = flist-previous; + flist-previous-next = flist-next; + flist-next-previous = flist-previous; flist-next = finalizer_free_list; flist-previous = NULL; finalizer_free_list = flist; --live_finalizer_count; @@ -3232,11 +3230,11 @@ /* Mark locative table: */ for(i = 0; i locative_table_count; ++i) remark(locative_table[ i ]); /* Mark finalizer table: */ - for(flist = finalizer_list; flist != NULL; flist = flist-next) { + for(flist = finalizer_list.next; flist != finalizer_list; flist = flist-next) { remark(flist-item); remark(flist-finalizer); } /* Mark weakly held items: */ @@ -8097,15 +8095,14 @@ else { flist = finalizer_free_list; finalizer_free_list = flist-next; } - if(finalizer_list != NULL) finalizer_list-previous = flist; - - flist-previous = NULL; - flist-next = finalizer_list; - finalizer_list = flist; + flist-next = finalizer_list; + flist-previous = finalizer_list.previous; + finalizer_list.previous-next = flist; + finalizer_list.previous = flist; if(C_in_stackp(x)) C_mutate(flist-item, x); else flist-item = x; if(C_in_stackp(proc)) C_mutate(flist-finalizer, proc); @@ -8118,14 +8115,14 @@ int C_do_unregister_finalizer(C_word x) { int n; FINALIZER_NODE *flist; - for(flist = finalizer_list; flist != NULL; flist = flist-next) { + for(flist = finalizer_list.next; flist != finalizer_list; flist = flist-next) { if(flist-item == x) { -
[Chicken-users] severe bug in file-exists?
Hi all. I have just lost some files (fortunately, they can be restored somehow) because file-exists? returned #f for large files ( 2 GB). Version: CHICKEN (c)2008-2011 The Chicken Team (c)2000-2007 Felix L. Winkelmann Version 4.7.4 (rev b6eba65) linux-unix-gnu-x86 [ manyargs dload ] compiled 2011-09-23 on sem11 (Linux) This is a 32bit build on a 64bit machine. (Same for 4.7.0) Ciao Sven ___ Chicken-users mailing list Chicken-users@nongnu.org https://lists.nongnu.org/mailman/listinfo/chicken-users
Re: [Chicken-users] severe bug in file-exists?
* Sven Hartrumpf hartru...@gmx.net [110928 14:57]: Hi all. I have just lost some files (fortunately, they can be restored somehow) because file-exists? returned #f for large files ( 2 GB). I am sorry to hear that. This seems to be an issue with 32bit chickens. Thanks for the report, I hope the data is not lost completely. I have files bug #706 in the tracker. https://bugs.call-cc.org/ticket/706 Kind regards, Christian -- Who can (make) the muddy water (clear)? Let it be still, and it will gradually become clear. Who can secure the condition of rest? Let movement go on, and the condition of rest will gradually arise. -- Lao Tse. ___ Chicken-users mailing list Chicken-users@nongnu.org https://lists.nongnu.org/mailman/listinfo/chicken-users
Re: [Chicken-users] severe bug in file-exists?
Hi Christian. Wed, 28 Sep 2011 15:10:46 +0200, ckeen wrote: I have just lost some files I hope the data is not lost completely. No, it can be recovered automatically :-) I have filed bug #706 in the tracker. https://bugs.call-cc.org/ticket/706 Thanks for filing the bug. Looking at the report, I see that file-exists? returns the file name if the file exists. This violates R7RS and R6RS, does not it? Sven ___ Chicken-users mailing list Chicken-users@nongnu.org https://lists.nongnu.org/mailman/listinfo/chicken-users
Re: [Chicken-users] severe bug in file-exists?
* Sven Hartrumpf hartru...@gmx.net [110928 15:38]: Hi Christian. Wed, 28 Sep 2011 15:10:46 +0200, ckeen wrote: I have just lost some files I hope the data is not lost completely. No, it can be recovered automatically :-) I have filed bug #706 in the tracker. https://bugs.call-cc.org/ticket/706 Thanks for filing the bug. Looking at the report, I see that file-exists? returns the file name if the file exists. This violates R7RS and R6RS, does not it? As I see it, this procedure needs an overhaul anyway. If fstat fails it returns #f regardless the reason. On IRC we have been comming to the understanding that we should raise an I/O exception for all other cases (if the fstat fails for other reasons than the file not being there). What does R7RS specify there? -- Who can (make) the muddy water (clear)? Let it be still, and it will gradually become clear. Who can secure the condition of rest? Let movement go on, and the condition of rest will gradually arise. -- Lao Tse. ___ Chicken-users mailing list Chicken-users@nongnu.org https://lists.nongnu.org/mailman/listinfo/chicken-users
Re: [Chicken-users] severe bug in file-exists?
Wed, 28 Sep 2011 15:40:57 +0200, ckeen wrote: As I see it, this procedure needs an overhaul anyway. If fstat fails it returns #f regardless the reason. On IRC we have been coming to the understanding that we should raise an I/O exception for all other cases (if the fstat fails for other reasons than the file not being there). What does R7RS specify there? Nothing, just this: (file-exists? filename) Filename must be a string. The file-exists? procedure returns #t if the named file exists at the time the procedure is called, #f otherwise. Sven ___ Chicken-users mailing list Chicken-users@nongnu.org https://lists.nongnu.org/mailman/listinfo/chicken-users
Re: [Chicken-users] another proposal to modify runtime.c
On Wed, Sep 28, 2011 at 01:41:03PM +0200, Jörg F. Wittenberger wrote: I can't resist to propose another minor code improvement. For this one I even recall where I learned the trick: early in my CS studies, we been taken to analyse how we could do better than the straight forward implementation of double linked lists. (Which would be the implementation of e.g., the finalizer_list in runtime.c) The idea is: unlinking requires too many conditionals. The solution would be: you don't want to keep a pointer to the list elements (which in case of the empty list would be NULL) as root. Instead you use a static list node (thereby wasting the unused memory for the payload). As end-of-list marker you don't use NULL, but the address of that root node. You initialize the root nodes previous and next to the address of the root node. Now you can save all those conditionals. Unlinking is turned into two straight forward updates of the previous and next pointers handing on the corresponding fields of the node. Saves a few line, conditional and looks IMHO more clever. Though I'm biased by the abovementioned history. Find the diff attached. /Jörg I've heard this called a dummy head list. I didn't think people wrote linked list code any other way... You use one extra cons cell and remove all the beginning of list checks you'd otherwise require. I thought this part came standard. ;-) Good catch. It's a trick I've been able to use well outside of C programming. Heck, I think my egg, genturfahi, uses this one somewhere. -Alan -- .i ma'a lo bradi cu penmi gi'e du ___ Chicken-users mailing list Chicken-users@nongnu.org https://lists.nongnu.org/mailman/listinfo/chicken-users
Re: [Chicken-users] severe bug in file-exists?
2011/9/28 Christian Kellermann ck...@pestilenz.org: [...] As I see it, this procedure needs an overhaul anyway. If fstat fails it returns #f regardless the reason. [...] Hello, while it is true that only an ENOENT errno indicates a missing path component in any file system operation, I also wonder why on earth anyone would want to use fstat to check for the existence of a file? To use fstat you first have to open the file, but if it can be opened, it clearly exists and calling fstat at all is redundant. However, if it cannot be opened, a large variety of reasons other than nonexistence of the file can be responsible. Calling stat instead of fstat and checking for an ENOENT errno would be an option, but if one is only interested in the existence of the file it looks like overkill to me to collect all the metainformation about the file and then throw it away. I would say that the canonical way to check for file existence is calling access with the candidate path as first argument and the mode F_OK as second argument and checking for an ENOENT errno. Ciao, Thomas -- When C++ is your hammer, every problem looks like your thumb. ___ Chicken-users mailing list Chicken-users@nongnu.org https://lists.nongnu.org/mailman/listinfo/chicken-users
Re: [Chicken-users] another proposal to modify runtime.c
Jörg F. Wittenberger scripsit: One consideration is: as it is now, it works quite well. But I see more simplifications ahead. Maybe it's the best to integrate the well tested state of affairs now and have me tampering later. Yes, please take this alternative. Nothing should get integrated that is not already well-tested. -- John Cowan co...@ccil.org http://www.ccil.org/~cowan Most people are much more ignorant about language than they are about [other subjects], but they reckon that because they can talk and read and write, their opinions about talking and reading and writing are as well informed as anybody's. And since I have DNA, I'm entitled to carry on at length about genetics without bothering to learn anything about it. Not. --Mark Liberman ___ Chicken-users mailing list Chicken-users@nongnu.org https://lists.nongnu.org/mailman/listinfo/chicken-users
Re: [Chicken-users] severe bug in file-exists?
Sven Hartrumpf scripsit: (file-exists? filename) Filename must be a string. The file-exists? procedure returns #t if the named file exists at the time the procedure is called, #f otherwise. Since nothing is said about exceptions, you are free to throw one if you cannot determine the answer. I agree that access() is the Right Thing here. -- Henry S. Thompson said, / Syntactic, structural, John Cowan Value constraints we / Express on the fly. co...@ccil.org Simon St. Laurent: Your / Incomprehensible http://www.ccil.org/~cowan Abracadabralike / schemas must die! ___ Chicken-users mailing list Chicken-users@nongnu.org https://lists.nongnu.org/mailman/listinfo/chicken-users
[Chicken-users] EINTR with self-pipe signal trampoline
Below is a test case for a problem I'm seeing in some multi-process code I'm writing. I'm getting the error: Error: (file-read) cannot read from file - Interrupted system call because a signal handler is going off while my main thread is in an iowait state. In C, I have always handled this by manually restarting a system call when EINTR is called. In my attached test case, I'm trying to use SA_RESTART in sigaction(2) for the same affect, and that isn't working for me. Does that actually work? I'm trying to determine which direction to head in to fix this problem, and I was surprised that SA_RESTART didn't work. Will one of you with access to a linux machine try running this code? Both in the version as seen here and also run uncommenting the two foreign-code lines. This code might have bugs that prevent it from running as intended--I'm not able to test past my EINTR problem. I'm now planning on patching file-read and file-write to restart on EINTR, unless someone has a better idea! Can I catch this exception at runtime? -Alan PS: this code is using this trick: http://cr.yp.to/docs/selfpipe.html ++ eintr.scm ;;; ;;; self-pipe signal trampoline. ;;; ;;; this test case should: ;;; ;;; * register SIGUSR1 and SIGCHLD as signal trampolines using the ;;; self-pipe trick. ;;; * spawn a child process which: ;;; - sends SIGUSR1 to the parent. ;;; - enters an iowait state forever. (to be killed by our ;;; parent) ;;; * simultaneously, in the parent: ;;; - we perform a blocking read on our self-pipe, and wait for ;;; one of two signals: ;;; SIGUSR1: send SIGTERM to our child process ;;; SIGCHLD: call wait and then exit ourselves. ;;; ;;; Instead, file-read is called and enters a blocking state. Our ;;; signal is raised, causing file-read to return EINTR. Normally, ;;; one would restart the syscall. I'm not sure how one does this ;;; in Chicken Scheme, or if you can. ;;; ;;; Even deferring to a C implementation of the signal trampoline ;;; which properly sets SA_RESTART does not seem to help. ;;; (use posix) ; restart system calls on EINTR. ; (foreign-declare #EOS #include sys/types.h #include unistd.h #include signal.h #include errno.h void trampoline(int signum) { char b[1]; int saved_errno=errno; b[0] = (char)(unsigned)signum; /* hack: I know my output pipe fd in this test case. */ write(5, b[0], 1); errno=saved_errno; } void register_trampoline(int signum) { struct sigaction new, old; int r; new.sa_handler = trampoline; new.sa_flags = SA_RESTART; sigemptyset(new.sa_mask); /* hack: ignoring the return value */ r = sigaction(signum, new, old); } EOS ) (call-with-values create-pipe (lambda (input-pipe output-pipe) ; signal handler. write the signal received to our self-pipe. ; (define (trampoline signum) (file-write output-pipe (string (integer-char signum ; helper routine to read a single (unbuffered) byte and convert ; it to an integer (here representing a signal number). ; (define (read1 fd) (char-integer (string-ref (car (file-read input-pipe 1)) 0))) (define (child) ; close our parent's self-pipe (file-close input-pipe) (file-close output-pipe) ; and reset (not technically true, but another bug not ; relevant to this test case) our signal handlers. ; (set-signal-handler! signal/usr1 #f) (set-signal-handler! signal/chld #f) ; send our parent SIGUSR1, which should result in ; our parent sending us a SIGTERM. ; (process-signal (parent-process-id) signal/usr1) (call-with-values create-pipe (lambda (input-pipe output-pipe) ; pause (iowait) until we get our SIGTERM. ; (read1 input-pipe) ; never actually executed. ; (file-close input-pipe) (file-close output-pipe) (exit 0 (define (parent pid) (case (read1 input-pipe) ((signal/usr1) (process-signal pid) (parent pid)) ((signal/chld) (process-wait pid ; register our signal trampoline ; (set-signal-handler! signal/usr1 trampoline) (set-signal-handler! signal/chld trampoline) ; or, register our signal trampoline. ; ; uncomment these lines to test SA_RESTART ; ;(foreign-code register_trampoline(SIGUSR1);) ;(foreign-code register_trampoline(SIGCHLD);) ; fork our child and do event handling. ; (let ((pid (process-fork))) (case pid ((0) (child)) (else (parent pid)) -- -- .i ma'a lo bradi cu penmi gi'e du ___ Chicken-users mailing list Chicken-users@nongnu.org https://lists.nongnu.org/mailman/listinfo/chicken-users
Re: [Chicken-users] two minor tweaks to runtime.c
On Wed, Sep 28, 2011 at 4:29 AM, Alan Post alanp...@sunflowerriver.org wrote: I don't have enough data to say that it matters in this case, but in principle it surely does. In theory, theory and practice are the same. In practice, they're different. The problem here specifically is the lack of data. Why even bother with a change like this without benchmark results to prove it's worth it (preferably tested across all the variety of platforms Chicken compiles on, with wildly differing branch prediction features)? The proper way to optimize is: 1) DON'T! Just write an application. If it's too slow for your purposes, then move on to 2) Profile. Find out where all the time is being spent. There's no point in optimizing something if it's not a significant factor in you performance. 3) Of the code sections you've determined the most time is being spent in, choose the one with the best estimated speedup-to-effort ratio. You should have an intuition that the code in question can be improved, either algorithmically (potential huge speedup) or by tuning (smaller speedup, usually uglier code, but may be less effort). Making this choice is something of an art, but is completely impossible without 2. 4) Write benchmarks that isolate what you want to optimize. Measure how fast the current solution is, if possible compared to alternative implementations or equivalent tasks in other languages. 5) If you don't already have a test suite, write one now that verifies the code used in the benchmark. It's too easy to write an optimized version of something that performs better initially, but worse once you fix the bugs in it. 6) Try one or more optimizations, and measure them compared to the result in 4 once they've passed the tests in 5. Iterate as often as you have time/ideas. 7) Of the best results in 6, determine if the speedup they introduce is worth the complexity they introduce. Keep in mind the maintenance cost will persist long term, and be shared by other people who want to work on the code. 8) Document what you tried regardless so people don't waste the same effort again! Include a one-line comment in the code itself with a link to more info if needed, e.g. ;; The following is a little ugly, but performs best in ;; practice - see benchmarks/widget-hack.scm. 9) Send a patch to the list with the benchmarks and tests as proof that the optimization is worth it. If you've come this far, the maintainers will almost certainly accept it. -- Alex ___ Chicken-users mailing list Chicken-users@nongnu.org https://lists.nongnu.org/mailman/listinfo/chicken-users
Re: [Chicken-users] two minor tweaks to runtime.c
Will you show me this data for the current implementation? -Alan On Thu, Sep 29, 2011 at 10:30:00AM +0900, Alex Shinn wrote: On Wed, Sep 28, 2011 at 4:29 AM, Alan Post alanp...@sunflowerriver.org wrote: I don't have enough data to say that it matters in this case, but in principle it surely does. In theory, theory and practice are the same. In practice, they're different. The problem here specifically is the lack of data. Why even bother with a change like this without benchmark results to prove it's worth it (preferably tested across all the variety of platforms Chicken compiles on, with wildly differing branch prediction features)? The proper way to optimize is: 1) DON'T! Just write an application. If it's too slow for your purposes, then move on to 2) Profile. Find out where all the time is being spent. There's no point in optimizing something if it's not a significant factor in you performance. 3) Of the code sections you've determined the most time is being spent in, choose the one with the best estimated speedup-to-effort ratio. You should have an intuition that the code in question can be improved, either algorithmically (potential huge speedup) or by tuning (smaller speedup, usually uglier code, but may be less effort). Making this choice is something of an art, but is completely impossible without 2. 4) Write benchmarks that isolate what you want to optimize. Measure how fast the current solution is, if possible compared to alternative implementations or equivalent tasks in other languages. 5) If you don't already have a test suite, write one now that verifies the code used in the benchmark. It's too easy to write an optimized version of something that performs better initially, but worse once you fix the bugs in it. 6) Try one or more optimizations, and measure them compared to the result in 4 once they've passed the tests in 5. Iterate as often as you have time/ideas. 7) Of the best results in 6, determine if the speedup they introduce is worth the complexity they introduce. Keep in mind the maintenance cost will persist long term, and be shared by other people who want to work on the code. 8) Document what you tried regardless so people don't waste the same effort again! Include a one-line comment in the code itself with a link to more info if needed, e.g. ;; The following is a little ugly, but performs best in ;; practice - see benchmarks/widget-hack.scm. 9) Send a patch to the list with the benchmarks and tests as proof that the optimization is worth it. If you've come this far, the maintainers will almost certainly accept it. -- Alex ___ Chicken-users mailing list Chicken-users@nongnu.org https://lists.nongnu.org/mailman/listinfo/chicken-users -- .i ma'a lo bradi cu penmi gi'e du ___ Chicken-users mailing list Chicken-users@nongnu.org https://lists.nongnu.org/mailman/listinfo/chicken-users
Re: [Chicken-users] two minor tweaks to runtime.c
On Thu, Sep 29, 2011 at 12:09:19PM +0900, Alex Shinn wrote: On Thu, Sep 29, 2011 at 11:40 AM, Alan Post alanp...@sunflowerriver.org wrote: Will you show me this data for the current implementation? The first implementation doesn't need to justify itself, just be working. *nods* How did irregex, which by account is slower, replace the existing regex code? -Alan -- .i ma'a lo bradi cu penmi gi'e du ___ Chicken-users mailing list Chicken-users@nongnu.org https://lists.nongnu.org/mailman/listinfo/chicken-users
Re: [Chicken-users] two minor tweaks to runtime.c
On Thu, Sep 29, 2011 at 12:25 PM, Alan Post alanp...@sunflowerriver.org wrote: How did irregex, which by account is slower, replace the existing regex code? I didn't make the call, but as I understand that was motivated by portability concerns, simplifying the Chicken distribution, and avoiding the frequently occurring memory bugs in PCRE. So speed wasn't a concern, but there is a class of regexps for which irregex is exponentially faster than PCRE. -- Alex ___ Chicken-users mailing list Chicken-users@nongnu.org https://lists.nongnu.org/mailman/listinfo/chicken-users
Re: [Chicken-users] two minor tweaks to runtime.c
On Thu, Sep 29, 2011 at 12:33:41PM +0900, Alex Shinn wrote: On Thu, Sep 29, 2011 at 12:25 PM, Alan Post alanp...@sunflowerriver.org wrote: How did irregex, which by account is slower, replace the existing regex code? I didn't make the call, but as I understand that was motivated by portability concerns, simplifying the Chicken distribution, and avoiding the frequently occurring memory bugs in PCRE. So speed wasn't a concern, but there is a class of regexps for which irregex is exponentially faster than PCRE. -- Alex Thank you Alex. I understand, between all of this, that the bar is raised on smaller changes (and it probably ought to be, it's easier to bike shed a smaller change) but that usefully disruptive changes can be larger and require a lower burden of proof for inclusion. For the dubious purpose of pedantic completeness, This conversation does not include any proof of your second paragraph: that these exponentially faster regexps come up in practice: there's no citation of data or test cases to back up such an assertion. I did, for the first time this week, use a feature of irregex that was more than straightforward translation of a regex into irregex syntax. It was a light-bulb moment for me, as I was previously using irregex as a drop-in replacement and not appreciating it, for what I suspect are all the reason you're motivated to participate in this conversation. . -Alan -- .i ma'a lo bradi cu penmi gi'e du ___ Chicken-users mailing list Chicken-users@nongnu.org https://lists.nongnu.org/mailman/listinfo/chicken-users
Re: [Chicken-users] two minor tweaks to runtime.c
On 28/09/11 11:33 PM, Alex Shinn wrote: On Thu, Sep 29, 2011 at 12:25 PM, Alan Postalanp...@sunflowerriver.org wrote: How did irregex, which by account is slower, replace the existing regex code? I didn't make the call, but as I understand that was motivated by portability concerns, simplifying the Chicken distribution, and avoiding the frequently occurring memory bugs in PCRE. So speed wasn't a concern, but there is a class of regexps for which irregex is exponentially faster than PCRE. And if I am not mistaken this rationale is nicely given by Russ Cox: http://swtch.com/~rsc/regexp/regexp1.html --Toby ___ Chicken-users mailing list Chicken-users@nongnu.org https://lists.nongnu.org/mailman/listinfo/chicken-users
[Chicken-users] difference between ##sys#error and posix-error?
Looking at posixunix.scm, I find that some error messages are produced with ##sys#error, and others with posix-error. What distinguishes these two routines? Why would I use one but not the other? -Alan -- .i ma'a lo bradi cu penmi gi'e du ___ Chicken-users mailing list Chicken-users@nongnu.org https://lists.nongnu.org/mailman/listinfo/chicken-users