I am always very happy to see these types of libraries. I try to take
the time to look each of these personal toolkits and feel strongly that
we need to establish a "standard" library for things that just about
every C programmer does in every project.
For a library attributed to comp.lang.c I would expect the following
features:
ANSI
tested very thuroughly
reentrant
well designed interfaces
consistent
only ubiquitous ADTs, algorithms, and functions
no assumptions about coding style, tool chain, or environment
free (preferably public domain)
I have a couple of questions though:
Why is GNU autoconf being used if the code is ANSI?
Why does libclc define it's own error codes? What libclc function could
possibly return CLC_ENODEV? If a platform does not have ISO C and POSIX
error codes available there is probably a reason for it.
I have some other issues that are more subtle and somewhat opinionated
so I will not discuss them in the detail but permit me to make an
observation. I have looked at many libraries like this (libtc, kazlib,
dlib, ossp, ...) and one thing that immediately discourages me is
the assumption by the author(s) that their library will be the basis
around which applications will be built (e.g. glib). This is invariably
true for the author and exactly the opposite of the truth for everyone
else. It would be very thoughtful of the authors to make each module
stand-alone. Meaning I would like to be able to copy src/linkedlist.{c,h}
into my tree, add the .o to the Makefile (or IDE) and go.
Finally, there was some discussion about whether or not it would be
necessary to write new code or if several implementations would be
examined and the best one chosen for inclusion. By attributing the
library with the 'clc' acronym I would assmue that this code would be
scrutinized very thoroughly making this question irrelevant. I will
always cherish the experience I had here on clc writing a stack ADT
as a learning example. Many people contributed to the discussion, the
resulting code was small, clean, ANSI, and it defined the style that
I use today. If I saw that level of interaction for a linkedlist, CSV
parser, etc I would be delighted to contribute in any way I can.
Mike
--
A program should be written to model the concepts of the task it
performs rather than the physical world or a process because this
maximizes the potential for it to be applied to tasks that are
conceptually similar and, more important, to tasks that have not
yet been conceived.
> For a library attributed to comp.lang.c I would expect the following
> features:
>
> ANSI
Yup.
> tested very thuroughly
> reentrant
> well designed interfaces
> consistent
We'll do our best. Feel free to help.
> only ubiquitous ADTs, algorithms, and functions
Don't know. Hopefully it will only contain stuff that the majority of
the people who discuss the library think will be useful.
> no assumptions about coding style,
Not sure what you mean here.
> tool chain, or environment
Right.
> free (preferably public domain)
Free. BSD license. Unless someone has a strong objection and
manages to convince enough people. My guess is that an objection
would just lead to a fruitless holy war, though.
> Why is GNU autoconf being used if the code is ANSI?
I believe that if it's used, it will only be used to discover possible
optimizations. The library should work if compiled without autoconf.
> Why does libclc define it's own error codes?
Because ANSI C only defines two error codes: EDOM and ERANGE. That's
the only error codes libclc functions could set if we were to stick to
portable error codes. We don't know if we'll need more, but we want to
be sure a function _can_ report other errors if it wants to.
Note that C library functions called by libclc may set other error codes
(dependent on the platform), so unless libclc overrides these it will
return other system error codes than EDOM and ERANGE.
> one thing that immediately discourages me is
> the assumption by the author(s) that their library will be the basis
> around which applications will be built (e.g. glib). This is invariably
> true for the author and exactly the opposite of the truth for everyone
> else. It would be very thoughtful of the authors to make each module
> stand-alone. Meaning I would like to be able to copy src/linkedlist.{c,h}
> into my tree, add the .o to the Makefile (or IDE) and go.
I don't see why it's a problem to build and link libclc. But if we did
what you want, libclc could not use its own assert functions that
display more clearly than plain assert how a libclc function was used
wrongly. Nor could we use our own error codes.
If you want to use libclc's functions, you'll have to copy the code,
edit the asserts and any error returns, check that the copyright is
compatible with yours (and you'd have to do that your way too).
> Finally, there was some discussion about whether or not it would be
> necessary to write new code or if several implementations would be
> examined and the best one chosen for inclusion.
Yes, Bjørn hopes we'll copy most of the code rather than write it from
scratch. I don't know how much work would be done to decide what to
choose when there are several good existing implementations.
> By attributing the
> library with the 'clc' acronym I would assmue that this code would be
> scrutinized very thoroughly making this question irrelevant.
Not really.
> I would be delighted to contribute in any way I can.
Great!
--
Hallvard
Oh, and which commands to use in order to build the library. Which
compiler to use, its options, whether to use ranlib, and so on. Maybe
in particular how to build a shared library, which can be a bit hairy.
--
Hallvard
>> no assumptions about coding style,
>
> Not sure what you mean here.
Things like excessive typedef-ing a la glib; guint, gpointer, etc
>> Why is GNU autoconf being used if the code is ANSI?
>
> I believe that if it's used, it will only be used to discover possible
> optimizations. The library should work if compiled without autoconf.
Don't most (all?) versions of make define $CC, $CFLAGS, $RM, etc to be
all set. You're code is strict ANSI so what is so complex that you need
to determine optimisation by pulling in GNU autoconf?
>> Why does libclc define it's own error codes?
>
> Because ANSI C only defines two error codes: EDOM and ERANGE. That's
ISO C requires three error codes: EDOM, ERANGE, and ESEQ. But any normal
C library will define the any of the constants that would be used by
simple ADTs and algorithms. Their values are not garunteed to be the same
but why would they need to be?
>
> Note that C library functions called by libclc may set other error codes
> (dependent on the platform), so unless libclc overrides these it will
> return other system error codes than EDOM and ERANGE.
Is this an argument for or against making up your own error codes?
>
>> one thing that immediately discourages me is the assumption by the
>> author(s) that their library will be the basis around which
>> applications will be built (e.g. glib). This is invariably true for the
>> author and exactly the opposite of the truth for everyone else. It
>> would be very thoughtful of the authors to make each module
>> stand-alone. Meaning I would like to be able to copy
>> src/linkedlist.{c,h} into my tree, add the .o to the Makefile (or IDE)
>> and go.
>
> I don't see why it's a problem to build and link libclc. But if we did
It violates the law of demeter. I don't consider it a law but it's a good
idea for the modules not to depend on one another.
> what you want, libclc could not use its own assert functions that
> display more clearly than plain assert how a libclc function was used
> wrongly. Nor could we use our own error codes.
Well you know what I think about using your own error codes and my
understanding was that assert should never be used for anything but
testing.
If it's not necessary to introduce these "inflexabilities" then why do it?
I don't know them. I expect we'll have typedefs for most structs and so
on defined by the library, and I hope there won't be many typedefs for
standard types like int.
>>> Why is GNU autoconf being used if the code is ANSI?
>>
>> I believe that if it's used, it will only be used to discover possible
>> optimizations. The library should work if compiled without autoconf.
>
> Don't most (all?) versions of make define $CC, $CFLAGS, $RM, etc to be
> all set
Yes, but not the commands to build libraries.
> You're code is strict ANSI so what is so complex that you need
> to determine optimisation by pulling in GNU autoconf?
Example: A rot13 function, which swaps a <-> n, b <-> o, and so on,
could be something like this:
int clc_rot13_char(char c)
{
#if <character set is an ISO646 variant, e.g. ASCII>
unsigned char upper_c = toupper((unsigned char)c);
if ('A' <= upper_c && upper_c <= 'Z')
return upper_c < 'N' ? c + 13 : c - 13;
#else
const char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz";
const char rot[] = "NOPQRSTUVWXYZABCDEFGHIJKLM"
"nopqrstuvwxyzabcdefghijklm";
const char *ptr = strchr(alphabet, c);
if (ptr)
return rot(ptr - alphabet);
#endif
return c;
}
You can see rot13 of a string is a lot faster if we can avoid strchr().
>>> Why does libclc define it's own error codes?
>>
>> Because ANSI C only defines two error codes: EDOM and ERANGE. That's
>
> ISO C requires three error codes: EDOM, ERANGE, and ESEQ.
C99, yes. It will be a while before we can assume C99, so we won't
depend on ESEQ being defined.
> But any normal C library will define the any of the constants that
> would be used by simple ADTs and algorithms. Their values are not
> garunteed to be the same but why would they need to be?
The point is that EDOM and ERANGE are the only values defined by the C89
standard. We can't depend on e.g. EEXIST being defined, and if it is
defined, we can't depend on it having the Unix meaning. Some other
system might define it to have a different meaning. For that matter, we
can't depend on two different E* names in the system having different
_values_, so if a libclc function sets EFOO on one error and EBAR on
another where EFOO and EBAR are defined by errno.h, the caller might
break if depends on being able to differentiate between EFOO and EBAR.
>> Note that C library functions called by libclc may set other error codes
>> (dependent on the platform), so unless libclc overrides these it will
>> return other system error codes than EDOM and ERANGE.
>
> Is this an argument for or against making up your own error codes?
Neither. Just a point of info.
>>> one thing that immediately discourages me is the assumption by the
>>> author(s) that their library will be the basis around which
>>> applications will be built (e.g. glib). This is invariably true for the
>>> author and exactly the opposite of the truth for everyone else. It
>>> would be very thoughtful of the authors to make each module
>>> stand-alone. Meaning I would like to be able to copy
>>> src/linkedlist.{c,h} into my tree, add the .o to the Makefile (or IDE)
>>> and go.
>>
>> I don't see why it's a problem to build and link libclc. But if we did
>
> It violates the law of demeter.
Um. The only Demeter my dictionary knows is "the Greek goddess of
agriculture".
> I don't consider it a law but it's a good
> idea for the modules not to depend on one another.
Huh? If one module needs functionality coded by another, why should
it duplicate that code instead of just calling the existing function?
> my understanding was that assert should never be used for anything but
> testing.
Usually true. So when the user of libclc tests _his_ application,
he can link with the debugging (asserting) version of libclc and get
asserts which will tell him if he gives invalid arguments to clc
functions.
--
Hallvard
Agreed 100%
>>> Why is GNU autoconf being used if the code is ANSI?
>>
>> I believe that if it's used, it will only be used to discover possible
>> optimizations. The library should work if compiled without autoconf.
>
> Don't most (all?) versions of make define $CC, $CFLAGS, $RM, etc to be
> all set. You're code is strict ANSI so what is so complex that you need
> to determine optimisation by pulling in GNU autoconf?
I believe this allows people to test for, eg, ASCII character set.
>>> Why does libclc define it's own error codes?
>>
>> Because ANSI C only defines two error codes: EDOM and ERANGE. That's
>
> ISO C requires three error codes: EDOM, ERANGE, and ESEQ. But any normal
> C library will define the any of the constants that would be used by
> simple ADTs and algorithms. Their values are not garunteed to be the same
> but why would they need to be?
If it requires other error codes, then it's no longer ANSI. On the
other hand, if we have CLC_ENOMEM, then code can be written like:
errno = 0;
p = malloc(sizeof *p);
if (!p) {
if (errno == 0)
errno = CLC_ENOMEM;
return NULL;
}
So that even if the standard library functions aren't well-behaved wrt
errno, libclc can be.
- Kevin.
I believe that the majority opinion on clc is that gratuitous typedefs
for structs are evil. The exception would be if the struct is visible
to the user only as an incomplete type. Certainly typedefs for pointer
type are evil.
- Kevin.
Bingo. So I prefer to minimize even dependence on the std library
whenever it involves loading code. I had an argument over that
earlier.
--
Chuck F (cbfal...@yahoo.com) (cbfal...@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!
> "Michael B. Allen" wrote:
>>
> ... snip ...
>>
>> I have some other issues that are more subtle and somewhat opinionated
>> so I will not discuss them in the detail but permit me to make an
>> observation. I have looked at many libraries like this (libtc, kazlib,
>> dlib, ossp, ...) and one thing that immediately discourages me is the
>> assumption by the author(s) that their library will be the basis around
>> which applications will be built (e.g. glib). This is invariably true
>> for the author and exactly the opposite of the truth for everyone else.
It occurred to me that my wording above may not have been choice. With the
excpetion of glib I did not mean to imply that the above mentioned libtc,
kazlib, dlib, or ossp libraries suffer from the problems described.
I hope it uses libtool, at least
--
Freenet distribution not available
Anyone stupid enough to be caught by the police is probably guilty.
Why?
> Certainly typedefs for pointer type are evil.
Yes.
--
Hallvard
Because if something's a struct, you don't want that fact to be hidden.
- Kevin.
I figured out that part. What I don't know is why I don't want that.
--
Hallvard
Why do you want that?
- Kevin.
I don't particularly want to hide it. I just want to use shorter type
names (i.e. no 'struct '). I don't see what harm that does.
--
Hallvard
>Michael B. Allen wrote:
>>On Fri, 14 Mar 2003 18:25:35 -0500, Hallvard B Furuseth wrote:
>>
>> >> no assumptions about coding style,
>> >
>> > Not sure what you mean here.
>>
>> Things like excessive typedef-ing a la glib; guint, gpointer, etc
>
>I don't know them. I expect we'll have typedefs for most structs and so
^^^^^^^^^^^^^^^^
Why? What's wrong with letting a struct be a struct?
Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Dan...@ifh.de
>Michael B. Allen <mia...@eskimo.com> wrote:
>> On Fri, 14 Mar 2003 18:25:35 -0500, Hallvard B Furuseth wrote:
>>
>>>> no assumptions about coding style,
>>>
>>> Not sure what you mean here.
>>
>> Things like excessive typedef-ing a la glib; guint, gpointer, etc
>
>Agreed 100%
>
>>>> Why is GNU autoconf being used if the code is ANSI?
>>>
>>> I believe that if it's used, it will only be used to discover possible
>>> optimizations. The library should work if compiled without autoconf.
>>
>> Don't most (all?) versions of make define $CC, $CFLAGS, $RM, etc to be
>> all set. You're code is strict ANSI so what is so complex that you need
>> to determine optimisation by pulling in GNU autoconf?
>
>I believe this allows people to test for, eg, ASCII character set.
>
>>>> Why does libclc define it's own error codes?
>>>
>>> Because ANSI C only defines two error codes: EDOM and ERANGE. That's
>>
>> ISO C requires three error codes: EDOM, ERANGE, and ESEQ. But any normal
>> C library will define the any of the constants that would be used by
>> simple ADTs and algorithms. Their values are not garunteed to be the same
>> but why would they need to be?
>
>If it requires other error codes, then it's no longer ANSI. On the
It doesn't require them, but it handles them graciously, if present.
>other hand, if we have CLC_ENOMEM, then code can be written like:
>
>errno = 0;
>p = malloc(sizeof *p);
>if (!p) {
> if (errno == 0)
> errno = CLC_ENOMEM;
> return NULL;
>}
>
>So that even if the standard library functions aren't well-behaved wrt
>errno, libclc can be.
This errno handling is sloppy. Imagine that errno was != 0 when the
function was called, and the function succeeds. A successful function
call should NEVER reset errno.
Even then, you can give it to the user declared as
struct clc_foo;
It's 7 extra characters in the 'type name'.
--
Hallvard
If it's used as an ADT (e.g. FILE), hiding it behind a typedef is the
right thing. If it's used as a struct (e.g. struct tm), the code is
more readable if the word struct appears in every relevant declaration.
typedef is not meant to be used as a typing saving device.
Imagine that you see the following in a piece of code you're not
familiar with:
extern foo_t bar;
...
bar.a = i;
j = bar.b;
Is bar a struct or a union? Time to grep the headers... ;-)
Good point. Thanks.
--
Hallvard
While I basically agree with you, the example is flawed in one way
or another. If bar is a union, the snippet is undefined
behaviour. If a struct, all seems to be well. So the question
becomes "who wrote it?".
My attitude would be: It (the typedef) shouldn't be in the
headers, unless it is an incomplete type. It it is local to the
file it is not hard to find the complete definition.
>Dan Pop wrote:
>>
>... snip ...
>>
>> Imagine that you see the following in a piece of code you're not
>> familiar with:
>>
>> extern foo_t bar;
>> ...
>> bar.a = i;
>> j = bar.b;
>>
>> Is bar a struct or a union? Time to grep the headers... ;-)
>
>While I basically agree with you, the example is flawed in one way
>or another. If bar is a union, the snippet is undefined
>behaviour.
Not if the type of bar.b is unsigned char!
>My attitude would be: It (the typedef) shouldn't be in the
>headers, unless it is an incomplete type.
Nonsense. There are good reasons for having typedef's to complete
types in headers. There are no good reasons for hiding a struct behind
a typedef, unless it is supposed to be used as an ADT by the user code
(i.e. the user code ignores the fact that it is a struct). The best
example is FILE, as defined by <stdio.h>.