On 04/06/2025 20:58, Paul Edwards wrote:UTF-8,
"David Brown" <david.brown@hesbynett.no> wrote in message news:101poqm$t350$1@dont-email.me...
On 04/06/2025 11:23, Paul Edwards wrote:
And I know what you're thinking - all the data is in EBCDIC.
There are no other EBCDIC systems I could possibly jump to.
We would need an 80386 EBCDIC version of Win32 in order
for this to be remotely possible - which doesn't exist, and likely
never will exist.
For it to exist it would need some sort of pseudo-bios concept
that allowed charset conversion. And no such thing exists as far
as I am aware!
You don't need an EBCDIC operating system, or "pseudo-bios" (whatever
/that/ might be) to use data using EBCDIC character encoding. It is no
different from working with any other character encoding - ASCII,
different 8-bit code pages, or whatever. If the data is just passing
through your code, read it in and pass it out without a care. If you
need to convert it or mix it with some other encoding, work with a
common encoding - UTF-8 is normally the right choice.
If I have existing C code that does:
fopen("test1.dat", "rb");
fread into buf
if (memcmp(buf + 5, "XYZ", 3) == 0)
and test1.dat is in EBCDIC, the above program on the 80386
has been compiled with EBCDIC strings, so it works, and then
now you do:
printf("It matches!\n");
where do you expect those characters in the printf string - all
currently EBCDIC - to be translated to ASCII on a modern
Windows 10/11 system?
In /your/ code!
/You/ are responsible for writing the code that handles the data, and
which gets the encoding right. If you want to handle data in an odd encoding, write code to handle it. That's what everyone else does when dealing with data in different encodings.
And how do you expect Windows 10/11 to find "test1.dat" -
all EBCDIC on its current ASCII filesystem?
Convert the character encoding for the string.
People do this all the time. They write code that uses UTF-8, and have
to deal with Windows crappy UCS2 / partial UTF-16 / wchar_t mess. Or
they have code that supports different code pages because they started
it in the pre-Unicode days and don't live in a little American-only
ASCII bubble.
C does not make this stuff particularly convenient, though it has
improved a little since C90 - other languages have vastly superior
string and encoding handling. But that does not mean you can't do it,
or should not do it.
Maybe if you actually wanted to contribute something useful to the C
world - something that other people might find useful - you could put
your efforts into writing a library that has functions for converting encodings back and forth with UTF-8 as the base. Include support for
the dozen different EDBDIC versions.
Or do you really think that if someone sent me a file to read that was
in EDBDIC encoding, I'd be happy to install an EDBDIC "pseudo-bios" and EDBDIC version of Windows so that I could read it?
On 2025-06-04, Paul Edwards <mutazilah@gmail.com> wrote:
"Kaz Kylheku" <643-408-1753@kylheku.com> wrote in message news:20250604121550.286@kylheku.com...
On 2025-06-04, Paul Edwards <mutazilah@gmail.com> wrote:
If I have existing C code that does:
fopen("test1.dat", "rb");
fread into buf
if (memcmp(buf + 5, "XYZ", 3) == 0)
and test1.dat is in EBCDIC, the above program on the 80386
has been compiled with EBCDIC strings, so it works, and then
now you do:
printf("It matches!\n");
where do you expect those characters in the printf string - all
currently EBCDIC - to be translated to ASCII on a modern
Windows 10/11 system?
I think that in this case you would ideally want the EBCDIC-enabled
compiler to have extensions for working with both character sets.
For isntance E"foo" would specify a string object that is
encoded in EBCDIC in the execution environment, whereas
"foo" is ASCII.
You could develop a textual preprocesor which implements
this transformation: tokenizes the C well enough to recognize
string literals preceded by E, and translates them to
string literals without E, whose content is EBCDIC bytes.
It wouldn't have to be absoultely perfect; only to work
correctly on your small amount of private code.
Even assuming the above was technically possible - what's
wrong with just having a pseudo-bios and OS so that
everything is totally clean?
Nothing; it's just that the OS doesn't match the requirement given in
some above quoted text I was responding to that this is on "modern
Windows 10/11 system" which requires the program output to be
"translated to ASCII".
Maybe if you actually wanted to contribute something useful to the C
world - something that other people might find useful
Maybe if you actually wanted to contribute something useful to the C
world - something that other people might find useful - you could put
your efforts into writing a library that has functions for converting encodings back and forth with UTF-8 as the base. Include support for
the dozen different EDBDIC versions.
Bonita Montero <Bonita.Montero@gmail.com> writes:
Am 02.06.2025 um 17:24 schrieb Scott Lurndal:
Bonita Montero <Bonita.Montero@gmail.com> writes:
Am 01.06.2025 um 09:43 schrieb Lawrence D'Oliveiro:
On Sun, 1 Jun 2025 07:58:54 +0200, Bonita Montero wrote:
Sth. like this:
for( directory_entry const &de : recursive_directory_iterator( "\\", >>>>>> directory_options::follow_directory_symlink ) )
cout << de.path() << endl;
You need the dirfd functions to avoid certain potential security holes >>>>> on operations with symlinks.
Which security holes ?
The fchownat() function shall be equivalent to the chown() and lchown()
functions except in the case where path specifies a relative path. In >>> this case the file to be changed is determined relative to the directory
associated with the file descriptor fd instead of the current working >>> directory. If the access mode of the open file description associated >>> with the file descriptor is not O_SEARCH, the function shall check
whether directory searches are permitted using the current permissions >>> of the directory underlying the file descriptor. If the access mode is >>> O_SEARCH, the function shall not perform the check.
And why is this relevant for directory_iterator or
recursive_directory_iterator ?
Why are you asking this question on comp.lang.c?
Am 03.06.2025 um 20:25 schrieb Scott Lurndal:
The fchownat() function shall be equivalent to the chown() and lchown()
functions except in the case where path specifies a relative path. In >>>> this case the file to be changed is determined relative to the directory
associated with the file descriptor fd instead of the current working >>>> directory. If the access mode of the open file description associated >>>> with the file descriptor is not O_SEARCH, the function shall check >>>> whether directory searches are permitted using the current permissions
of the directory underlying the file descriptor. If the access mode is
O_SEARCH, the function shall not perform the check.
And why is this relevant for directory_iterator or
recursive_directory_iterator ?
Why are you asking this question on comp.lang.c?
Because you can have it easier than with opendir() / readdir().
Bonita Montero <Bonita.Montero@gmail.com> writes:
Am 03.06.2025 um 20:25 schrieb Scott Lurndal:
The fchownat() function shall be equivalent to the chown() and lchown()
functions except in the case where path specifies a relative path. In
this case the file to be changed is determined relative to the directory
associated with the file descriptor fd instead of the current working
directory. If the access mode of the open file description associated
with the file descriptor is not O_SEARCH, the function shall check >>>>> whether directory searches are permitted using the current permissions
of the directory underlying the file descriptor. If the access mode is
O_SEARCH, the function shall not perform the check.
And why is this relevant for directory_iterator or
recursive_directory_iterator ?
Why are you asking this question on comp.lang.c?
Because you can have it easier than with opendir() / readdir().
Personally, I'd use nftw to iterate over a path.
https://pubs.opengroup.org/onlinepubs/9799919799/functions/nftw.html
Am 06.06.2025 um 16:10 schrieb Scott Lurndal:
Bonita Montero <Bonita.Montero@gmail.com> writes:
Am 03.06.2025 um 20:25 schrieb Scott Lurndal:
The fchownat() function shall be equivalent to the chown() and lchown()
functions except in the case where path specifies a relative path. In
this case the file to be changed is determined relative to the directory
associated with the file descriptor fd instead of the current working
directory. If the access mode of the open file description associated
with the file descriptor is not O_SEARCH, the function shall check >>>>>> whether directory searches are permitted using the current permissions
of the directory underlying the file descriptor. If the access mode is
O_SEARCH, the function shall not perform the check.
And why is this relevant for directory_iterator or
recursive_directory_iterator ?
Why are you asking this question on comp.lang.c?
Because you can have it easier than with opendir() / readdir().
Personally, I'd use nftw to iterate over a path.
https://pubs.opengroup.org/onlinepubs/9799919799/functions/nftw.html
That would be much nicer with a lambda which can take the context
of the calling function.
Bonita Montero <Bonita.Montero@gmail.com> writes:
Am 06.06.2025 um 16:10 schrieb Scott Lurndal:
Bonita Montero <Bonita.Montero@gmail.com> writes:
Am 03.06.2025 um 20:25 schrieb Scott Lurndal:
The fchownat() function shall be equivalent to the chown() and lchown()
functions except in the case where path specifies a relative path. In
this case the file to be changed is determined relative to the directory
associated with the file descriptor fd instead of the current working
directory. If the access mode of the open file description associated
with the file descriptor is not O_SEARCH, the function shall check
whether directory searches are permitted using the current permissions
of the directory underlying the file descriptor. If the access mode is
O_SEARCH, the function shall not perform the check.
And why is this relevant for directory_iterator or
recursive_directory_iterator ?
Why are you asking this question on comp.lang.c?
Because you can have it easier than with opendir() / readdir().
Personally, I'd use nftw to iterate over a path.
https://pubs.opengroup.org/onlinepubs/9799919799/functions/nftw.html
That would be much nicer with a lambda which can take the context
of the calling function.
That's a matter of opinion.
In any case, nftw is a C function and C doesn't support lamda functions.
Am 06.06.2025 um 19:24 schrieb Scott Lurndal:
Bonita Montero <Bonita.Montero@gmail.com> writes:
Am 06.06.2025 um 16:10 schrieb Scott Lurndal:
Bonita Montero <Bonita.Montero@gmail.com> writes:
Am 03.06.2025 um 20:25 schrieb Scott Lurndal:
The fchownat() function shall be equivalent to the chown() and lchown()
functions except in the case where path specifies a relative path. In
this case the file to be changed is determined relative to the directory
associated with the file descriptor fd instead of the current working
directory. If the access mode of the open file description associated
with the file descriptor is not O_SEARCH, the function shall check
whether directory searches are permitted using the current permissions
of the directory underlying the file descriptor. If the access mode is
O_SEARCH, the function shall not perform the check.
And why is this relevant for directory_iterator or recursive_directory_iterator ?
Why are you asking this question on comp.lang.c?
Because you can have it easier than with opendir() / readdir().
Personally, I'd use nftw to iterate over a path.
https://pubs.opengroup.org/onlinepubs/9799919799/functions/nftw.html
That would be much nicer with a lambda which can take the context
of the calling function.
That is illusion, particularly in this case (about directory).That's a matter of opinion.
It results in much less code.
Just like a lambda passed--- Synchronet 3.21a-Linux NewsLink 1.2
to std::sort() which takes context of the calling function.
In any case, nftw is a C function and C doesn't support lamda functions.
Lambdas without capture can be converted to C function-pointers.
On 2025-05-28, Michael S <already5chosen@yahoo.com> wrote:
Got it. Stability occurs when the standards is fenced from
changes by presence of the next edition.
Each technical corrigendum effectively yields a new edition.
The previous standard without that corrigendum is forever stable,
as any immutable object.
On Tue, 27 May 2025 16:16:50 -0700
Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:
Michael S <already5chosen@yahoo.com> writes:
On Tue, 27 May 2025 16:23:22 +0200
David Brown <david.brown@hesbynett.no> wrote:
On 26/05/2025 07:19, Peter 'Shaggy' Haywood wrote:
Groovy hepcat Tim Rentsch was jivin' in comp.lang.c on Fri, 23 May
2025 10:43 pm. It's a cool scene! Dig it.
C99 is just as stable as C90, and has been for well over a
decade.
Methinks Tim is having trouble with his arithmetic. Either
that or he doesn't know what year it is now. :)
C99 was ratified in 1999, over two and a half decades ago.
C11 is just as stable as C90, and has been for just slightly
less than a decade.
And C11 was ratified in 2011, no? That was almost a decade
and a half ago.
Tim was, I believe, taking into account the time it took for common
implementations of C compilers and libraries to have complete and
generally bug-free support for the standards, and for these
implementations to become common. C99 was published in 1999, but
it took quite a while before most people programming in C could
happily use C99 without worrying about the tool support being
"experimental" or not as mature as C90 support.
I believe that your belief is wrong.
It is much more likely that Tim took into account defect reports.
Here is the list of C11 defect reports with the last dated 2016:
https://open-std.org/jtc1/sc22/wg14/www/docs/summary.htm
I did not find similar list for C99. However believing Tim I would
guess that the last change in C99 document was made ~15 years ago.
You are partly right. Besides defect reports, there are TCs. And
there is always the possibility of future TCs, future defect
reports, or future changes for any ISO C standard while it is
still current.
To be as stable as C90, a C standard would need to be immune to
the possibility of such future changes.
I take C99 to have reached this level of stability in 2011, when
it was superseded by C11. I take C11 to have reached this level
of stability in 2017, when it was superseded by C17.
Got it. Stability occurs when the standards is fenced from
changes by presence of the next edition.
Stability by obsolescence.
On Fri, 2025-06-06 at 19:26 +0200, Bonita Montero wrote:
Am 06.06.2025 um 19:24 schrieb Scott Lurndal:
Bonita Montero <Bonita.Montero@gmail.com> writes:
Am 06.06.2025 um 16:10 schrieb Scott Lurndal:
Bonita Montero <Bonita.Montero@gmail.com> writes:
Am 03.06.2025 um 20:25 schrieb Scott Lurndal:
The fchownat() function shall be equivalent to the chown() and lchown()And why is this relevant for directory_iterator or
functions except in the case where path specifies a relative path. In
this case the file to be changed is determined relative to the directory
associated with the file descriptor fd instead of the current working
directory. If the access mode of the open file description associated
with the file descriptor is not O_SEARCH, the function shall check
whether directory searches are permitted using the current permissions
of the directory underlying the file descriptor. If the access mode is
O_SEARCH, the function shall not perform the check. >>>>>>>>
recursive_directory_iterator ?
Why are you asking this question on comp.lang.c?
Because you can have it easier than with opendir() / readdir().
Personally, I'd use nftw to iterate over a path.
https://pubs.opengroup.org/onlinepubs/9799919799/functions/nftw.html
That would be much nicer with a lambda which can take the context
of the calling function.
That's a matter of opinion.
It results in much less code.
That is illusion, particularly in this case (about directory).
Most serious programs will 'invent' their own functions, even their own 'sugar syntax'...
'sugar syntax'... result would be better than 'directory_iterator'.
In general, no need for such things as 'directory_iterator' in C-library.
Just like a lambda passed
to std::sort() which takes context of the calling function.
In any case, nftw is a C function and C doesn't support lamda functions.
Lambdas without capture can be converted to C function-pointers.
Am 06.06.2025 um 22:04 schrieb wij:
On Fri, 2025-06-06 at 19:26 +0200, Bonita Montero wrote:
Am 06.06.2025 um 19:24 schrieb Scott Lurndal:
Bonita Montero <Bonita.Montero@gmail.com> writes:
Am 06.06.2025 um 16:10 schrieb Scott Lurndal:
Bonita Montero <Bonita.Montero@gmail.com> writes:
Am 03.06.2025 um 20:25 schrieb Scott Lurndal:
The fchownat() function shall be equivalent to the chown() and lchown()
functions except in the case where path specifies a relative path. In
this case the file to be changed is determined relative to the directory
associated with the file descriptor fd instead of the current working
directory. If the access mode of the open file description associated
with the file descriptor is not O_SEARCH, the function shall check
whether directory searches are permitted using the current permissions
of the directory underlying the file descriptor. If the access mode is
O_SEARCH, the function shall not perform the check.
And why is this relevant for directory_iterator or recursive_directory_iterator ?
Why are you asking this question on comp.lang.c?
Because you can have it easier than with opendir() / readdir().
Personally, I'd use nftw to iterate over a path.
https://pubs.opengroup.org/onlinepubs/9799919799/functions/nftw.html
That would be much nicer with a lambda which can take the context
of the calling function.
C has to deal with hardware, that is all the basic (C++ and other languages are fundamentally the same).That's a matter of opinion.
It results in much less code.
That is illusion, particularly in this case (about directory).
I've shown the code. In C++17 iterating through a single directory and printing it is two lines of code.
There are many kinds of 'sub-languages' that can do any specific job better.Most serious programs will 'invent' their own functions, even their own 'sugar syntax'...
Not to iterate through a directory in C++.
'sugar syntax'... result would be better than 'directory_iterator'.
Why ?
In general, no need for such things as 'directory_iterator' in C-library.
In C you're forced to write ten times the code if you include errorC++ is no better, probably worse. Firstly, the term 'exception' (and
handling.
Just like a lambda passed
to std::sort() which takes context of the calling function.
In any case, nftw is a C function and C doesn't support lamda functions.
Lambdas without capture can be converted to C function-pointers.
C++ is no better, probably worse. Firstly, the term 'exception' (and
'vector' probably) is disabled in human mind to think about exception.
C++ had been trying to HIDE error (exception) from its beginning, very wrong and very unsuccessful.
Am 07.06.2025 um 13:58 schrieb wij:The error from opendir(..):
C++ is no better, probably worse. Firstly, the term 'exception' (and 'vector' probably) is disabled in human mind to think about exception.
I deal with exceptions every day and I've no problems with that. C++ exceptions aren't that clean like Java exceptions, but still make much
less work than C return code handling.
Conditional. As said 'simplified'.C++ had been trying to HIDE error (exception) from its beginning, very wrong
and very unsuccessful.
Exceptions are the cleanest way of error handling.
In most cases youIf you can handle errors that way, C can also do it in much simpler way.
deal with the error in a higher function and not in the leaf of the
call graph; therefore exceptions are perfect.
The error from opendir(..):
EACCES Permission denied.
EBADF fd is not a valid file descriptor opened for reading.
EMFILE The per-process limit on the number of open file descriptors has
been reached.
ENFILE The system-wide limit on the total number of open files has been
reached.
ENOENT Directory does not exist, or name is an empty string.
ENOMEM Insufficient memory to complete the operation.
ENOTDIR name is not a directory.
...
I think your 'less work' was from simplication or idealization, lots are simplified and idealized.
If you can handle errors that way, C can also do it in much simpler way.
The basic problem of throwing error is losing error context, it is similar
to set a global errno (or object) and cause the program to stack unwind.
C++ has many artificial fancy things and encourages such programming style. Good or bad? Both, but I would say mostly bad.
Am 07.06.2025 um 20:43 schrieb wij:I see std::filesystem as evidence that C++ finally admits the deficiency of
The error from opendir(..):
EACCES Permission denied.
EBADF fd is not a valid file descriptor opened for reading.
EMFILE The per-process limit on the number of open file descriptors has
been reached.
ENFILE The system-wide limit on the total number of open files has been
reached.
ENOENT Directory does not exist, or name is an empty string. ENOMEM Insufficient memory to complete the operation. ENOTDIR name is not a directory.
...
With C++ that's all encapsulated in filesystem_error which is derived
from system_error. But you can omit permission denied errors with directory_options::skip_permission_denied. That makes sense mostly
with recursive_directory_iterator.
If you want to to that in C you'veMost of the above replies are false owing from narrow view. I'll save my explanations.
at least ten times the code.
I think your 'less work' was from simplication or idealization, lots are simplified and idealized.
No, show me your C code to iterate through a directory and I show you
the same code with up to a fifth of C++-code. When you iterate
recur-sively that's a tenth of the code.
If you can handle errors that way, C can also do it in much simpler way.
Absolutely not.
The basic problem of throwing error is losing error context, it is similar to set a global errno (or object) and cause the program to stack unwind.
The context doesn't matter. A bad_alloc doesn't need context, a
system_error also not. And that's most of the exceptions the C++
runtime throws (some are derived from system_error).
C++ has many artificial fancy things and encourages such programming style. Good or bad? Both, but I would say mostly bad.
C is bad, because you've to do simple things over and over with multiple times the code because there are no language-facilities to abstract your coding.
Am 07.06.2025 um 20:43 schrieb wij:
The basic problem of throwing error is losing error context, [...]
The context doesn't matter. A bad_alloc doesn't need context, a
system_error also not. And that's most of the exceptions the C++
runtime throws (some are derived from system_error).
I see std::filesystem as evidence that C++ finally admits the deficiency of its advance error handling system (std::exception). But the result is worse than C.
I am not familiar with C++ std lib, I cannot say much.
I see std::filesystem as evidence that C++ finally admits the deficiency of its advance error handling system (std::exception). But the result is worse
than C.
Am 07.06.2025 um 21:56 schrieb wij:
I see std::filesystem as evidence that C++ finally admits the deficiency of >> its advance error handling system (std::exception). But the result is worse
than C.
That's just a mere assertion without any facts. In fact, exception
handling makes error handling possible with a fraction of the code
length, because most parts of the code don't need to handle errors,
whereas in C they do. In C every call level has to deal with erorrs,
whereas in C++ only one level at the upper edge has to catch the
errors.
Am 07.06.2025 um 21:56 schrieb wij:I know a bit of the development of std::filesystem. The view of mere 'standard' disregards fact and uses more the 'assertion' criticized.
I see std::filesystem as evidence that C++ finally admits the deficiency of its advance error handling system (std::exception). But the result is worse
than C.
That's just a mere assertion without any facts.
In fact, exception"dont' need" is illusion, errors are always there, mostly ignored and encouraged
handling makes error handling possible with a fraction of the code
length, because most parts of the code don't need to handle errors,
whereas in C they do. In C every call level has to deal with erorrs,C has not hard coded what 'exception' should be. E.g. C can also set an error object and let interested code to handle it in many ways, what's left is impl. issues.
whereas in C++ only one level at the upper edge has to catch the
errors.
You can of course use setjmp & longjmp in C but depending on how many levels up you jump they could be more trouble than they're worth. I think I've only ever used them once.
I know a bit of the development of std::filesystem. The view of mere 'standard'
disregards fact and uses more the 'assertion' criticized.
"dont' need" is illusion, errors are always there, mostly ignored and encouraged
to ignore by simplification.
C has not hard coded what 'exception' should be. E.g. C can also set an error object and let interested code to handle it in many ways, what's left is impl.
issues.
But, I think the 'throw' mechanism (not std::exception) is good, like many others. 'throw' is more like a soft assert failure, which is no error handling.
Am 08.06.2025 um 10:55 schrieb Muttley@DastardlyHQ.org:
You can of course use setjmp & longjmp in C but depending on how many levels >> up you jump they could be more trouble than they're worth. I think I've only >> ever used them once.
That's makes a lot of work and it's really ugly. And you need global >jump_buf-s for that.
Context, in the general case, matters. ...
It's been decades that I used C++, but back then in the 1990's
we did pass error context with the thrown error object.
That's an inherent part of C++'s exception handling. If you useMost exceptions you throw or catch are bad_allocs or system_errors.
standard error classes without context that's of course possible,
but nothing prevents you to define yet another error class derived
from some existing error class with additional information. You
are actually free to do what suits you and your projects best;
use rudimentary handling, or have a sophisticated error framework,
or anything in between.
Its no different to C++ exceptions except obviously no destructors
are called so there's no chance to do a tidy up at each stack level.
Am 08.06.2025 um 16:52 schrieb wij:My primary interest of programming is on the theory. From your presented wording, I don't think you can conduct a logical discussion (it seems you continue to ask for logical proof).
I know a bit of the development of std::filesystem. The view of mere 'standard'
disregards fact and uses more the 'assertion' criticized.
Another statement without arguments.
It seems your whole idea (and 'fact') is based on C++'s propaganda."dont' need" is illusion, errors are always there, mostly ignored and encouraged
to ignore by simplification.
If the code is written to be exception-safe, i.e. it uses
RAII throughout, then this is easily possible.
C has not hard coded what 'exception' should be. E.g. C can also set an error
object and let interested code to handle it in many ways, what's left is impl.
issues.
Are you serious? The fact that the exception type is transported along
with the exception itself makes things really convenient. This way, the
stack can be unrolled until the correct exception handler is found.
But, I think the 'throw' mechanism (not std::exception) is good, like many others. 'throw' is more like a soft assert failure, which is no error handling.
Totally different - asserts are handled at debug-time.
Based on this statement, you didn't understand exceptions correctly.
On Sun, 8 Jun 2025 17:02:08 +0200
Bonita Montero <Bonita.Montero@gmail.com> wibbled:
Am 08.06.2025 um 10:55 schrieb Muttley@DastardlyHQ.org:
You can of course use setjmp & longjmp in C but depending on how many levels
up you jump they could be more trouble than they're worth. I think I've only
ever used them once.
That's makes a lot of work and it's really ugly. And you need global >>jump_buf-s for that.
Its no different to C++ exceptions except obviously no destructors are called >so there's no chance to do a tidy up at each stack level. Also jumps arn't >limited to lower to higher stack frames jumps, they can jump about all over >the place. Whether thats useful or not I can't say. I've never needed it.
Am 07.06.2025 um 23:12 schrieb Janis Papanagnou:
Context, in the general case, matters. ...
If you need the context then you catch the exception near where
it is thrown; but that's not usual, meaning in most cases you
don't need that context. F.e. when a bad_alloc is thown it dosn't
matter which allocation failed, it's just enough to know that a >memory-collapse happened.
Muttley@DastardlyHQ.org writes:
On Sun, 8 Jun 2025 17:02:08 +0200
Bonita Montero <Bonita.Montero@gmail.com> wibbled:
Am 08.06.2025 um 10:55 schrieb Muttley@DastardlyHQ.org:
You can of course use setjmp & longjmp in C but depending on how many levels
up you jump they could be more trouble than they're worth. I think I've only
ever used them once.
That's makes a lot of work and it's really ugly. And you need global >>>jump_buf-s for that.
Its no different to C++ exceptions except obviously no destructors are called >>so there's no chance to do a tidy up at each stack level. Also jumps arn't >>limited to lower to higher stack frames jumps, they can jump about all over >>the place. Whether thats useful or not I can't say. I've never needed it.
I've used sigsetjmp/siglongjmp in C++ code, very successfully. As an experiment a few
years ago, I replaced it with C++ exceptions and took a 20% performance
hit in the application. Needless to say the experiment was a failure.
In general, I tend to concur with wij - I prefer to handle run-of-the-mill errors when they're detected.
For example:^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
c_file_card_unit::c_file_card_unit(ulong channel, ulong unit, const char *name,
So, if is_ready() returns false after the constructor runs,
the creator of the object knows the creation failed.
Bonita Montero <Bonita.Montero@gmail.com> writes:
Am 07.06.2025 um 23:12 schrieb Janis Papanagnou:
Context, in the general case, matters. ...
If you need the context then you catch the exception near where
it is thrown; but that's not usual, meaning in most cases you
don't need that context. F.e. when a bad_alloc is thown it dosn't
matter which allocation failed, it's just enough to know that a
memory-collapse happened.
Actually it very much matters where the allocation failed, if
one wishes to recover from it.
It seems your concept of error
handling is simply reporting it (hopefully with sufficient
context information for the user to understand what needs to
be fixed) and calling exit().
My primary interest of programming is on the theory. ...
I've used sigsetjmp/siglongjmp in C++ code, very successfully. As an experiment a few
years ago, I replaced it with C++ exceptions and took a 20% performance
hit in the application. Needless to say the experiment was a failure.
Actually it very much matters where the allocation failed, if
one wishes to recover from it.
Am 08.06.2025 um 18:28 schrieb wij:Where did I talk about theory?
My primary interest of programming is on the theory. ...
Then don't talk about practical issues.
For example:
c_file_card_unit::c_file_card_unit(ulong channel, ulong unit, const char *name,
c_logger *lp, c_card_dlp *dlp, bool punch,
bool hollerith, const char *binpath)
: c_card_unit(channel, unit, lp, dlp, punch)
{
int flags = punch?O_RDWR|O_APPEND:O_RDONLY;
int diag;
uint8 header[CARD_SIZE_COLUMNS];
f_file = NULL;
f_inputhopper = 0ul;
f_binfd = -1;
snprintf(f_binary_path, sizeof(f_binary_path), "%s", binpath);
diag = stat(name, &cu_stat);
if (diag == -1) {
if ((errno == ENOENT) && punch) {
flags |= O_CREAT|O_EXCL;
}
}
cu_fd = open(name, flags, 0600);
if (cu_fd == -1) {
fprintf(stdout, "%4.4lu/%2.2lu Unable to open '%s': %s\n", cu_channel, cu_unit, name, strerror(errno)); return;
}
diag = fcntl(cu_fd, F_SETFD, FD_CLOEXEC);
if (diag == -1) {
lp->log("%4.4lu/%2.2lu Unable to set FD_CLOEXEC on '%s': %s\n",
cu_channel, cu_unit, name, strerror(errno));
diag = close(cu_fd);
cu_fd = -1;
return;
}
...
}
bool
c_file_card_unit::is_ready(void)
{
return (cu_fd != -1) && ((f_file != NULL) && !feof(f_file));
}
So, if is_ready() returns false after the constructor runs,
the creator of the object knows the creation failed.
In C every call level has to deal with erorrs, whereas in C++ only
one level at the upper edge has to catch the errors.
Am 08.06.2025 um 17:08 schrieb Muttley@DastardlyHQ.org:
Its no different to C++ exceptions except obviously no destructors
are called so there's no chance to do a tidy up at each stack level.
It's much more complicated than exceptions because the functions where
the error raises and where the error is "caught" need shared global >variables. C++ doesn't need that, just throw and catch and everything
is glued to the runtime.
And the problem with your solution is: All functions between the setjmp-
and the longjmp-calls don't have any cleanup, i.e. they don't handle
back their opened resources to the runtime or the kernel. With RAII in >combination with exceptions that's for free.
Do you really think setjmp() / longjmp() is a competitive solution ?
You're naive.
In general, I tend to concur with wij - I prefer to handle run-of-the-mill >errors when they're detected.
Did you actually read what I wrote? Obviously in C++ you'd use exceptionsI ask myself if setjmp() / longjmp() with manual unwinding then is
but in C without any kind of built in exception mechanism they're better
than nothing if you want to jump out of a deep stack.
Same here. I think with exceptions the clue is in the name. They should really
only be used for exceptional circumstances, not as a general minor error handling mechanism.
Not necessarily that simple. It might be easier if C++ had
try/finally (like Python does), but it doesn’t.
Am 08.06.2025 um 18:58 schrieb Scott Lurndal:
Actually it very much matters where the allocation failed, if
one wishes to recover from it.
This very rarely makes sense. It's almost always the case that if
an operation fails, it doesn't matter what allocation was behind
it.
Have you ever written real-world production code? Like an operating system, where allocation failures should -never- result in an
inability to recover.
Am 09.06.2025 um 16:01 schrieb Scott Lurndal:
Have you ever written real-world production code? Like an operating
system, where allocation failures should -never- result in an
inability to recover.
If you need an allocation to proceed and it fails you can't recover.
Bonita Montero <Bonita.Montero@gmail.com> writes:
Am 09.06.2025 um 16:01 schrieb Scott Lurndal:
Have you ever written real-world production code? Like an operating
system, where allocation failures should -never- result in an
inability to recover.
If you need an allocation to proceed and it fails you can't recover.
That's your problem caused by poor design and implementation.
Exacerbated by the propensity for you to use C++ features that require dynamic allocation where other forms of data structures are more suitable.
Bonita Montero <Bonita.Montero@gmail.com> writes:
Am 09.06.2025 um 16:01 schrieb Scott Lurndal:
Have you ever written real-world production code? Like an operating
system, where allocation failures should -never- result in an
inability to recover.
If you need an allocation to proceed and it fails you can't recover.
That's your problem caused by poor design and implementation.
Am 09.06.2025 um 17:53 schrieb Scott Lurndal:
Bonita Montero <Bonita.Montero@gmail.com> writes:
Am 09.06.2025 um 16:01 schrieb Scott Lurndal:
Have you ever written real-world production code? Like an operating >>>> system, where allocation failures should -never- result in an
inability to recover.
If you need an allocation to proceed and it fails you can't recover.
That's your problem caused by poor design and implementation.
That's how 100% of all programs that deal with bad_alloc are designed.
Exacerbated by the propensity for you to use C++ features that require
dynamic allocation where other forms of data structures are more suitable.
When dynamic allocation is needed it is needed.
And there are many ways to handle it that don't include throwing
bad_alloc when the system is unable to provide additional address
space, memory or backing store.
Allocating major data structures at application start (perhaps using
a pool allocator) and crafting your algorithms such that they
don't require infinite memory is a good start.
Bonita Montero <Bonita.Montero@gmail.com> writes:
Am 08.06.2025 um 18:58 schrieb Scott Lurndal:
Actually it very much matters where the allocation failed, if
one wishes to recover from it.
This very rarely makes sense. It's almost always the case that if
an operation fails, it doesn't matter what allocation was behind
it.
Have you ever written real-world production code? Like an operating system, where allocation failures should -never- result in an
inability to recover.
Bonita Montero <Bonita.Montero@gmail.com> writes:
Am 09.06.2025 um 17:53 schrieb Scott Lurndal:
Bonita Montero <Bonita.Montero@gmail.com> writes:
Am 09.06.2025 um 16:01 schrieb Scott Lurndal:
Have you ever written real-world production code? Like an operating >>>>> system, where allocation failures should -never- result in an
inability to recover.
If you need an allocation to proceed and it fails you can't recover.
That's your problem caused by poor design and implementation.
That's how 100% of all programs that deal with bad_alloc are designed.
Exacerbated by the propensity for you to use C++ features that requireWhen dynamic allocation is needed it is needed.
dynamic allocation where other forms of data structures are more suitable. >>
And there are many ways to handle it that don't include throwing
bad_alloc when the system is unable to provide additional address
space, memory or backing store.
Allocating major data structures at application start (perhaps using a
pool allocator) and crafting your algorithms such that they
don't require infinite memory is a good start.
You're talking to someone who can't understand the difference
between comp.lang.c and comp.lang.c++. What do you expect?
On 2025-06-08, Scott Lurndal <scott@slp53.sl.home> wrote:
Muttley@DastardlyHQ.org writes:
On Sun, 8 Jun 2025 17:02:08 +0200
Bonita Montero <Bonita.Montero@gmail.com> wibbled:
Am 08.06.2025 um 10:55 schrieb Muttley@DastardlyHQ.org:
You can of course use setjmp & longjmp in C but depending on how
many levels up you jump they could be more trouble than they're
worth. I think I've only ever used them once.
That's makes a lot of work and it's really ugly. And you need
global jump_buf-s for that.
setjmp and longjmp have a clearly defined implementation model
(obviously not in ISO C, but so in implementation practice).
On Mon, 2 Jun 2025 09:35:24 +0200, Bonita Montero wrote:
Am 01.06.2025 um 09:43 schrieb Lawrence D'Oliveiro:
On Sun, 1 Jun 2025 07:58:54 +0200, Bonita Montero wrote:
Sth. like this:
for( directory_entry const &de : recursive_directory_iterator( "\\", >>>> directory_options::follow_directory_symlink ) )
cout << de.path() << endl;
You need the dirfd functions to avoid certain potential security
holes on operations with symlinks.
Which security holes ?
TOCTOU.
On Mon, 09 Jun 2025 18:33:38 GMT
scott@slp53.sl.home (Scott Lurndal) wibbled:
Bonita Montero <Bonita.Montero@gmail.com> writes:
Am 09.06.2025 um 17:53 schrieb Scott Lurndal:
Bonita Montero <Bonita.Montero@gmail.com> writes:
Am 09.06.2025 um 16:01 schrieb Scott Lurndal:
Have you ever written real-world production code? Like an operating >>>>>> system, where allocation failures should -never- result in an
inability to recover.
If you need an allocation to proceed and it fails you can't recover.
That's your problem caused by poor design and implementation.
That's how 100% of all programs that deal with bad_alloc are designed.
Exacerbated by the propensity for you to use C++ features that require >>>> dynamic allocation where other forms of data structures are more suitable. >>>When dynamic allocation is needed it is needed.
And there are many ways to handle it that don't include throwing
bad_alloc when the system is unable to provide additional address
space, memory or backing store.
Allocating major data structures at application start (perhaps using a
pool allocator) and crafting your algorithms such that they
don't require infinite memory is a good start.
Ugh. Then you end up like the Java JVM - grabbing boatloads of memory that >causes huge startup delays and can often cause the machine to do lots of >swapping and/or slow everything else down to treacle.
And all the existing C compilers in the entire planet support
the C90 dialect[*], if so instructed. Where is the problem?
Am 03.06.2025 um 02:37 schrieb Lawrence D'Oliveiro:
On Mon, 2 Jun 2025 09:35:24 +0200, Bonita Montero wrote:
Am 01.06.2025 um 09:43 schrieb Lawrence D'Oliveiro:
On Sun, 1 Jun 2025 07:58:54 +0200, Bonita Montero wrote:
Sth. like this:
for( directory_entry const &de : recursive_directory_iterator( "\\", >>>>> directory_options::follow_directory_symlink ) )
cout << de.path() << endl;
You need the dirfd functions to avoid certain potential security
holes on operations with symlinks.
Which security holes ?
TOCTOU.
That's unavoidable with directory-operations.
That's unavoidable with directory-operations.
Incorrect. The entire purpose of the POSIX *at functions are to close
those security holes.
Muttley@DastardlyHQ.org writes:
Ugh. Then you end up like the Java JVM - grabbing boatloads of memory that >>causes huge startup delays and can often cause the machine to do lots of >>swapping and/or slow everything else down to treacle.
That's a problem with host not being suitable for java, if that
is the behavior you are seeing. I've not seen that in production
java-based applications that are competently developed.
For C/C++, one generally allocates page-aligned regions with mmap, eschewing >granular allocation methods such as new/delete/malloc.
Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
Richard Harnden <richard.harnden@gmail.invalid> writes:
On 22/05/2025 23:32, Keith Thompson wrote:
[...]
In one of your library's headers:
extern const char ESCAPE;
In the corresponding *.c file:
const char ESCAPE = ('z' - 'a' == 25 ? '\x1b' : '\x27');
Change the name if you prefer.
Wouldn't that be a reserved identifier?
Yes, it would. Good catch.
(Identifiers starting with E followed by either a digit or an
uppercase letter are reserved; they could be defined as macros
in <errno.h>.)
They are reserved only as macros, and only if <errno.h> has
been #include'd.
For this particular use, it's easy to make the definition work,
simply by adding
#undef ESCAPE
before the declaration in the header file, and before the
definition in the source file (assuming of course that if
there are any #include <errno.h> they precede the #undef's).
It would be even easier to pick a different name.
Bonita Montero <Bonita.Montero@gmail.com> writes:
Am 03.06.2025 um 02:37 schrieb Lawrence D'Oliveiro:
On Mon, 2 Jun 2025 09:35:24 +0200, Bonita Montero wrote:
Am 01.06.2025 um 09:43 schrieb Lawrence D'Oliveiro:
On Sun, 1 Jun 2025 07:58:54 +0200, Bonita Montero wrote:
Sth. like this:
for( directory_entry const &de : recursive_directory_iterator( "\\", >>>>>> directory_options::follow_directory_symlink ) )
cout << de.path() << endl;
You need the dirfd functions to avoid certain potential security
holes on operations with symlinks.
Which security holes ?
TOCTOU.
That's unavoidable with directory-operations.
Incorrect. The entire purpose of the POSIX *at functions are to close
those security holes.
Muttley@DastardlyHQ.org writes:
On Mon, 09 Jun 2025 18:33:38 GMT
scott@slp53.sl.home (Scott Lurndal) wibbled:
Bonita Montero <Bonita.Montero@gmail.com> writes:
Am 09.06.2025 um 17:53 schrieb Scott Lurndal:
Bonita Montero <Bonita.Montero@gmail.com> writes:
Am 09.06.2025 um 16:01 schrieb Scott Lurndal:That's your problem caused by poor design and implementation.
Have you ever written real-world production code? Like an operating >>>>>>> system, where allocation failures should -never- result in an
inability to recover.
If you need an allocation to proceed and it fails you can't recover. >>>>>
That's how 100% of all programs that deal with bad_alloc are designed. >>>>
Exacerbated by the propensity for you to use C++ features that require >>>>> dynamic allocation where other forms of data structures are more suitable.
When dynamic allocation is needed it is needed.
And there are many ways to handle it that don't include throwing
bad_alloc when the system is unable to provide additional address
space, memory or backing store.
Allocating major data structures at application start (perhaps using a
pool allocator) and crafting your algorithms such that they
don't require infinite memory is a good start.
Ugh. Then you end up like the Java JVM - grabbing boatloads of memory that >> causes huge startup delays and can often cause the machine to do lots of
swapping and/or slow everything else down to treacle.
That's a problem with host not being suitable for java, if that
is the behavior you are seeing. I've not seen that in production
java-based applications that are competently developed.
For C/C++, one generally allocates page-aligned regions with mmap, eschewing granular allocation methods such as new/delete/malloc.
Bonita Montero <Bonita.Montero@gmail.com> writes:
Am 09.06.2025 um 17:53 schrieb Scott Lurndal:
Bonita Montero <Bonita.Montero@gmail.com> writes:
Am 09.06.2025 um 16:01 schrieb Scott Lurndal:
Have you ever written real-world production code? Like an operating >>>>> system, where allocation failures should -never- result in an
inability to recover.
If you need an allocation to proceed and it fails you can't recover.
That's your problem caused by poor design and implementation.
That's how 100% of all programs that deal with bad_alloc are designed.
Exacerbated by the propensity for you to use C++ features that requireWhen dynamic allocation is needed it is needed.
dynamic allocation where other forms of data structures are more suitable. >>
And there are many ways to handle it that don't include throwing
bad_alloc when the system is unable to provide additional address
space, memory or backing store.
Allocating major data structures at application start (perhaps using a
pool allocator) and crafting your algorithms such that they
don't require infinite memory is a good start.
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:[...]
Richard Harnden <richard.harnden@gmail.invalid> writes:
On 22/05/2025 23:32, Keith Thompson wrote:
In one of your library's headers:
extern const char ESCAPE;
In the corresponding *.c file:
const char ESCAPE = ('z' - 'a' == 25 ? '\x1b' : '\x27');
Change the name if you prefer.
Wouldn't that be a reserved identifier?
Yes, it would. Good catch.
(Identifiers starting with E followed by either a digit or an
uppercase letter are reserved; they could be defined as macros
in <errno.h>.)
They are reserved only as macros, and only if <errno.h> has
been #include'd.
For this particular use, it's easy to make the definition work,
simply by adding
#undef ESCAPE
before the declaration in the header file, and before the
definition in the source file (assuming of course that if
there are any #include <errno.h> they precede the #undef's).
It would be even easier to pick a different name.
The point of my comment was to help explain the rules about what
macro names are reserved and under what circumstances, not to
suggest a way to avoid conflicts.
A better way to avoid conflicts with E* macros is to take functions
where errno is needed, as for example signal(), and not call them
directly but rather wrap each one in a function, with the wrapping
functions put in (one or more) separate translation unit(s). Those translation units, and only those translation units, are the ones
where a #include <errno.h> is done. Some details are needed to keep
the separation complete, but I think those aren't too hard to work
out, so if someone has trouble please ask. This way most of the
program can use names beginning with E that might otherwise be
reserved, without any fear of conflicts. There is a bit of source
code overhead, but that is paid only once, across all projects that
use this approach. Also there are some other benefits, related to
libraries used that are not part of ISO C, such as Posix, which
again should be readily apparent to anyone used to working in large
projects that use such libraries.
I find the reservation of potential errno macro names annoying.
On 2025-06-10, Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
I find the reservation of potential errno macro names annoying.
If the standard contained /no/ statements about what a given header
file may reserve, then /any/ identifier whatsoever would be a potential clash.
The errno reservation is kind of good because implementors often extend
the set of errno constants. POSIX has a lot more of them than ISO C, and there are some vendor-specific ones.
Anyway, you can safely ignore the reservation theatre, and just
deal with clashes that happen, when they happen. (If you're lucky,
that could just be never).
Anyway, ISO C, POSIX and vendors have historically introduced new
identifiers in spaces that were not previously declared as reserved.
If you're ever hit by that, you will feel like a completel sucker if
you've religiously adhered to namespaces from your end.
Am 03.06.2025 um 02:37 schrieb Lawrence D'Oliveiro:\",
On Mon, 2 Jun 2025 09:35:24 +0200, Bonita Montero wrote:
Am 01.06.2025 um 09:43 schrieb Lawrence D'Oliveiro:
On Sun, 1 Jun 2025 07:58:54 +0200, Bonita Montero wrote:
Sth. like this:
for( directory_entry const &de : recursive_directory_iterator( "\
directory_options::follow_directory_symlink ) )
cout << de.path() << endl;
You need the dirfd functions to avoid certain potential security
holes on operations with symlinks.
Which security holes ?
TOCTOU.
That's unavoidable with directory-operations.
Kaz Kylheku <643-408-1753@kylheku.com> writes:
On 2025-06-10, Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
I find the reservation of potential errno macro names annoying.
If the standard contained /no/ statements about what a given header
file may reserve, then /any/ identifier whatsoever would be a potential
clash.
The errno reservation is kind of good because implementors often extend
the set of errno constants. POSIX has a lot more of them than ISO C, and
there are some vendor-specific ones.
Anyway, you can safely ignore the reservation theatre, and just
deal with clashes that happen, when they happen. (If you're lucky,
that could just be never).
You can do that, but a new clash could happen when your code is
compiled on a system that defines an errno macro that you haven't
seen before.
Anyway, ISO C, POSIX and vendors have historically introduced new
identifiers in spaces that were not previously declared as reserved.
If you're ever hit by that, you will feel like a completel sucker if
you've religiously adhered to namespaces from your end.
Yes, that can happen, but no, I won't feel like a complete sucker.
If I define my own strfoo() function and a new edition of the standard defines strfoo() in <string.h>, the clash is my fault,and I could have avoided it by defining str_foo().
On 2025-06-10, Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
Kaz Kylheku <643-408-1753@kylheku.com> writes:
On 2025-06-10, Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
I find the reservation of potential errno macro names annoying.
If the standard contained /no/ statements about what a given header
file may reserve, then /any/ identifier whatsoever would be a potential
clash.
The errno reservation is kind of good because implementors often extend
the set of errno constants. POSIX has a lot more of them than ISO C, and >>> there are some vendor-specific ones.
Anyway, you can safely ignore the reservation theatre, and just
deal with clashes that happen, when they happen. (If you're lucky,
that could just be never).
You can do that, but a new clash could happen when your code is
compiled on a system that defines an errno macro that you haven't
seen before.
A new CRASH could happen too, and any number of things.
This clash would be literally one of the first roadblocks, if not the
first one, that we would see when just exploring the possibility whether
our code might not run on that system.
At that point we could be months away from declaring that a supported platform.
Anyway, ISO C, POSIX and vendors have historically introduced new
identifiers in spaces that were not previously declared as reserved.
If you're ever hit by that, you will feel like a completel sucker if
you've religiously adhered to namespaces from your end.
Yes, that can happen, but no, I won't feel like a complete sucker.
If I define my own strfoo() function and a new edition of the standard
defines strfoo() in <string.h>, the clash is my fault,and I could have
avoided it by defining str_foo().
But, my point is, that maybe you could have called it kidneybeans() and
still have a clash.
In fact, if you are writing new string functions that are the same sort
of stuff like the standard ones, you should use the str prefix,
for consistency.
If your code is influential enough, they might be standardized one
day---and then they are ready with the proper naming, so early adopters
of your functions won't have to change anything; just in their build
system drop the third party code and switch to what their library now provides.
No it isn’t. That’s why we have the fd-based calls in recent POSIX, and in
Linux. That plugs the holes, and makes it possible to implement privileged file-access software like Samba securely.
Am 11.06.2025 um 01:33 schrieb Lawrence D'Oliveiro:
No it isn’t. That’s why we have the fd-based calls in recent POSIX, and >> in Linux. That plugs the holes, and makes it possible to implement
privileged file-access software like Samba securely.
opendir() and readdir() hasn't changed for decades.
Am 11.06.2025 um 01:33 schrieb Lawrence D'Oliveiro:
No it isn’t. That’s why we have the fd-based calls in recent POSIX, and in
Linux. That plugs the holes, and makes it possible to implement privileged >> file-access software like Samba securely.
opendir() and readdir() hasn't changed for decades.
Kaz Kylheku <643-408-1753@kylheku.com> writes:
On 2025-06-10, Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
Kaz Kylheku <643-408-1753@kylheku.com> writes:
On 2025-06-10, Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
I find the reservation of potential errno macro names annoying.
If the standard contained /no/ statements about what a given header
file may reserve, then /any/ identifier whatsoever would be a potential >>>> clash.
The errno reservation is kind of good because implementors often extend >>>> the set of errno constants. POSIX has a lot more of them than ISO C, and >>>> there are some vendor-specific ones.
Anyway, you can safely ignore the reservation theatre, and just
deal with clashes that happen, when they happen. (If you're lucky,
that could just be never).
You can do that, but a new clash could happen when your code is
compiled on a system that defines an errno macro that you haven't
seen before.
A new CRASH could happen too, and any number of things.
Sure, but a compilation failure is more likely.
This clash would be literally one of the first roadblocks, if not the
first one, that we would see when just exploring the possibility whether
our code might not run on that system.
At that point we could be months away from declaring that a supported
platform.
Sure, but why not skip that first roadblock?
Anyway, ISO C, POSIX and vendors have historically introduced new
identifiers in spaces that were not previously declared as reserved.
If you're ever hit by that, you will feel like a completel sucker if
you've religiously adhered to namespaces from your end.
Yes, that can happen, but no, I won't feel like a complete sucker.
If I define my own strfoo() function and a new edition of the standard
defines strfoo() in <string.h>, the clash is my fault,and I could have
avoided it by defining str_foo().
But, my point is, that maybe you could have called it kidneybeans() and
still have a clash.
Certainly, I've already acknowledged that.
But surely an identifier that the standard says is reserved is less
likely to cause a clash than one that isn't.
In fact, if you are writing new string functions that are the same sort
of stuff like the standard ones, you should use the str prefix,
for consistency.
If your code is influential enough, they might be standardized one
day---and then they are ready with the proper naming, so early adopters
of your functions won't have to change anything; just in their build
system drop the third party code and switch to what their library now
provides.
I see your point, but ... meh. To me, a name matching "str[a-z]*"
fairly strongly suggests a function declared in <string.h> in ISO C.
Of course it's not an absolute rule; see strlcpy(), for example
(which is now part of POSIX).
Even a str*() identifier that never clashes with ISO C's <string.h>
can still clash with POSIX, or glibc, or BSD, or ....
I would have been happier if POSIX were less intrusive on the
C standard library, but the way C and POSIX evolved didn't make
that feasible.
I find the reservation of potential errno macro names annoying.
That turns out to not be true. fdopendir(3) was added in Issue
7 of the Single Unix Specification (aka POSIX). https://pubs.opengroup.org/onlinepubs/9799919799/functions/fdopendir.html ftw(3)/nftw(3) are used more often than opendir(3) in real world code.
Kaz Kylheku <643-408-1753@kylheku.com> writes:
On 2025-06-10, Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
I find the reservation of potential errno macro names annoying.
If the standard contained /no/ statements about what a given header
file may reserve, then /any/ identifier whatsoever would be a potential
clash.
The errno reservation is kind of good because implementors often extend
the set of errno constants. POSIX has a lot more of them than ISO C, and
there are some vendor-specific ones.
Anyway, you can safely ignore the reservation theatre, and just
deal with clashes that happen, when they happen. (If you're lucky,
that could just be never).
You can do that, but a new clash could happen when your code is
compiled on a system that defines an errno macro that you haven't
seen before.
Anyway, ISO C, POSIX and vendors have historically introduced new
identifiers in spaces that were not previously declared as reserved.
If you're ever hit by that, you will feel like a completel sucker if
you've religiously adhered to namespaces from your end.
Yes, that can happen, but no, I won't feel like a complete sucker.
If I define my own strfoo() function and a new edition of the standard defines strfoo() in <string.h>, the clash is my fault,and I could have avoided it by defining str_foo().
Nothing can prevent all possible name clashes, but I like to follow the
rules in the standard that let me prevent some of them.
[fdopendir] doesn't make a difference for the discussed point.
On 28/05/2025 13:41, Tim Rentsch wrote:
Richard Heathfield <rjh@cpax.org.uk> writes:
On 24/05/2025 06:32, Tim Rentsch wrote:
Richard Heathfield <rjh@cpax.org.uk> writes:
On 23/05/2025 13:43, Tim Rentsch wrote:
Richard Heathfield <rjh@cpax.org.uk> writes:
On 20/05/2025 10:18, Keith Thompson wrote:
C90 will never be extended.
And for that reason it will always be valuable. Stability
has a value all its own.
C99 is just as stable as C90, and has been for well over a
decade.
Sure, but it's a different stable.
If it were the same stable, it would be C90.
C99 isn't C90, therefore it isn't the same stable.
If you tell me C99 is a rock, I will not doubt you. But the C90
rock it most certainly isn't.
Now you're being silly.
No, sir. If you want to play that game, you can play it with
yourself. I know that you are perfectly capable of polite
conversation, so I see no reason to endure the opposite.
I don't think I'm being impolite.
Then we are again in disagreement, and it seems obvious that it would
be foolishly optimistic of me to expect to be able to resolve the
matter. I'll tell Thunderbird to leave it there.
On 30/05/2025 10:20, David Brown wrote:
On 29/05/2025 14:38, Richard Heathfield wrote:
This really is a very simple point, but perhaps a simple analogy
will help to clarify it. You don't throw out your 3/4" just
because you've bought a 19mm. There is room for both in the
toolbox, and why write 3/4" on your new spanner? It /isn't/ a
3/4" spanner even though it's very like it, so why pretend
otherwise?
Your analogy does not cover C99 vs C90.
It does if we can construct a program that is legal C90 but not
legal C99, which is easy enough, or (slightly harder but still not
that hard) a program that is legal in both dialects but which
gives different output under C99 than it does for C90.
$ cat c9099.c; \
gcc -W -Wall -ansi -pedantic -o c90 c9099.c; \
gcc -o c99 c9099.c; \
./c90; \
./c99
#include <stdio.h>
int main(void)
{
int a = 42;
int b = a //* comment */ 6;
;
printf("Soln = %d\n", b);
return 0;
}
Soln = 7
Soln = 42
Obviously it's a contrived example, but then examples pointing out
the consequences of language differences invariably are.
"Lawrence D'Oliveiro" <ldo@nz.invalid> wrote in message news:100jhor$2lgt3$4@dont-email.me...
On Wed, 21 May 2025 10:23:27 +1000, Paul Edwards wrote:...
The C90 standard deferred to MVS - probably still does -
and says that you can't open a file as "w", then read it as
"rb" and write (a new file) as "wb", and still access (the
new file) with "r".
I was shocked when I saw IBM's C library lose the newlines
when I did the above, and went to look at the standard to
show that IBM was violating C90 - but it turns out they
weren't.
That sort of means you can't write a "zip" program portably,
against the theoretical C90 file system. Or you would have
to have flags to say which files need to be opened as text
or binary.
I do not agree with IBM's C library, and PDPCLIB does
not have that behavior, so that constraint could potentially
be dropped in a C90+ standard.
BFN. Paul.
Lawrence D'Oliveiro <ldo@nz.invalid> writes:
On Thu, 22 May 2025 02:20:36 +0200, Jakob Bohm wrote:
The later UNIX-like file system NTFS ...
It was (and is) hard to describe NTFS as “Unix-like”. Yes, it had
hierarchical directories and long(ish) file names, but not much else.
Drive letters were inherited (indirectly) from DEC OSes, of all things,
along with an insistence on having filename extensions, restrictions on
characters allowed in names etc.
I don't believe that NTFS requires filename extensions.
My understanding is that a file name is stored as a single string
(with some restrictions).
Symlinks were not even added until Windows Vista. And you have to have
special privileges to create them.
Do note one more thing.
The C90 standard deferred to MVS - probably still does -
and says that you can't open a file as "w", then read it as
"rb" and write (a new file) as "wb", and still access (the
new file) with "r".
I was shocked when I saw IBM's C library lose the newlines
when I did the above, and went to look at the standard to
show that IBM was violating C90 - but it turns out they
weren't.
That sort of means you can't write a "zip" program portably,
against the theoretical C90 file system.
Or you would have
to have flags to say which files need to be opened as text
or binary.
On 2025-05-21, Paul Edwards <mutazilah@gmail.com> wrote:...
Do note one more thing.
The C90 standard deferred to MVS - probably still does -
and says that you can't open a file as "w", then read it as
"rb" and write (a new file) as "wb", and still access (the
new file) with "r".
You mean:
- write a text file, close it; then
- open it as a binary file and copy the bytes to another, new binary file; and
- finally, read the new binary file in text mode?
I don't see how that would be allowed to lose any newlines.
You made a bitwise copy of the file.
A recent draft of ISO C says "A binary stream is an ordered sequence of characters that can transparently record internal data. Data read in
from a binary stream shall compare equal to the data that were earlier written out to that stream, under the same implementation. Such a stream
may, however, have an implementation- defined number of null characters appended to the end of the stream."
I have C90 somewhere, I can look that up too, but I suspect it was
the same.
I was shocked when I saw IBM's C library lose the newlines
when I did the above, and went to look at the standard to
show that IBM was violating C90 - but it turns out they
weren't.
Sysop: | DaiTengu |
---|---|
Location: | Appleton, WI |
Users: | 1,064 |
Nodes: | 10 (0 / 10) |
Uptime: | 159:15:02 |
Calls: | 13,691 |
Calls today: | 1 |
Files: | 186,936 |
D/L today: |
7,070 files (2,120M bytes) |
Messages: | 2,411,313 |