On 11/20/2024 2:21 AM, Muttley@DastartdlyHQ.org wrote:
On Tue, 19 Nov 2024 18:43:48 -0800
merlyn@stonehenge.com (Randal L. Schwartz) boring babbled:
"Lawrence" == Lawrence D'Oliveiro <ldo@nz.invalid> writes:
Lawrence> Perl was the language that made regular expressions
Lawrence> sexy. Because it made them easy to use.
I'm often reminded of this as I've been coding very little in Perl these >>> days, and a lot more in languages like Dart, where the regex feels like
a clumsy bolt-on rather than a proper first-class citizen.
Regex itself is clumsy beyond simple search and replace patterns. A lot of >> stuff I've seen done in regex would have better done procedurally at the
expense of slightly more code but a LOT more readability.
Definitely. The most relevant statement about regexps is this:
Some people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems.
Obviously regexps are very useful and commonplace but if you find you
have to use some online site or other tools to help you write/understand
one or just generally need more than a couple of minutes to
write/understand it then it's time to back off and figure out a better
way to write your code for the sake of whoever has to read it 6 months
later (and usually for robustness too as it's hard to be sure all rainy
day cases are handled correctly in a lengthy and/or complicated regexp).
On Wed, 20 Nov 2024 11:51:11 +0100
Janis Papanagnou <janis_papanagnou+ng@hotmail.com> boring babbled:
On 20.11.2024 09:21, Muttley@DastartdlyHQ.org wrote:
On Tue, 19 Nov 2024 18:43:48 -0800which
merlyn@stonehenge.com (Randal L. Schwartz) boring babbled:
I'm often reminded of this as I've been coding very little in Perl these >>>> days, and a lot more in languages like Dart, where the regex feels like >>>> a clumsy bolt-on rather than a proper first-class citizen.
Regex itself is clumsy beyond simple search and replace patterns. A lot of >>> stuff I've seen done in regex would have better done procedurally at the >>> expense of slightly more code but a LOT more readability. Also given its >>> effectively a compact language with its own grammar and syntax IMO it should
not be the core part of any language as it can lead to a syntatic mess,
is what often happens with Perl.
I wouldn't look at it that way. I've seen Regexps as part of languages
usually in well defined syntactical contexts. For example, like strings
are enclosed in "...", Regexps could be seen within /.../ delimiters.
GNU Awk (in recent versions) went towards first class "strongly typed"
Regexps which are then denoted by the @/.../ syntax.
I'm curious what you mean by Regexps presented in a "procedural" form.
Can you give some examples?
Anything that can be done in regex can obviously also be done procedurally. At the point regex expression become unwieldy - usually when substitution variables raise their heads - I prefer procedural code as its also often easier to debug.
In practice, given that a Regexp conforms to a FSA, any Regexp can be
precompiled and used multiple times. The thing I had used in Java - it
Precompiled regex is no more efficient than precompiled anything , its all just assembler at the bottom.
then operate on that same object. (Since there's still typical Regexp
syntax involved I suppose that is not what you meant by "procedural"?)
If you don't know the different between declarative syntax like regex and procedural syntax then there's not much point continuing this discussion.
Definitely. The most relevant statement about regexps is this:
Some people, when confronted with a problem, think "I know, I'll use
regular expressions." Now they have two problems.
Obviously regexps are very useful and commonplace but if you find you
have to use some online site or other tools to help you write/understand
one or just generally need more than a couple of minutes to
write/understand it then it's time to back off and figure out a better
way to write your code for the sake of whoever has to read it 6 months
later (and usually for robustness too as it's hard to be sure all rainy
day cases are handled correctly in a lengthy and/or complicated regexp).
On 20.11.2024 12:30, Muttley@DastartdlyHQ.org wrote:
Anything that can be done in regex can obviously also be done procedurally. >> At the point regex expression become unwieldy - usually when substitution
variables raise their heads - I prefer procedural code as its also often
easier to debug.
You haven't even tried to honestly answer my (serious) question.
With your statement above and your hostility below, it rather seems
Personally I think that writing bulky procedural stuff for something
like [0-9]+ can only be much worse, and that further abbreviations
like \d+ are the better direction to go if targeting a good interface.
YMMV.
With your statement above and your hostility below, it rather seems
If you think my reply was hostile then I suggest you go find a safe space
and cuddle your teddy bear snowflake.
There's surely no reason why anyone could ever think you were inclined
to substitute verbal aggression for arguments.
Edge cases are regex achilles heal, eg an expression that only accounted
for 1 -> N chars, not 0 -> N, or matches in the middle but not at the
ends.
[...]
With your statement above and your hostility below, it rather seems
If you think my reply was hostile then I suggest you go find a safe space
and cuddle your teddy bear snowflake.
There's surely no reason why anyone could ever think you were inclined
to substitute verbal aggression for arguments.
On Wed, 20 Nov 2024 12:27:54 -0000 (UTC), Muttley wrote:
Edge cases are regex achilles heal, eg an expression that only accounted
for 1 -> N chars, not 0 -> N, or matches in the middle but not at the
ends.
ThatrCOs what rCL^rCY and rCL$rCY are for.
On Wed, 20 Nov 2024 17:54:22 +0000
Rainer Weikusat <rweikusat@talktalk.net> wrote:
There's surely no reason why anyone could ever think you were inclined
to substitute verbal aggression for arguments.
I mean, it's his whole thing - why would he stop now?
"Rainer" == Rainer Weikusat <rweikusat@talktalk.net> writes:
On Wed, 20 Nov 2024 17:54:22 +0000
Rainer Weikusat <rweikusat@talktalk.net> wrote:
There's surely no reason why anyone could ever think you were inclined
to substitute verbal aggression for arguments.
I mean, it's his whole thing - why would he stop now?
Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
[...]
Personally I think that writing bulky procedural stuff for something
like [0-9]+ can only be much worse, and that further abbreviations
like \d+ are the better direction to go if targeting a good interface.
YMMV.
Assuming that p is a pointer to the current position in a string, e is a >pointer to the end of it (ie, point just past the last byte) and -
that's important - both are pointers to unsigned quantities, the 'bulky'
C equivalent of [0-9]+ is
while (p < e && *p - '0' < 10) ++p;
That's not too bad. And it's really a hell lot faster than a
general-purpose automaton programmed to recognize the same pattern
(which might not matter most of the time, but sometimes, it does).
Rainer Weikusat <rweikusat@talktalk.net> wrote:
Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
[...]
Personally I think that writing bulky procedural stuff for something
like [0-9]+ can only be much worse, and that further abbreviations
like \d+ are the better direction to go if targeting a good interface.
YMMV.
Assuming that p is a pointer to the current position in a string, e is a >>pointer to the end of it (ie, point just past the last byte) and -
that's important - both are pointers to unsigned quantities, the 'bulky'
C equivalent of [0-9]+ is
while (p < e && *p - '0' < 10) ++p;
That's not too bad. And it's really a hell lot faster than a >>general-purpose automaton programmed to recognize the same pattern
(which might not matter most of the time, but sometimes, it does).
It's also not exactly right. `[0-9]+` would match one or more
characters; this possibly matches 0 (ie, if `p` pointed to
something that wasn't a digit).
Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
Assuming that p is a pointer to the current position in a string, e is a pointer to the end of it (ie, point just past the last byte) and -
that's important - both are pointers to unsigned quantities, the 'bulky'
C equivalent of [0-9]+ is
while (p < e && *p - '0' < 10) ++p;
That's not too bad. And it's really a hell lot faster than a
general-purpose automaton programmed to recognize the same pattern
(which might not matter most of the time, but sometimes, it does).
In article <20241120100347.00005f10@gmail.com>,
John Ames <commodorejohn@gmail.com> wrote:
On Wed, 20 Nov 2024 17:54:22 +0000
Rainer Weikusat <rweikusat@talktalk.net> wrote:
There's surely no reason why anyone could ever think you were inclined
to substitute verbal aggression for arguments.
I mean, it's his whole thing - why would he stop now?
This is the guy who didn't know what a compiler is, right?
Whats it like being so wet? Do you get cold easily?
I have zero time
On 2024-11-20, Rainer Weikusat <rweikusat@talktalk.net> wrote:
Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
Assuming that p is a pointer to the current position in a string, e is a
pointer to the end of it (ie, point just past the last byte) and -
that's important - both are pointers to unsigned quantities, the 'bulky'
C equivalent of [0-9]+ is
while (p < e && *p - '0' < 10) ++p;
That's not too bad. And it's really a hell lot faster than a
general-purpose automaton programmed to recognize the same pattern
(which might not matter most of the time, but sometimes, it does).
int
main(int argc, char **argv) {
unsigned char *p, *e;
unsigned char mystr[] = "12#45XY ";
p = mystr;
e = mystr + sizeof(mystr);
while (p < e && *p - '0' < 10) ++p;
size_t xlen = p-mystr;
printf("digits: '%.*s'\n", (int) xlen, mystr);
printf("mystr %p p %p e %p\n", mystr, p, e);
printf("xlen %zd\n", xlen);
return 0;
}
./a.out
digits: '12#45'
mystr 0x7ffc92ac55ff p 0x7ffc92ac5604 e 0x7ffc92ac5608
xlen 5
Rainer> -| I used to use a JSON parser written in OO-Perl which made"Rainer" == Rainer Weikusat <rweikusat@talktalk.net> writes:
Rainer> extensive use of regexes for that. I've recently replaced that Rainer> with a C/XS version which - while slightly larger (617 vs 410
Rainer> lines of text) - is over a hundred times faster and conceptually Rainer> simpler at the same time.
I wonder if that was my famous "JSON parser in a single regex" from https://www.perlmonks.org/?node_id=995856, or from one of the two CPAN modules that incorporated it.
mas@a4.home writes:
On 2024-11-20, Rainer Weikusat <rweikusat@talktalk.net> wrote:
Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
Assuming that p is a pointer to the current position in a string, e is a >>> pointer to the end of it (ie, point just past the last byte) and -
that's important - both are pointers to unsigned quantities, the 'bulky' >>> C equivalent of [0-9]+ is
while (p < e && *p - '0' < 10) ++p;
That's not too bad. And it's really a hell lot faster than a
general-purpose automaton programmed to recognize the same pattern
(which might not matter most of the time, but sometimes, it does).
int
main(int argc, char **argv) {
unsigned char *p, *e;
unsigned char mystr[] = "12#45XY ";
p = mystr;
e = mystr + sizeof(mystr);
while (p < e && *p - '0' < 10) ++p;
size_t xlen = p-mystr;
printf("digits: '%.*s'\n", (int) xlen, mystr);
printf("mystr %p p %p e %p\n", mystr, p, e);
printf("xlen %zd\n", xlen);
return 0;
}
./a.out
digits: '12#45'
mystr 0x7ffc92ac55ff p 0x7ffc92ac5604 e 0x7ffc92ac5608
xlen 5
Indeed. Rainer's while loop should be using isdigit(*p).
Indeed. Rainer's while loop should be using isdigit(*p).
On 2024-11-20, Rainer Weikusat <rweikusat@talktalk.net> wrote:
Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
Assuming that p is a pointer to the current position in a string, e is a
pointer to the end of it (ie, point just past the last byte) and -
that's important - both are pointers to unsigned quantities, the 'bulky'
C equivalent of [0-9]+ is
while (p < e && *p - '0' < 10) ++p;
That's not too bad. And it's really a hell lot faster than a
general-purpose automaton programmed to recognize the same pattern
(which might not matter most of the time, but sometimes, it does).
int
main(int argc, char **argv) {
unsigned char *p, *e;
unsigned char mystr[] = "12#45XY ";
p = mystr;
e = mystr + sizeof(mystr);
while (p < e && *p - '0' < 10) ++p;
On 20.11.2024 09:21, Muttley@DastartdlyHQ.org wrote:
Regex itself is clumsy beyond simple search and replace patterns. A lot of >> stuff I've seen done in regex would have better done procedurally at the
expense of slightly more code but a LOT more readability. Also given its
effectively a compact language with its own grammar and syntax IMO it should >> not be the core part of any language as it can lead to a syntatic mess, which
is what often happens with Perl.
I wouldn't look at it that way. I've seen Regexps as part of languages usually in well defined syntactical contexts. For example, like strings
are enclosed in "...", Regexps could be seen within /.../ delimiters.
GNU Awk (in recent versions) went towards first class "strongly typed" Regexps which are then denoted by the @/.../ syntax.
I'm curious what you mean by Regexps presented in a "procedural" form.
Can you give some examples?
On Wed, 20 Nov 2024 21:43:41 -0000 (UTC)
Lawrence D'Oliveiro <ldo@nz.invalid> boring babbled:
On Wed, 20 Nov 2024 12:27:54 -0000 (UTC), Muttley wrote:
Edge cases are regex achilles heal, eg an expression that only
accounted for 1 -> N chars, not 0 -> N, or matches in the middle but
not at the ends.
ThatrCOs what rCL^rCY and rCL$rCY are for.
Yes, but people forget about those (literal) edge cases.
On 2024-11-20, Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
I'm curious what you mean by Regexps presented in a "procedural" form.
Can you give some examples?
Here is an example: using a regex match to capture a C comment /* ... */
in Lex compared to just recognizing the start sequence /* and handling
the discarding of the comment in the action.
Without non-greedy repetition matching, the regex for a C comment is
quite obtuse. The procedural handling is straightforward: read
characters until you see a * immediately followed by a /.
Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
Personally I think that writing bulky procedural stuff for something
like [0-9]+ can only be much worse, and that further abbreviations
like \d+ are the better direction to go if targeting a good interface.
YMMV.
Assuming that p is a pointer to the current position in a string, e is a pointer to the end of it (ie, point just past the last byte) and -
that's important - both are pointers to unsigned quantities, the 'bulky'
C equivalent of [0-9]+ is
while (p < e && *p - '0' < 10) ++p;
That's not too bad. And it's really a hell lot faster than a
general-purpose automaton programmed to recognize the same pattern
(which might not matter most of the time, but sometimes, it does).
[...]
In the wild, you see regexes being used for all sorts of stupid stuff,
like checking whether numeric input is in a certain range, rather than converting it to a number and doing an arithmetic check.
On Thu, 21 Nov 2024 08:15:41 -0000 (UTC), Muttley wrote:
On Wed, 20 Nov 2024 21:43:41 -0000 (UTC)
Lawrence D'Oliveiro <ldo@nz.invalid> boring babbled:
[...]
ThatrCOs what rCL^rCY and rCL$rCY are for.
Yes, but people forget about those (literal) edge cases.
Those of us who are accustomed to using regexes do not.
Another handy one is rCL\brCY for word boundaries.
On 20.11.2024 18:50, Rainer Weikusat wrote:
Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
Personally I think that writing bulky procedural stuff for something
like [0-9]+ can only be much worse, and that further abbreviations
like \d+ are the better direction to go if targeting a good interface.
YMMV.
Assuming that p is a pointer to the current position in a string, e is a
pointer to the end of it (ie, point just past the last byte) and -
that's important - both are pointers to unsigned quantities, the 'bulky'
C equivalent of [0-9]+ is
while (p < e && *p - '0' < 10) ++p;
That's not too bad. And it's really a hell lot faster than a
general-purpose automaton programmed to recognize the same pattern
(which might not matter most of the time, but sometimes, it does).
Okay, I see where you're coming from (and especially in that simple
case).
Personally (and YMMV), even here in this simple case I think that
using pointers is not better but worse - and anyway isn't [in this
form] available in most languages;
in other cases (and languages)
such constructs get yet more clumsy, and for my not very complex
example - /[0-9]+(ABC)?x*foo/ - even a "catastrophe" concerning
readability, error-proneness, and maintainability.
If that is what the other poster meant I'm fine with your answer;
there's no need to even consider abandoning regular expressions
in favor of explicitly codified parsing.
cross@spitfire.i.gajendra.net (Dan Cross) writes:
Rainer Weikusat <rweikusat@talktalk.net> wrote:
Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
[...]
Personally I think that writing bulky procedural stuff for something
like [0-9]+ can only be much worse, and that further abbreviations
like \d+ are the better direction to go if targeting a good interface. >>>> YMMV.
Assuming that p is a pointer to the current position in a string, e is a >>>pointer to the end of it (ie, point just past the last byte) and -
that's important - both are pointers to unsigned quantities, the 'bulky' >>>C equivalent of [0-9]+ is
while (p < e && *p - '0' < 10) ++p;
That's not too bad. And it's really a hell lot faster than a >>>general-purpose automaton programmed to recognize the same pattern
(which might not matter most of the time, but sometimes, it does).
It's also not exactly right. `[0-9]+` would match one or more
characters; this possibly matches 0 (ie, if `p` pointed to
something that wasn't a digit).
The regex won't match any digits if there aren't any. In this case, the
match will fail. I didn't include the code for handling that because it >seemed pretty pointless for the example.
mas@a4.home writes:
On 2024-11-20, Rainer Weikusat <rweikusat@talktalk.net> wrote:
Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
Assuming that p is a pointer to the current position in a string, e is a >>> pointer to the end of it (ie, point just past the last byte) and -
that's important - both are pointers to unsigned quantities, the 'bulky' >>> C equivalent of [0-9]+ is
while (p < e && *p - '0' < 10) ++p;
That's not too bad. And it's really a hell lot faster than a
general-purpose automaton programmed to recognize the same pattern
(which might not matter most of the time, but sometimes, it does).
int
main(int argc, char **argv) {
unsigned char *p, *e;
unsigned char mystr[] = "12#45XY ";
p = mystr;
e = mystr + sizeof(mystr);
while (p < e && *p - '0' < 10) ++p;
The code I'm actually using is
while (p < e && (unsigned)*p - '0' < 10)
++p;
I just omitted that when posting this beause I mistakenly assumed that
it probably wasn't needed, ;-). You could have pointed this out instead
of trying to dress it up as some sort of mystery problem-|. Especially as
I did mention that using unsigned arithmetic was necessary (should
really be self-evident).
In article <87o728qzbc.fsf@doppelsaurus.mobileactivedefense.com>,
Rainer Weikusat <rweikusat@talktalk.net> wrote:
mas@a4.home writes:
On 2024-11-20, Rainer Weikusat <rweikusat@talktalk.net> wrote:
Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
Assuming that p is a pointer to the current position in a string, e is a >>>> pointer to the end of it (ie, point just past the last byte) and -
that's important - both are pointers to unsigned quantities, the 'bulky' >>>> C equivalent of [0-9]+ is
while (p < e && *p - '0' < 10) ++p;
That's not too bad. And it's really a hell lot faster than a
general-purpose automaton programmed to recognize the same pattern
(which might not matter most of the time, but sometimes, it does).
int
main(int argc, char **argv) {
unsigned char *p, *e;
unsigned char mystr[] = "12#45XY ";
p = mystr;
e = mystr + sizeof(mystr);
while (p < e && *p - '0' < 10) ++p;
The code I'm actually using is
while (p < e && (unsigned)*p - '0' < 10)
++p;
I just omitted that when posting this beause I mistakenly assumed that
it probably wasn't needed, ;-). You could have pointed this out instead
of trying to dress it up as some sort of mystery problem|e-|. Especially as >>I did mention that using unsigned arithmetic was necessary (should
really be self-evident).
Well, no, not exactly. You said that it was important that the
pointers point to unsigned quantities, but that wasn't the
issue.
Rainer Weikusat <rweikusat@talktalk.net> wrote:
cross@spitfire.i.gajendra.net (Dan Cross) writes:
Rainer Weikusat <rweikusat@talktalk.net> wrote:
Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
[...]
Personally I think that writing bulky procedural stuff for something >>>>> like [0-9]+ can only be much worse, and that further abbreviations
like \d+ are the better direction to go if targeting a good interface. >>>>> YMMV.
Assuming that p is a pointer to the current position in a string, e is a >>>>pointer to the end of it (ie, point just past the last byte) and - >>>>that's important - both are pointers to unsigned quantities, the 'bulky' >>>>C equivalent of [0-9]+ is
while (p < e && *p - '0' < 10) ++p;
That's not too bad. And it's really a hell lot faster than a >>>>general-purpose automaton programmed to recognize the same pattern >>>>(which might not matter most of the time, but sometimes, it does).
It's also not exactly right. `[0-9]+` would match one or more
characters; this possibly matches 0 (ie, if `p` pointed to
something that wasn't a digit).
The regex won't match any digits if there aren't any. In this case, the >>match will fail. I didn't include the code for handling that because it >>seemed pretty pointless for the example.
That's rather the point though, isn't it? The program snippet
(modulo the promotion to signed int via the "usual arithmetic
conversions" before the subtraction and comparison giving you
unexpected values; nothing to do with whether `char` is signed
or not) is a snippet that advances a pointer while it points to
a digit, starting at the current pointer position; that is, it
just increments a pointer over a run of digits.
But that's not the same as a regex matcher, which has a semantic
notion of success or failure. I could run your snippet against
a string such as, say, "ZZZZZZ" and it would "succeed" just as
it would against an empty string or a string of one or more
digits.
By the way, something that _would_ match `^[0-9]+$` might be:
Something which would match [0-9]+ in its first argument (if any) would
be:
#include "string.h"
#include "stdlib.h"
int main(int argc, char **argv)
{
char *p;
unsigned c;
p = argv[1];
if (!p) exit(1);
while (c = *p, c && c - '0' > 10) ++p;
cross@spitfire.i.gajendra.net (Dan Cross) writes:
Rainer Weikusat <rweikusat@talktalk.net> wrote: >>>cross@spitfire.i.gajendra.net (Dan Cross) writes:
[snip]
It's also not exactly right. `[0-9]+` would match one or more
characters; this possibly matches 0 (ie, if `p` pointed to
something that wasn't a digit).
The regex won't match any digits if there aren't any. In this case, the >>>match will fail. I didn't include the code for handling that because it >>>seemed pretty pointless for the example.
That's rather the point though, isn't it? The program snippet
(modulo the promotion to signed int via the "usual arithmetic
conversions" before the subtraction and comparison giving you
unexpected values; nothing to do with whether `char` is signed
or not) is a snippet that advances a pointer while it points to
a digit, starting at the current pointer position; that is, it
just increments a pointer over a run of digits.
That's the core part of matching someting equivalent to the regex [0-9]+
and the only part of it is which is at least remotely interesting.
But that's not the same as a regex matcher, which has a semantic
notion of success or failure. I could run your snippet against
a string such as, say, "ZZZZZZ" and it would "succeed" just as
it would against an empty string or a string of one or more
digits.
Why do you believe that p being equivalent to the starting position
would be considered a "successful match", considering that this
obviously doesn't make any sense?
[...]
By the way, something that _would_ match `^[0-9]+$` might be:
[too much code]
Something which would match [0-9]+ in its first argument (if any) would
be:
#include "string.h"
#include "stdlib.h"
int main(int argc, char **argv)
{
char *p;
unsigned c;
p = argv[1];
if (!p) exit(1);
while (c = *p, c && c - '0' > 10) ++p;
if (!c) exit(1);
return 0;
}
but that's 14 lines of text, 13 of which have absolutely no relation to
the problem of recognizing a digit.
Rainer Weikusat <rweikusat@talktalk.net> writes:
[...]
Something which would match [0-9]+ in its first argument (if any) would
be:
#include "string.h"
#include "stdlib.h"
int main(int argc, char **argv)
{
char *p;
unsigned c;
p = argv[1];
if (!p) exit(1);
while (c = *p, c && c - '0' > 10) ++p;
This needs to be
while (c = *p, c && c - '0' > 9) ++p
In article <87zflrs1ti.fsf@doppelsaurus.mobileactivedefense.com>,
Rainer Weikusat <rweikusat@talktalk.net> wrote:
Rainer Weikusat <rweikusat@talktalk.net> writes:
[...]
Something which would match [0-9]+ in its first argument (if any) would
be:
#include "string.h"
#include "stdlib.h"
int main(int argc, char **argv)
{
char *p;
unsigned c;
p = argv[1];
if (!p) exit(1);
while (c = *p, c && c - '0' > 10) ++p;
This needs to be
while (c = *p, c && c - '0' > 9) ++p
No, that's still wrong. Try actually running it.
cross@spitfire.i.gajendra.net (Dan Cross) writes:
In article <87zflrs1ti.fsf@doppelsaurus.mobileactivedefense.com>,
Rainer Weikusat <rweikusat@talktalk.net> wrote:
Rainer Weikusat <rweikusat@talktalk.net> writes:
[...]
Something which would match [0-9]+ in its first argument (if any) would >>>> be:
#include "string.h"
#include "stdlib.h"
int main(int argc, char **argv)
{
char *p;
unsigned c;
p = argv[1];
if (!p) exit(1);
while (c = *p, c && c - '0' > 10) ++p;
This needs to be
while (c = *p, c && c - '0' > 9) ++p
No, that's still wrong. Try actually running it.
If you know something that's wrong with that, why not write it instead
of utilizing the claim for pointless (and wrong) snide remarks?
In article <87v7wfrx26.fsf@doppelsaurus.mobileactivedefense.com>,
Rainer Weikusat <rweikusat@talktalk.net> wrote: >>cross@spitfire.i.gajendra.net (Dan Cross) writes:
In article <87zflrs1ti.fsf@doppelsaurus.mobileactivedefense.com>,
Rainer Weikusat <rweikusat@talktalk.net> wrote:
Rainer Weikusat <rweikusat@talktalk.net> writes:
[...]
Something which would match [0-9]+ in its first argument (if any) would >>>>> be:
#include "string.h"
#include "stdlib.h"
int main(int argc, char **argv)
{
char *p;
unsigned c;
p = argv[1];
if (!p) exit(1);
while (c = *p, c && c - '0' > 10) ++p;
This needs to be
while (c = *p, c && c - '0' > 9) ++p
No, that's still wrong. Try actually running it.
If you know something that's wrong with that, why not write it instead
of utilizing the claim for pointless (and wrong) snide remarks?
I did, at length, in my other post.
Rainer Weikusat <rweikusat@talktalk.net> wrote:
cross@spitfire.i.gajendra.net (Dan Cross) writes:
Rainer Weikusat <rweikusat@talktalk.net> wrote: >>>>cross@spitfire.i.gajendra.net (Dan Cross) writes:
[snip]
It's also not exactly right. `[0-9]+` would match one or more
characters; this possibly matches 0 (ie, if `p` pointed to
something that wasn't a digit).
The regex won't match any digits if there aren't any. In this case, the >>>>match will fail. I didn't include the code for handling that because it >>>>seemed pretty pointless for the example.
That's rather the point though, isn't it? The program snippet
(modulo the promotion to signed int via the "usual arithmetic
conversions" before the subtraction and comparison giving you
unexpected values; nothing to do with whether `char` is signed
or not) is a snippet that advances a pointer while it points to
a digit, starting at the current pointer position; that is, it
just increments a pointer over a run of digits.
That's the core part of matching someting equivalent to the regex [0-9]+ >>and the only part of it is which is at least remotely interesting.
Not really, no. The interesting thing in this case appears to
be knowing whether or not the match succeeded, but you omited
that part.
But that's not the same as a regex matcher, which has a semantic
notion of success or failure. I could run your snippet against
a string such as, say, "ZZZZZZ" and it would "succeed" just as
it would against an empty string or a string of one or more
digits.
Why do you believe that p being equivalent to the starting position
would be considered a "successful match", considering that this
obviously doesn't make any sense?
Because absent any surrounding context, there's no indication
that the source is even saved.
Something which would match [0-9]+ in its first argument (if any) would
be:
#include "string.h"
#include "stdlib.h"
int main(int argc, char **argv)
{
char *p;
unsigned c;
p = argv[1];
if (!p) exit(1);
while (c = *p, c && c - '0' > 10) ++p;
if (!c) exit(1);
return 0;
}
but that's 14 lines of text, 13 of which have absolutely no relation to
the problem of recognizing a digit.
This is wrong in many ways. Did you actually test that program?
First of all, why `"string.h"` and not `<string.h>`? Ok, that's
not technically an error, but it's certainly unconventional, and
raises questions that are ultimately a distraction.
Second, suppose that `argc==0` (yes, this can happen under
POSIX).
Third, the loop: why `> 10`? Don't you mean `< 10`? You are
trying to match digits, not non-digits.
Fourth, you exit with failure (`exit(1)`) if `!p` *and* if `!c`
at the end, but `!c` there means you've reached the end of the
string; which should be success.
Something which would match [0-9]+ in its first argument (if any) would >>>be:
#include "string.h"
#include "stdlib.h"
int main(int argc, char **argv)
{
char *p;
unsigned c;
p = argv[1];
if (!p) exit(1);
while (c = *p, c && c - '0' > 10) ++p;
if (!c) exit(1);
return 0;
}
but that's 14 lines of text, 13 of which have absolutely no relation to >>>the problem of recognizing a digit.
This is wrong in many ways. Did you actually test that program?
First of all, why `"string.h"` and not `<string.h>`? Ok, that's
not technically an error, but it's certainly unconventional, and
raises questions that are ultimately a distraction.
Such as your paragraph above.
Second, suppose that `argc==0` (yes, this can happen under
POSIX).
It can happen in case of some piece of functionally hostile software >intentionally creating such a situation. Tangential, irrelevant
point. If you break it, you get to keep the parts.
Third, the loop: why `> 10`? Don't you mean `< 10`? You are
trying to match digits, not non-digits.
Mistake I made. The opposite of < 10 is > 9.
Fourth, you exit with failure (`exit(1)`) if `!p` *and* if `!c`
at the end, but `!c` there means you've reached the end of the
string; which should be success.
Mistake you made: [0-9]+ matches if there's at least one digit in the
string. That's why the loop terminates once one was found. In this case,
c cannot be 0.
On Thu, 21 Nov 2024 19:12:03 -0000 (UTC)
Kaz Kylheku <643-408-1753@kylheku.com> boring babbled:
On 2024-11-20, Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
I'm curious what you mean by Regexps presented in a "procedural" form.
Can you give some examples?
Here is an example: using a regex match to capture a C comment /* ... */
in Lex compared to just recognizing the start sequence /* and handling
the discarding of the comment in the action.
Without non-greedy repetition matching, the regex for a C comment is
quite obtuse. The procedural handling is straightforward: read
characters until you see a * immediately followed by a /.
Its not that simple I'm afraid since comments can be commented out.
eg:
// int i; /*
int j;
/*
int k;
*/
++j;
A C99 and C++ compiler would see "int j" and compile it, a regex would
simply remove everything from the first /* to */.
Also the same probably applies to #ifdef's.
cross@spitfire.i.gajendra.net (Dan Cross) writes:
Rainer Weikusat <rweikusat@talktalk.net> wrote: >>>cross@spitfire.i.gajendra.net (Dan Cross) writes:
Rainer Weikusat <rweikusat@talktalk.net> wrote:
Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
[...]
Personally I think that writing bulky procedural stuff for something >>>>>> like [0-9]+ can only be much worse, and that further abbreviations >>>>>> like \d+ are the better direction to go if targeting a good interface. >>>>>> YMMV.
Assuming that p is a pointer to the current position in a string, e is a >>>>>pointer to the end of it (ie, point just past the last byte) and - >>>>>that's important - both are pointers to unsigned quantities, the 'bulky' >>>>>C equivalent of [0-9]+ is
while (p < e && *p - '0' < 10) ++p;
That's not too bad. And it's really a hell lot faster than a >>>>>general-purpose automaton programmed to recognize the same pattern >>>>>(which might not matter most of the time, but sometimes, it does).
It's also not exactly right. `[0-9]+` would match one or more
characters; this possibly matches 0 (ie, if `p` pointed to
something that wasn't a digit).
The regex won't match any digits if there aren't any. In this case, the >>>match will fail. I didn't include the code for handling that because it >>>seemed pretty pointless for the example.
That's rather the point though, isn't it? The program snippet
(modulo the promotion to signed int via the "usual arithmetic
conversions" before the subtraction and comparison giving you
unexpected values; nothing to do with whether `char` is signed
or not) is a snippet that advances a pointer while it points to
a digit, starting at the current pointer position; that is, it
just increments a pointer over a run of digits.
That's the core part of matching someting equivalent to the regex [0-9]+
and the only part of it is which is at least remotely interesting.
But that's not the same as a regex matcher, which has a semantic
notion of success or failure. I could run your snippet against
a string such as, say, "ZZZZZZ" and it would "succeed" just as
it would against an empty string or a string of one or more
digits.
Why do you believe that p being equivalent to the starting position
would be considered a "successful match", considering that this
obviously doesn't make any sense?
[...]
By the way, something that _would_ match `^[0-9]+$` might be:
[too much code]
Something which would match [0-9]+ in its first argument (if any) would
be:
#include "string.h"
#include "stdlib.h"
int main(int argc, char **argv)
{
char *p;
unsigned c;
p = argv[1];
if (!p) exit(1);
while (c = *p, c && c - '0' > 10) ++p;
if (!c) exit(1);
return 0;
}
but that's 14 lines of text, 13 of which have absolutely no relation to
the problem of recognizing a digit.
scott@slp53.sl.home (Scott Lurndal) writes:
Rainer Weikusat <rweikusat@talktalk.net> writes: >>>cross@spitfire.i.gajendra.net (Dan Cross) writes:
Rainer Weikusat <rweikusat@talktalk.net> wrote: >>>>>cross@spitfire.i.gajendra.net (Dan Cross) writes:
Rainer Weikusat <rweikusat@talktalk.net> wrote:
Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:It's also not exactly right. `[0-9]+` would match one or more
[...]
Personally I think that writing bulky procedural stuff for something >>>>>>>> like [0-9]+ can only be much worse, and that further abbreviations >>>>>>>> like \d+ are the better direction to go if targeting a good interface. >>>>>>>> YMMV.
Assuming that p is a pointer to the current position in a string, e is a >>>>>>>pointer to the end of it (ie, point just past the last byte) and - >>>>>>>that's important - both are pointers to unsigned quantities, the 'bulky' >>>>>>>C equivalent of [0-9]+ is
while (p < e && *p - '0' < 10) ++p;
That's not too bad. And it's really a hell lot faster than a >>>>>>>general-purpose automaton programmed to recognize the same pattern >>>>>>>(which might not matter most of the time, but sometimes, it does). >>>>>>
characters; this possibly matches 0 (ie, if `p` pointed to
something that wasn't a digit).
The regex won't match any digits if there aren't any. In this case, the >>>>>match will fail. I didn't include the code for handling that because it >>>>>seemed pretty pointless for the example.
That's rather the point though, isn't it? The program snippet
(modulo the promotion to signed int via the "usual arithmetic
conversions" before the subtraction and comparison giving you
unexpected values; nothing to do with whether `char` is signed
or not) is a snippet that advances a pointer while it points to
a digit, starting at the current pointer position; that is, it
just increments a pointer over a run of digits.
That's the core part of matching someting equivalent to the regex [0-9]+ >>>and the only part of it is which is at least remotely interesting.
But that's not the same as a regex matcher, which has a semantic
notion of success or failure. I could run your snippet against
a string such as, say, "ZZZZZZ" and it would "succeed" just as
it would against an empty string or a string of one or more
digits.
Why do you believe that p being equivalent to the starting position
would be considered a "successful match", considering that this
obviously doesn't make any sense?
[...]
By the way, something that _would_ match `^[0-9]+$` might be:
[too much code]
Something which would match [0-9]+ in its first argument (if any) would >>>be:
#include "string.h"
#include "stdlib.h"
int main(int argc, char **argv)
{
char *p;
unsigned c;
p = argv[1];
if (!p) exit(1);
while (c = *p, c && c - '0' > 10) ++p;
if (!c) exit(1);
return 0;
}
but that's 14 lines of text, 13 of which have absolutely no relation to >>>the problem of recognizing a digit.
Personally, I'd use:
Albeit this is limited to strings of digits that sum to less than >ULONG_MAX...
$ cat /tmp/a.c
#include <stdint.h>
#include <string.h>
int
main(int argc, const char **argv)
{
char *cp;
uint64_t value;
if (argc < 2) return 1;
value = strtoull(argv[1], &cp, 10);
if ((cp == argv[1])
|| (*cp != '\0')) {
return 1;
}
return 0;
}
$ cc -o /tmp/a /tmp/a.c
$ /tmp/a 13254
$ echo $?
0
$ /tmp/a 23v23
$ echo $?
1
On 21.11.2024 20:12, Kaz Kylheku wrote:
[...]
In the wild, you see regexes being used for all sorts of stupid stuff,
No one can prevent folks using features for stupid things. Yes.
Rainer Weikusat <rweikusat@talktalk.net> writes: >>cross@spitfire.i.gajendra.net (Dan Cross) writes:
Rainer Weikusat <rweikusat@talktalk.net> wrote: >>>>cross@spitfire.i.gajendra.net (Dan Cross) writes:
Rainer Weikusat <rweikusat@talktalk.net> wrote:
Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
[...]
Personally I think that writing bulky procedural stuff for something >>>>>>> like [0-9]+ can only be much worse, and that further abbreviations >>>>>>> like \d+ are the better direction to go if targeting a good interface. >>>>>>> YMMV.
Assuming that p is a pointer to the current position in a string, e is a >>>>>>pointer to the end of it (ie, point just past the last byte) and - >>>>>>that's important - both are pointers to unsigned quantities, the 'bulky' >>>>>>C equivalent of [0-9]+ is
while (p < e && *p - '0' < 10) ++p;
That's not too bad. And it's really a hell lot faster than a >>>>>>general-purpose automaton programmed to recognize the same pattern >>>>>>(which might not matter most of the time, but sometimes, it does).
It's also not exactly right. `[0-9]+` would match one or more
characters; this possibly matches 0 (ie, if `p` pointed to
something that wasn't a digit).
The regex won't match any digits if there aren't any. In this case, the >>>>match will fail. I didn't include the code for handling that because it >>>>seemed pretty pointless for the example.
That's rather the point though, isn't it? The program snippet
(modulo the promotion to signed int via the "usual arithmetic
conversions" before the subtraction and comparison giving you
unexpected values; nothing to do with whether `char` is signed
or not) is a snippet that advances a pointer while it points to
a digit, starting at the current pointer position; that is, it
just increments a pointer over a run of digits.
That's the core part of matching someting equivalent to the regex [0-9]+ >>and the only part of it is which is at least remotely interesting.
But that's not the same as a regex matcher, which has a semantic
notion of success or failure. I could run your snippet against
a string such as, say, "ZZZZZZ" and it would "succeed" just as
it would against an empty string or a string of one or more
digits.
Why do you believe that p being equivalent to the starting position
would be considered a "successful match", considering that this
obviously doesn't make any sense?
[...]
By the way, something that _would_ match `^[0-9]+$` might be:
[too much code]
Something which would match [0-9]+ in its first argument (if any) would
be:
#include "string.h"
#include "stdlib.h"
int main(int argc, char **argv)
{
char *p;
unsigned c;
p = argv[1];
if (!p) exit(1);
while (c = *p, c && c - '0' > 10) ++p;
if (!c) exit(1);
return 0;
}
but that's 14 lines of text, 13 of which have absolutely no relation to
the problem of recognizing a digit.
Personally, I'd use:
$ cat /tmp/a.c--- Synchronet 3.21d-Linux NewsLink 1.2
#include <stdint.h>
#include <string.h>
int
main(int argc, const char **argv)
{
char *cp;
uint64_t value;
if (argc < 2) return 1;
value = strtoull(argv[1], &cp, 10);
if ((cp == argv[1])
|| (*cp != '\0')) {
return 1;
}
return 0;
}
$ cc -o /tmp/a /tmp/a.c
$ /tmp/a 13254
$ echo $?
0
$ /tmp/a 23v23
$ echo $?
1
In any event, this seems simpler than what you posted:
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
int
main(int argc, char *argv[])
{
if (argc != 2) {
fprintf(stderr, "Usage: matchd <str>\n");
return EXIT_FAILURE;
}
for (const char *p = argv[1]; *p != '\0'; p++)
if ('0' <= *p && *p <= '9')
return EXIT_SUCCESS;
return EXIT_FAILURE;
}
Rainer Weikusat <rweikusat@talktalk.net> writes:
Something which would match [0-9]+ in its first argument (if any) would
be:
#include "string.h"
#include "stdlib.h"
int main(int argc, char **argv)
{
char *p;
unsigned c;
p = argv[1];
if (!p) exit(1);
while (c = *p, c && c - '0' > 10) ++p;
if (!c) exit(1);
return 0;
}
but that's 14 lines of text, 13 of which have absolutely no relation to
the problem of recognizing a digit.
Personally, I'd use:
$ cat /tmp/a.c
#include <stdint.h>
#include <string.h>
int
main(int argc, const char **argv)
{
char *cp;
uint64_t value;
if (argc < 2) return 1;
value = strtoull(argv[1], &cp, 10);
if ((cp == argv[1])
|| (*cp != '\0')) {
return 1;
}
return 0;
}
cross@spitfire.i.gajendra.net (Dan Cross) writes:
[...]
In any event, this seems simpler than what you posted:
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
int
main(int argc, char *argv[])
{
if (argc != 2) {
fprintf(stderr, "Usage: matchd <str>\n");
return EXIT_FAILURE;
}
for (const char *p = argv[1]; *p != '\0'; p++)
if ('0' <= *p && *p <= '9')
return EXIT_SUCCESS;
return EXIT_FAILURE;
}
It's not only 4 lines longer but in just about every individual aspect >syntactically more complicated and more messy and functionally more
clumsy.
This is particularly noticable in the loop
for (const char *p = argv[1]; *p != '\0'; p++)
if ('0' <= *p && *p <= '9')
return EXIT_SUCCESS;
the loop header containing a spuriously qualified variable declaration,
the loop body and half of the termination condition.
The other half then
follows as special-case in the otherwise useless loop body.
It looks like a copy of my code which each individual bit redesigned
under the guiding principle of "Can we make this more complicated?", eg,
char **argv
declares an array of pointers
(as each pointer in C points to an array)
and
char *argv[]
accomplishes exactly the same but uses both more characters and more >different kinds of characters.
scott@slp53.sl.home (Scott Lurndal) writes:
Rainer Weikusat <rweikusat@talktalk.net> writes:
[...]
Something which would match [0-9]+ in its first argument (if any) would >>>be:
#include "string.h"
#include "stdlib.h"
int main(int argc, char **argv)
{
char *p;
unsigned c;
p = argv[1];
if (!p) exit(1);
while (c = *p, c && c - '0' > 10) ++p;
if (!c) exit(1);
return 0;
}
but that's 14 lines of text, 13 of which have absolutely no relation to >>>the problem of recognizing a digit.
Personally, I'd use:
$ cat /tmp/a.c
#include <stdint.h>
#include <string.h>
int
main(int argc, const char **argv)
{
char *cp;
uint64_t value;
if (argc < 2) return 1;
value = strtoull(argv[1], &cp, 10);
if ((cp == argv[1])
|| (*cp != '\0')) {
return 1;
}
return 0;
}
This will accept a string of digits whose numerical value is <=
ULLONG_MAX, ie, it's basically ^[0-9]+$ with unobvious length and
content limits.
return !strstr(argv[1], "0123456789");
would be a better approximation,
just a much more complicated algorithm
than necessary. Even in strictly conforming ISO-C "digitness" of a
character can be determined by a simple calculation instead of some kind
of search loop.
On 2024-11-22, Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
On 21.11.2024 20:12, Kaz Kylheku wrote:
[...]
In the wild, you see regexes being used for all sorts of stupid stuff,
No one can prevent folks using features for stupid things. Yes.
But the thing is that "modern" regular expressions (Perl regex and its progeny) have features that are designed to exclusively cater to these
folks.
Rainer Weikusat <rweikusat@talktalk.net> wrote:
cross@spitfire.i.gajendra.net (Dan Cross) writes:
[...]
In any event, this seems simpler than what you posted:
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
int
main(int argc, char *argv[])
{
if (argc != 2) {
fprintf(stderr, "Usage: matchd <str>\n");
return EXIT_FAILURE;
}
for (const char *p = argv[1]; *p != '\0'; p++)
if ('0' <= *p && *p <= '9')
return EXIT_SUCCESS;
return EXIT_FAILURE;
}
It's not only 4 lines longer but in just about every individual aspect >>syntactically more complicated and more messy and functionally more
clumsy.
That's a lot of opinion, and not particularly well-founded
opinion at that, given that your code was incorrect to begin
with.
In article <87cyinrt5s.fsf@doppelsaurus.mobileactivedefense.com>,
Rainer Weikusat <rweikusat@talktalk.net> wrote:
scott@slp53.sl.home (Scott Lurndal) writes:
Rainer Weikusat <rweikusat@talktalk.net> writes:
[...]
Something which would match [0-9]+ in its first argument (if any) would >>>>be:
#include "string.h"
#include "stdlib.h"
int main(int argc, char **argv)
{
char *p;
unsigned c;
p = argv[1];
if (!p) exit(1);
while (c = *p, c && c - '0' > 10) ++p;
if (!c) exit(1);
return 0;
}
but that's 14 lines of text, 13 of which have absolutely no relation to >>>>the problem of recognizing a digit.
Personally, I'd use:
$ cat /tmp/a.c
#include <stdint.h>
#include <string.h>
int
main(int argc, const char **argv)
{
char *cp;
uint64_t value;
if (argc < 2) return 1;
value = strtoull(argv[1], &cp, 10);
if ((cp == argv[1])
|| (*cp != '\0')) {
return 1;
}
return 0;
}
This will accept a string of digits whose numerical value is <=
ULLONG_MAX, ie, it's basically ^[0-9]+$ with unobvious length and
content limits.
He acknowledged this already.
return !strstr(argv[1], "0123456789");
would be a better approximation,
No it wouldn't. That's not even close. `strstr` looks for an
instance of its second argument in its first, not an instance of
any character in it's second argument in its first. Perhaps you
meant something with `strspn` or similar. E.g.,
const char *p = argv[1] + strspn(argv[1], "0123456789");
return *p != '\0';
Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
On 20.11.2024 18:50, Rainer Weikusat wrote:
[...]
while (p < e && *p - '0' < 10) ++p;
That's not too bad. And it's really a hell lot faster than a
general-purpose automaton programmed to recognize the same pattern
(which might not matter most of the time, but sometimes, it does).
Okay, I see where you're coming from (and especially in that simple
case).
Personally (and YMMV), even here in this simple case I think that
using pointers is not better but worse - and anyway isn't [in this
form] available in most languages;
That's a question of using the proper tool for the job. In C, that's
pointer and pointer arithmetic because it's the simplest way to express something like this.
in other cases (and languages)
such constructs get yet more clumsy, and for my not very complex
example - /[0-9]+(ABC)?x*foo/ - even a "catastrophe" concerning
readability, error-proneness, and maintainability.
Procedural code for matching strings constructed in this way is
certainly much simpler-| than the equally procedural code for a
programmable automaton capable of interpreting regexes.
Your statement
is basically "If we assume that the code interpreting regexes doesn't
exist, regexes need much less code than something equivalent which does exist." Without this assumption, the picture becomes a different one altogether.
[...]
cross@spitfire.i.gajendra.net (Dan Cross) writes:
Rainer Weikusat <rweikusat@talktalk.net> wrote: >>>cross@spitfire.i.gajendra.net (Dan Cross) writes:
[...]
In any event, this seems simpler than what you posted:
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
int
main(int argc, char *argv[])
{
if (argc != 2) {
fprintf(stderr, "Usage: matchd <str>\n");
return EXIT_FAILURE;
}
for (const char *p = argv[1]; *p != '\0'; p++)
if ('0' <= *p && *p <= '9')
return EXIT_SUCCESS;
return EXIT_FAILURE;
}
It's not only 4 lines longer but in just about every individual aspect >>>syntactically more complicated and more messy and functionally more >>>clumsy.
That's a lot of opinion, and not particularly well-founded
opinion at that, given that your code was incorrect to begin
with.
That's not at all an opinion but an observation. My opinion on this is
that this is either a poor man's attempt at winning an obfuscation
context or - simpler - exemplary bad code.
cross@spitfire.i.gajendra.net (Dan Cross) writes:
In article <87cyinrt5s.fsf@doppelsaurus.mobileactivedefense.com>,
Rainer Weikusat <rweikusat@talktalk.net> wrote:
scott@slp53.sl.home (Scott Lurndal) writes:
Rainer Weikusat <rweikusat@talktalk.net> writes:
[...]
Something which would match [0-9]+ in its first argument (if any) would >>>>>be:
#include "string.h"
#include "stdlib.h"
int main(int argc, char **argv)
{
char *p;
unsigned c;
p = argv[1];
if (!p) exit(1);
while (c = *p, c && c - '0' > 10) ++p;
if (!c) exit(1);
return 0;
}
but that's 14 lines of text, 13 of which have absolutely no relation to >>>>>the problem of recognizing a digit.
Personally, I'd use:
$ cat /tmp/a.c
#include <stdint.h>
#include <string.h>
int
main(int argc, const char **argv)
{
char *cp;
uint64_t value;
if (argc < 2) return 1;
value = strtoull(argv[1], &cp, 10);
if ((cp == argv[1])
|| (*cp != '\0')) {
return 1;
}
return 0;
}
This will accept a string of digits whose numerical value is <= >>>ULLONG_MAX, ie, it's basically ^[0-9]+$ with unobvious length and
content limits.
He acknowledged this already.
return !strstr(argv[1], "0123456789");
would be a better approximation,
No it wouldn't. That's not even close. `strstr` looks for an
instance of its second argument in its first, not an instance of
any character in it's second argument in its first. Perhaps you
meant something with `strspn` or similar. E.g.,
const char *p = argv[1] + strspn(argv[1], "0123456789");
return *p != '\0';
My bad.
On 21.11.2024 23:05, Lawrence D'Oliveiro wrote:
Another handy one is rCL\brCY for word boundaries.
I prefer \< and \> (that are quite commonly used) for such structural
things ...
cross@spitfire.i.gajendra.net (Dan Cross) writes:
In article <87o728qzbc.fsf@doppelsaurus.mobileactivedefense.com>,
Rainer Weikusat <rweikusat@talktalk.net> wrote:
mas@a4.home writes:
On 2024-11-20, Rainer Weikusat <rweikusat@talktalk.net> wrote:
Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
Assuming that p is a pointer to the current position in a string, e is a >>>>> pointer to the end of it (ie, point just past the last byte) and -
that's important - both are pointers to unsigned quantities, the 'bulky' >>>>> C equivalent of [0-9]+ is
while (p < e && *p - '0' < 10) ++p;
That's not too bad. And it's really a hell lot faster than a
general-purpose automaton programmed to recognize the same pattern
(which might not matter most of the time, but sometimes, it does).
int
main(int argc, char **argv) {
unsigned char *p, *e;
unsigned char mystr[] = "12#45XY ";
p = mystr;
e = mystr + sizeof(mystr);
while (p < e && *p - '0' < 10) ++p;
The code I'm actually using is
while (p < e && (unsigned)*p - '0' < 10)
++p;
I just omitted that when posting this beause I mistakenly assumed that
it probably wasn't needed, ;-). You could have pointed this out instead >>>of trying to dress it up as some sort of mystery problem|e-|. Especially as >>>I did mention that using unsigned arithmetic was necessary (should
really be self-evident).
Well, no, not exactly. You said that it was important that the
pointers point to unsigned quantities, but that wasn't the
issue.
The issue here is that I mistakenly assumed the (unsigned) in the code
was a left-over from before the time when I had changed to pointers to >unsigned char to fix a different issue.
As C tries really hard to force
signed arithmetic onto people despite this basically never makes any
sense,
the type of '0' is int *p gets promoted to int and hence, the
result of the subtraction will also be an int and the '< 10' condition
will be true for every codepoint numerically less than '9' which
obviously won't work as intended.
That's a mistake I made which would have warranted being pointed out and >possibly explained instead of posting some broken code together with
some output the broken code certainly never generated due it being
broken.
That's a mistake I made which would have warranted being pointed out and >>possibly explained instead of posting some broken code together with
some output the broken code certainly never generated due it being
broken.
Perhaps if you stopped being so unbearably smug and pretentious
in your judgements people would give you that grace. As it is,
you come across as thin-skinned and terribly insecure, and your
code shows a lack of competence.
irrelevant. That's not how C works: C will promote those
`unsigned char` values to `signed int` before it does the
subtraction. It does this because `unsigned char` has _rank_
lower than _int_ ...
... and the entire range of values is expressible
in a signed int.
... These are called, "the usual arithmetic
conversions."
In article <87h67zrtns.fsf@doppelsaurus.mobileactivedefense.com>,
Rainer Weikusat <rweikusat@talktalk.net> wrote:...
char **argv
declares an array of pointers
No, it declares a pointer to a pointer to char.
(as each pointer in C points to an array)
That's absolutely not true. A pointer in C may refer to
an array, or a scalar. Consider,
char c;
char *p = &c;
char **pp = &p;
On 11/22/24 16:14, Dan Cross wrote:
...
irrelevant. That's not how C works: C will promote those
`unsigned char` values to `signed int` before it does the
subtraction. It does this because `unsigned char` has _rank_
lower than _int_ ...
True.
... and the entire range of values is expressible
in a signed int.
Not necessarily. An implementation is allowed to have UCHAR_MAX >
INT_MAX, in which case unsigned char promotes to unsigned int rather
than int. I'm aware of systems where UCHAR_MAX > LONG_MAX was true:
char, short, int, and long were all 32 bits.
... These are called, "the usual arithmetic
conversions."
Actually, what you're talking about are the integer promotions. The
first step of the usual arithmetic conversions is to apply the integer >promotions to each operand, but then a few other things happen as well.
cross@spitfire.i.gajendra.net (Dan Cross) writes:
[...]
That's a mistake I made which would have warranted being pointed out and >>>possibly explained instead of posting some broken code together with
some output the broken code certainly never generated due it being >>>broken.
Perhaps if you stopped being so unbearably smug and pretentious
in your judgements people would give you that grace. As it is,
you come across as thin-skinned and terribly insecure, and your
code shows a lack of competence.
I suggest you print this and pin to to a place you frequently look
at. This may eventually lead you to a much more realistic assessment of >yourself than you presently seem to have.
On 11/22/24 14:05, Dan Cross wrote:
In article <87h67zrtns.fsf@doppelsaurus.mobileactivedefense.com>,
Rainer Weikusat <rweikusat@talktalk.net> wrote:...
char **argv
declares an array of pointers
No, it declares a pointer to a pointer to char.
Agreed.
(as each pointer in C points to an array)
That's absolutely not true. A pointer in C may refer to
an array, or a scalar. Consider,
char c;
char *p = &c;
char **pp = &p;
Not actually relevant. For purposes of pointer arithmetic, a pointer to
a single object is treated as if it pointed at the first element of a >1-element array of that object's type.
a) Please stop emailing me this stuff _and_ posting it here. I
have asked you this in the past, and previously you'd said that
it was because you switched news readers. That's fine, but that
was a year ago or more.
b) What you are referring to, from the section on Additive
Operators (6.5.7 in n3220; 6.5.6 in C99) is in reference to
pointer arithmetic; the statement that I was replying to was a
general statement about pointers, independent of issues of
pointer arithmetic. That is, it is not the case that, "each
pointer in C points to an array". The above example, to which
you replied, is a counterpoint to the general statement.
On 11/22/24 18:06, Dan Cross wrote:
...
a) Please stop emailing me this stuff _and_ posting it here. I
have asked you this in the past, and previously you'd said that
it was because you switched news readers. That's fine, but that
was a year ago or more.
Actually, Thunderbird made the change to how the "Reply" button works sometime around April 2021, and I'm still making the mistake of hitting
it when I should hit "Followup". At my age it's hard to change a habit acquired over a couple of decades of posting to usenet; I'm doing my
best to change it, and still failing frequently.
In article <e47664d3-7f9b-4e67-aa73-b72c6cc0687a@alumni.caltech.edu>,...
James Kuyper <jameskuyper@alumni.caltech.edu> wrote:
On 11/22/24 16:14, Dan Cross wrote:
... and the entire range of values is expressible
in a signed int.
Not necessarily. An implementation is allowed to have UCHAR_MAX >
INT_MAX, in which case unsigned char promotes to unsigned int rather
than int. I'm aware of systems where UCHAR_MAX > LONG_MAX was true:
char, short, int, and long were all 32 bits.
Yes, but in this context, that's obviously not the case as he
posted the behavior he saw. I was merely explaining _why_ he
saw that behavior, vis the standard.
... These are called, "the usual arithmetic
conversions."
Actually, what you're talking about are the integer promotions. The
first step of the usual arithmetic conversions is to apply the integer
promotions to each operand, but then a few other things happen as well.
This is correct, but IMHO too far down into the weeds. Consider
section 6.3.1.1 para 3, which notes that, "the integer
promotions are applied only: ... 1. as part of the usual
arithmetic conversions".
... Since we're talking about operands to
a binary operator, 6.3.1.8 applies. 6.3.1.8 is why converting
one side to unsigned is sufficient to get an unsigned result.
On 23.11.2024 04:49, James Kuyper wrote:...
Actually, Thunderbird made the change to how the "Reply" button works
sometime around April 2021, and I'm still making the mistake of hitting
it when I should hit "Followup". At my age it's hard to change a habit
acquired over a couple of decades of posting to usenet; I'm doing my
best to change it, and still failing frequently.
Been there. I desperately looked for a way to fix or alleviate that horrendous user-interface misconception. Eventually I was able to
fix it, but unfortunately cannot quite recall how that was done.
On 11/22/24 23:26, Janis Papanagnou wrote:
On 23.11.2024 04:49, James Kuyper wrote:...
Actually, Thunderbird made the change to how the "Reply" button works
sometime around April 2021, and I'm still making the mistake of hitting
it when I should hit "Followup". At my age it's hard to change a habit
acquired over a couple of decades of posting to usenet; I'm doing my
best to change it, and still failing frequently.
Been there. I desperately looked for a way to fix or alleviate that
horrendous user-interface misconception. Eventually I was able to
fix it, but unfortunately cannot quite recall how that was done.
I seem to recall that I was advised that I could use an older version of Thunderbird to edit the list of buttons that are visible, something that cannot be done in the latest version. I'm afraid to go back to an older version, because so many of the updates to most of the software I own consists of security fixes. I don't want to go back to an older, less
secure version of TB.
On 2024-11-22, Muttley@DastartdlyHQ.org <Muttley@DastartdlyHQ.org> wrote:
Its not that simple I'm afraid since comments can be commented out.
Umm, no.
eg:
// int i; /*
This /* sequence is inside a // comment, and so the machinery that
recognizes /* as the start of a comment would never see it.
A C99 and C++ compiler would see "int j" and compile it, a regex would
simply remove everything from the first /* to */.
No, it won't, because that's not how regexes are used in a lexical
Also the same probably applies to #ifdef's.
Lexically analyzing C requires implementing the translation phases
as described in the standard. There are preprocessor phases which
delimit the input into preprocessor tokens (pp-tokens). Comments
are stripped in preprocessing. But logical lines (backslash
continuations) are recognized below comments; i.e. this is one
comment:
On 11/22/24 18:06, Dan Cross wrote:
...
a) Please stop emailing me this stuff _and_ posting it here. I
have asked you this in the past, and previously you'd said that
it was because you switched news readers. That's fine, but that
was a year ago or more.
Actually, Thunderbird made the change to how the "Reply" button works >sometime around April 2021, and I'm still making the mistake of hitting
it when I should hit "Followup". At my age it's hard to change a habit >acquired over a couple of decades of posting to usenet; I'm doing my
best to change it, and still failing frequently.
I'm unlikely to deliberately send you e-mail, so you can easily avoid
the aggravation of dealing with my accidental e-mails by simply
kill-filing me.
b) What you are referring to, from the section on Additive
Operators (6.5.7 in n3220; 6.5.6 in C99) is in reference to
pointer arithmetic; the statement that I was replying to was a
general statement about pointers, independent of issues of
pointer arithmetic. That is, it is not the case that, "each
pointer in C points to an array". The above example, to which
you replied, is a counterpoint to the general statement.
I disagree. It is not independent, because there's nothing you can do
with pointer itself that has either it's value or it's validity
dependent upon whether that pointer points at a single object or the
first element of an array of length one.
On 11/22/24 17:34, Dan Cross wrote:
In article <e47664d3-7f9b-4e67-aa73-b72c6cc0687a@alumni.caltech.edu>,...
James Kuyper <jameskuyper@alumni.caltech.edu> wrote:
On 11/22/24 16:14, Dan Cross wrote:
... and the entire range of values is expressible
in a signed int.
Not necessarily. An implementation is allowed to have UCHAR_MAX >
INT_MAX, in which case unsigned char promotes to unsigned int rather
than int. I'm aware of systems where UCHAR_MAX > LONG_MAX was true:
char, short, int, and long were all 32 bits.
Yes, but in this context, that's obviously not the case as he
posted the behavior he saw. I was merely explaining _why_ he
saw that behavior, vis the standard.
Your wording could easily give the false impression, to anyone who
didn't already know better, that promotion of unsigned char to signed
int is required by the standard, rather than it being dependent upon
whether UCHAR_MAX > INT_MAX.
... These are called, "the usual arithmetic
conversions."
Actually, what you're talking about are the integer promotions. The
first step of the usual arithmetic conversions is to apply the integer
promotions to each operand, but then a few other things happen as well.
This is correct, but IMHO too far down into the weeds. Consider
section 6.3.1.1 para 3, which notes that, "the integer
promotions are applied only: ... 1. as part of the usual
arithmetic conversions".
The latest draft of the standard that I have is n3096.pdf, dated
2023-04-01.
In that draft, that wording is not present in paragraph 3,
but only footnote 63, which is referenced by paragraph 2. That footnote
does not contain the "1." that is present in your citation. That
footnote goes on to list the other contexts in which integer promotions
can occur: ", to certain argument expressions, to the operands of the
unary +, -, and ~ operators, and to both operands of the shift
operators, as specified by their respective subclauses."
Which version are you quoting? I have copies of most of the draft
standards that are available for free, but none of the final versions of
the standards, since those cost money.
... Since we're talking about operands to
a binary operator, 6.3.1.8 applies. 6.3.1.8 is why converting
one side to unsigned is sufficient to get an unsigned result.
Calling them the usual arithmetic conversions rather than the integer >promotions is being unnecessarily vague. Your description only covers
the integer promotions, it doesn't cover any of the other usual
arithmetic conversions.
I'm going to try to come up with an analogy; the best one I could come
up on the spur of the moment involves the US federal income tax form
1040. It has a section called "Payments". The first four payments are
all amounts that have been withheld from various income sources before
you ever get a chance to spend the money. Most the other payments are
things that you spent money on that you are entitled to take as a credit >against your tax liability.
What you've done is analogous to describing how withholding works, and
even using the term "withheld", and then referring to what you've just >described as "payments" rather than "amounts withheld", even though your >description doesn't fit the tax credits, which are the other kinds of >payments.
On 23.11.2024 06:04, James Kuyper wrote:...
I seem to recall that I was advised that I could use an older version of
Thunderbird to edit the list of buttons that are visible, something that
cannot be done in the latest version. I'm afraid to go back to an older
version, because so many of the updates to most of the software I own
consists of security fixes. I don't want to go back to an older, less
secure version of TB.
Understandable. - But you noticed that the "Smart Reply" thing was
a feature of my newer Thunderbird version? - I'd think it should be
there, or isn't it in your version? (What version are you running?)
In article <vhrmk1$1ivhr$1@dont-email.me>,...
James Kuyper <jameskuyper@alumni.caltech.edu> wrote:
Your wording could easily give the false impression, to anyone who
didn't already know better, that promotion of unsigned char to signed
int is required by the standard, rather than it being dependent upon
whether UCHAR_MAX > INT_MAX.
Actually I'm not sure that it did. Note the part that you
quoted above that says, "the entire range values is expressible
in a signed int." This implies UCHAR_MAX <= INT_MAX. (By
"values" I meant, "values of that type", not specific values in
any given program).
... Since we're talking about operands to
a binary operator, 6.3.1.8 applies. 6.3.1.8 is why converting
one side to unsigned is sufficient to get an unsigned result.
Calling them the usual arithmetic conversions rather than the integer
promotions is being unnecessarily vague. Your description only covers
the integer promotions, it doesn't cover any of the other usual
arithmetic conversions.
The integer promotions were the only relevant part in context.
Perhaps it would have allayed your concerns to say, "part of"?
[snip]
On 11/23/24 00:09, Janis Papanagnou wrote:
On 23.11.2024 06:04, James Kuyper wrote:...
I seem to recall that I was advised that I could use an older version of >>> Thunderbird to edit the list of buttons that are visible, something that >>> cannot be done in the latest version. I'm afraid to go back to an older
version, because so many of the updates to most of the software I own
consists of security fixes. I don't want to go back to an older, less
secure version of TB.
Understandable. - But you noticed that the "Smart Reply" thing was
a feature of my newer Thunderbird version? - I'd think it should be
there, or isn't it in your version? (What version are you running?)
115.16.0esr
I don't have a "More/Customize Toolbar" option, only "More/Customize",
[...]
On 20.11.2024 12:46, Ed Morton wrote:
Definitely. The most relevant statement about regexps is this:
Some people, when confronted with a problem, think "I know, I'll use
regular expressions." Now they have two problems.
(Worth a scribbling on a WC wall.)
Obviously regexps are very useful and commonplace but if you find you
have to use some online site or other tools to help you write/understand
one or just generally need more than a couple of minutes to
write/understand it then it's time to back off and figure out a better
way to write your code for the sake of whoever has to read it 6 months
later (and usually for robustness too as it's hard to be sure all rainy
day cases are handled correctly in a lengthy and/or complicated regexp).
Regexps are nothing for newbies.
The inherent fine thing with Regexps is that you can incrementally
compose them[*].[**]
It seems you haven't found a sensible way to work with them?
(And I'm really astonished about that since I know you worked with
Regexps for years if not decades.)
In those cases where Regexps *are* the tool for a specific task -
I don't expect you to use them where they are inappropriate?! -
what would be the better solution[***] then?
Janis
[*] Like the corresponding FSMs.
[**] And you can also decompose them if they are merged in a huge
expression, too large for you to grasp it. (BTW, I'm doing such decompositions also with other expressions in program code that
are too bulky.)
[***] Can you answer the question that another poster failed to do?
Here are some ideas for you to consider:
Thunderbird is open source, maybe even free software.
I am sure it is extremely easy to either remove the
"reply" button or to bind it to the "followup" function.
Kalevi Kolttonen <kalevi@kolttonen.fi> wrote:
...
Thunderbird is open source, maybe even free software.
I am sure it is extremely easy to either remove the
"reply" button or to bind it to the "followup" function.
I doubt it is any simple matter to find it in the massive source code,
much less to figure out how to fix it, much less figure out how to successfully re-build (and test!) it after making your changes.
Generally, most complicated GUI software, even if technically Open
Source, is difficult, if not impossible, for ordinary people using
ordinary machines, to re-build from source. Among other things, you
will generally end up spending many hours, if not days, getting all
the dependencies installed.
Dan Cross <cross@spitfire.i.gajendra.net> wrote:
Here are some ideas for you to consider:
Sorry for replying to an old post. I do not even
remember who it is that keeps sending emails when
he intends to send follow-ups to Usenet. However,
I have a good solution.
Thunderbird is open source, maybe even free software.
I am sure it is extremely easy to either remove the
"reply" button or to bind it to the "followup" function.
I am sure it is extremely easy to either remove the
"reply" button or to bind it to the "followup" function.
On Debian-derived platforms, thats what apt-get build-dep is for.
Source package rebuild is also standardized. It looks like the RH world
has something pretty similar.
On Fri, 27 Dec 2024 13:59:47 -0000 (UTC)
kalevi@kolttonen.fi (Kalevi Kolttonen) wrote:
I am sure it is extremely easy to either remove the
"reply" button or to bind it to the "followup" function.
Have you, like, actually *checked* this assertion?
In article <wwvh66p9ntv.fsf@LkoBDZeT.terraraq.uk>,
Richard Kettlewell <invalid@invalid.invalid> wrote:
...
On Debian-derived platforms, thats what apt-get build-dep is for.
Source package rebuild is also standardized. It looks like the RH world >>has something pretty similar.
I know all that - and, in theory, it should "just work".
But my experience is that theory and practice diverge.
Now, I may not be the most capable person in the world, probably not even
in the top 10 (or 100). But that's exactly my point. It's just not an
easy task for ordinary people under ordinary circumstances.
In article <wwvh66p9ntv.fsf@LkoBDZeT.terraraq.uk>,
Richard Kettlewell <invalid@invalid.invalid> wrote:
...
On Debian-derived platforms, thats what apt-get build-dep is for.
Source package rebuild is also standardized. It looks like the RH world
has something pretty similar.
I know all that - and, in theory, it should "just work".
But my experience is that theory and practice diverge.
Now, I may not be the most capable person in the world, probably not even
in the top 10 (or 100). But that's exactly my point. It's just not an
easy task for ordinary people under ordinary circumstances.
On Fri, 27 Dec 2024 13:59:47 -0000 (UTC)
kalevi@kolttonen.fi (Kalevi Kolttonen) wrote:
I am sure it is extremely easy to either remove the
"reply" button or to bind it to the "followup" function.
Have you, like, actually *checked* this assertion?
Dan Cross <cross@spitfire.i.gajendra.net> wrote:
Here are some ideas for you to consider:
Sorry for replying to an old post. I do not even
remember who it is that keeps sending emails when
he intends to send follow-ups to Usenet. However,
I have a good solution.
Thunderbird is open source, maybe even free software.
If I were not full of tasks right now, I would set up a VM with Debian
and try it out---build-dep for Thunderbird. Just to see if compiles successfully without much hacking involved.
On Debian-derived platforms, thatrCOs what apt-get build-dep is for.
If I were not full of tasks right now, I would set up a VM with Debian
and try it out---build-dep for Thunderbird. Just to see if compiles successfully without much hacking involved. I am also skeptical of such things. It usually works on smaller projects; I'd be surprised and
happy to find out that it works with no hacking involved.
kalevi@kolttonen.fi (Kalevi Kolttonen) writes:
Dan Cross <cross@spitfire.i.gajendra.net> wrote:
Here are some ideas for you to consider:
Sorry for replying to an old post. I do not even
remember who it is that keeps sending emails when
he intends to send follow-ups to Usenet. However,
I have a good solution.
Thunderbird is open source, maybe even free software.
I am sure it is extremely easy to either remove the
"reply" button or to bind it to the "followup" function.
Go on then?
[ Thunderbird issues ]
Thunderbird is yet another mail program whose developers think that
Usenet is just like e-mail, and can be bolted onto a mail client.
[...]
[...]
No need to be skeptical, we live in modern ages
where things have been made quite convenient for us.
Compiling Thunderbird should be very easy indeed
when we use Linux distro's package management.
[ snip suggested 8-step development process ]
On 28.12.2024 00:22, Kalevi Kolttonen wrote:
[...]
No need to be skeptical, we live in modern ages
where things have been made quite convenient for us.
LOL. :-)
Compiling Thunderbird should be very easy indeed
when we use Linux distro's package management.
You expect _users_ of tools to use a _development_
environment to fix *inherent* shortcomings of a tool?
(Shortcomings that should not be there in the first
place!)
I got 16GM of RAM. Maybe the build parameters in the
spec file are too aggressive for this modest laptop,
but I did not find any "make -j" invocation.
Now I have to sleep and maybe try it again tomorrow.
Kalevi Kolttonen <kalevi@kolttonen.fi> wrote:
I got 16GM of RAM. Maybe the build parameters in the
spec file are too aggressive for this modest laptop,
but I did not find any "make -j" invocation.
Now I have to sleep and maybe try it again tomorrow.
Still awake for a while. I looked at the spec file
and replaced:
./mach build -v
with
./mach build -j6 -v
Maybe in the morning we have a complete build.
On 28.12.2024 00:22, Kalevi Kolttonen wrote:
Compiling Thunderbird should be very easy indeed when we use Linux
distro's package management.
You expect _users_ of tools to use a _development_ environment to fix *inherent* shortcomings of a tool?
Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
On 28.12.2024 00:22, Kalevi Kolttonen wrote:
[...]
No need to be skeptical, we live in modern ages
where things have been made quite convenient for us.
LOL. :-)
My comment above was a reference to the bad old
days when you had to manually download tar.gz packages
and compile them to satisfy dependencies. Now the
builds are super easy with the help of package management.
Compiling Thunderbird should be very easy indeed
when we use Linux distro's package management.
You expect _users_ of tools to use a _development_
environment to fix *inherent* shortcomings of a tool?
(Shortcomings that should not be there in the first
place!)
Why would you think so? This is just one way to
solve the problem. [...]
On Sat, 28 Dec 2024 00:44:10 +0100, Janis Papanagnou wrote:
On 28.12.2024 00:22, Kalevi Kolttonen wrote:
Compiling Thunderbird should be very easy indeed when we use Linux
distro's package management.
You expect _users_ of tools to use a _development_ environment to fix
*inherent* shortcomings of a tool?
On Linux, there is no rCLdevelopment environmentrCY versus rCLuser environmentrCY.
The same packaging tools work with both source code and built binaries.
On 28.12.2024 00:22, Kalevi Kolttonen wrote:
[...]
No need to be skeptical, we live in modern ages
where things have been made quite convenient for us.
LOL. :-)
Compiling Thunderbird should be very easy indeed
when we use Linux distro's package management.
You expect _users_ of tools to use a _development_
environment to fix *inherent* shortcomings of a tool?
(Shortcomings that should not be there in the first
place!)
./mach build -v
with
./mach build -j6 -v
I cannot understand this because all references to
patches 416 and 419 are commented out in the Fedora
41 spec file. I now completely removed them and will
try again...
It is really painful but I guess I have to use
just a single CPU:
./mach build -j1 -v
Because of this, the build takes forever to complete.
You think it's normal that on a Linux installation where, say, no 'cc'
(as prominent example of a development tool) is installed the package
manager would first install ALL the necessary compilers and scripting languages just to create a binary (as opposed to just installing the
binary)?
Personally I don't think that package managers contribute a lot since
for ordinary users it's the same whether the package managers install a binary package or a source that is compiled under the hood.
The difference is that source package needs a development
environment (compiler, etc.) that "ordinary users" might not have
installed or may not want to get installed (just for that).
On Sat, 28 Dec 2024 19:40:46 +0100, Janis Papanagnou wrote:
You think it's normal that on a Linux installation where, say, no 'cc'
(as prominent example of a development tool) is installed the package
manager would first install ALL the necessary compilers and scripting
languages just to create a binary (as opposed to just installing the
binary)?
The discussion has to do with creating your own version of the binary, rather than using the repo-provided version.
This codebase is absolutely massive! I am beginning to lose patience.
Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
On Sat, 28 Dec 2024 19:40:46 +0100, Janis Papanagnou wrote:
You think it's normal that on a Linux installation where, say, no 'cc'
(as prominent example of a development tool) is installed the package
manager would first install ALL the necessary compilers and scripting
languages just to create a binary (as opposed to just installing the
binary)?
The discussion has to do with creating your own version of the binary,
rather than using the repo-provided version.
Right.
Anyway, to be honest, I never realized how bloated Thunderbird is.
The source RPM thunderbird-128.5.2-1.fc41.src.rpm is 690MB and
the main source directory unpacked is:
~/tmp/tb/thunderbird-128.5.2 $ du -sh
4.2G .
Building TB with the help of a pre-made spec file on Fedora is
probably very much easier than doing 'git clone' and trying to
build it from there. Using 'dnf', it was just one command to
download all the dependencies. I suppose the size of the
dependency packages was 260MB in total. It would be a nightmare
having to download them manually and then building them.
Packages are just so handy.
Fedora and Red Hat have already done the hard work so it
is wise to use their source RPM as a basis for your own
modifications when you are on Fedora or Red Hat Enterprise
Linux.
My single CPU Thunderbird build has now lasted for over two
and half hours and I have no clue when it will be ready.
This codebase is absolutely massive! I am beginning to
lose patience.
br,
KK
Kalevi Kolttonen <kalevi@kolttonen.fi> wrote:
I cannot understand this because all references to
patches 416 and 419 are commented out in the Fedora
41 spec file. I now completely removed them and will
try again...
I am having massive problems with having only 16GB of
RAM.
Using 'top', I was able to see that Rust compiler 'rustc'
was hogging something like 11GB of memory, and then
after a while OOM killer got rid of the Rust compiler
process. I am also seeing swapping take place when I
attempt the build.
Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
On Sat, 28 Dec 2024 19:40:46 +0100, Janis Papanagnou wrote:
You think it's normal that on a Linux installation where, say, no 'cc'
(as prominent example of a development tool) is installed the package
manager would first install ALL the necessary compilers and scripting
languages just to create a binary (as opposed to just installing the
binary)?
The discussion has to do with creating your own version of the binary,
rather than using the repo-provided version.
Right.
Anyway, to be honest, I never realized how bloated Thunderbird is.
The source RPM thunderbird-128.5.2-1.fc41.src.rpm is 690MB and
the main source directory unpacked is:
~/tmp/tb/thunderbird-128.5.2 $ du -sh
4.2G .
Why TF is the rust compiler involved in the process at all?
In article <vkr61v$srrk$1@dont-email.me>, <Muttley@dastardlyhq.com> wrote: >....
Why TF is the rust compiler involved in the process at all?
Well, obviously, because parts of TB are (apparently) written in Rust...
Rust seems to be, like Python, trying to ingratiate itself into the basic >running of the system, not just be a peripheral "scripting language".
On Sat, 28 Dec 2024 23:32:37 -0000 (UTC)
kalevi@kolttonen.fi (Kalevi Kolttonen) gabbled:
Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
On Sat, 28 Dec 2024 19:40:46 +0100, Janis Papanagnou wrote:
You think it's normal that on a Linux installation where, say, no 'cc' >>>> (as prominent example of a development tool) is installed the package
manager would first install ALL the necessary compilers and scripting
languages just to create a binary (as opposed to just installing the
binary)?
The discussion has to do with creating your own version of the binary,
rather than using the repo-provided version.
Right.
Anyway, to be honest, I never realized how bloated Thunderbird is.
The source RPM thunderbird-128.5.2-1.fc41.src.rpm is 690MB and
the main source directory unpacked is:
~/tmp/tb/thunderbird-128.5.2 $ du -sh
4.2G .
Welcome to Lego brick style programming where the main application devs are incompetant halfwits unable to implement even simple things themselves beyond designing (if that applies to Thunderbird) a GUI so have to import 101 libraries
to do everything for them.
I've written my own newsreader system and while admittedly its command line only it requires only one 3rd party library which is OpenSSL.
Why TF is the rust compiler involved in the process at all?
Because these builds take four hours, I have to admit defeat.
I simply do not have the time to make more modification
attempts.
Is the whole thing obscene ? Yes. You won't find too many
software creations, this distorted. Still, people are using it.
Most people are not aware what is under the hood. It's
a herd of elephants :-)
Kalevi Kolttonen <kalevi@kolttonen.fi> wrote:*SKIP* [ 14 lines 1 level deep]
./mach build -vOkay, I am finally back at home and it is 21:43 o'clock.
with
./mach build -j6 -v
I cannot understand this because all references to patches 416 and 419
are commented out in the Fedora 41 spec file. I now completely removed
them and will try again...
Yay! The joy of building redhat. Expect your
build dependencies being inadequate, missing,
or plainly wrong. Just saying.
On 12/27/24 18:44, Janis Papanagnou wrote:
On 28.12.2024 00:22, Kalevi Kolttonen wrote:
Compiling Thunderbird should be very easy indeed
when we use Linux distro's package management.
You expect _users_ of tools to use a _development_
environment to fix *inherent* shortcomings of a tool?
(Shortcomings that should not be there in the first
place!)
IIRC, this is in reference to my difficulty when Thunderbird changed the Reply button to mean "Reply" rather than "Followup", and instead added a
new button that is labelled "Followup". I have never complained about
that change - it was an entirely sensible one. I'm just having trouble re-training myself to use the newer, more sensible interface in a few
years after spending a couple of decades using the older, less sensible
one. And I fully appreciate other people's irritation at my difficulty
with re-training.
I wouldn't mind if they reinstated the ability, which existed in older versions of Thunderbird, to rearrange the list of buttons that are
displayed. I do complain about the removal of that customization
ability. I don't want to go back to those older versions because that
would mean undoing other improvements. I'm especially worried about
undoing security bug fixes.
I don't like the idea of creating my own personal version of Thunderbird
by modifying their source code, because it means I would have to re-do
the build every time they put out a new version. I want quick and easy upgrades to newer versions, especially security bug fixes, and that
desire conflicts with the desire for customization.
On Sun, 29 Dec 2024 10:33:43 -0000 (UTC)
gazelle@shell.xmission.com (Kenny McCormack) gabbled:
[...]
Rust seems to be, like Python, trying to ingratiate itself into the basic
running of the system, not just be a peripheral "scripting language".
Requiring 2 seperate compilers to build anything is an absurdity.
On Sun, 12/29/2024 4:54 AM, Muttley@dastardlyhq.com wrote:
[...]
I've written my own newsreader system and while admittedly its command line >> only it requires only one 3rd party library which is OpenSSL.
[ snip explanations of some TB internals ]
Is the whole thing obscene ? Yes. You won't find too many
software creations, this distorted. Still, people are using it.
Most people are not aware what is under the hood. It's
a herd of elephants :-)
In article <vkrfue$vl1b$1@dont-email.me>, Paul <nospam@needed.invalid> wrote:
...
Is the whole thing obscene ? Yes. You won't find too many
software creations, this distorted. Still, people are using it.
Most people are not aware what is under the hood. It's
a herd of elephants :-)
Just out curiosity, does all of this apply to the Windows version as well?
I know this thread is mostly about the Linux version, and although I
actually don't use TB at all, I know someone who uses the Windows version.
On Sun, 12/29/2024 4:54 AM, Muttley@dastardlyhq.com wrote:
[...]
I've written my own newsreader system and while admittedly its command line
only it requires only one 3rd party library which is OpenSSL.
That's a fine property. - Too bad one has to write one's own piece
of software to get a more sensibly defined product.
Without my hack, the build process took four hours to complete
and it produced a working TB. However, with my tiny JavaScript
modification, the build failed.
Because these builds take four hours, I have to admit defeat.
I simply do not have the time to make more modification
attempts.
What is more, James Kuyper said that he does not want to
build his own TB so it was all in vain anyway.
Muttley@dastardlyhq.com wrote:
gazelle@shell.xmission.com (Kenny McCormack) gabbled:
Rust seems to be, like Python, trying to ingratiate itself into the
basic running of the system, not just be a peripheral "scripting
language".
Requiring 2 seperate compilers to build anything is an absurdity.
(Disclaimer: I skipped most of the sub-thread, so if that generalizing sentence was addressing some peculiar (maybe even TB-related) software specialities you may ignore the rest of my post.)
From my experience it's no "absurdity" but actual (sensible) normality
to use multiple compilers and other software generators in SW-projects.
It seems that depends on the software architecture. It's (IMO) fine to
create libraries that are combined in an "anything" to be compiled
with the (at the time of their creation) most appropriate
compiler. It's also fine if you use a second language as a
higher-level intermediate language. Also if you create the "anything"
based on several components (or subsystems) that are combined. Using
separate protocol compilers is also not uncommon to get the transfer
objects and functions. Also using own compilers for the accompanying
parts like documentation is typical. (All these examples just off the
top of my head from some professional projects that I observed or was
engaged with.)
In article <vkrfue$vl1b$1@dont-email.me>, Paul <nospam@needed.invalid> wrote:
...
Is the whole thing obscene ? Yes. You won't find too many
software creations, this distorted. Still, people are using it.
Most people are not aware what is under the hood. It's
a herd of elephants :-)
Just out curiosity, does all of this apply to the Windows version as well?
I know this thread is mostly about the Linux version, and although I
actually don't use TB at all, I know someone who uses the Windows version.
Eric Pozharski <apple.universe@posteo.net> wrote:
Yay! The joy of building redhat. Expect your
build dependencies being inadequate, missing,
or plainly wrong. Just saying.
After some minor spec file tweaking, I managed to do
*one* successful TB build, but because Rust compiler can
hog almost 16GB of memory, most of the time I just
cannot build TB using my modest Lenovo laptop. OOM
killer kicks in and destroys the build.
I never could have believed that having 16GB of
RAM and 8GB of swap is not enough for building TB!
On 29.12.2024 11:38, Muttley@dastardlyhq.com wrote:
On Sun, 29 Dec 2024 10:33:43 -0000 (UTC)
gazelle@shell.xmission.com (Kenny McCormack) gabbled:
[...]
Rust seems to be, like Python, trying to ingratiate itself into the basic >>> running of the system, not just be a peripheral "scripting language".
Requiring 2 seperate compilers to build anything is an absurdity.
(Disclaimer: I skipped most of the sub-thread, so if that generalizing >sentence was addressing some peculiar (maybe even TB-related) software >specialities you may ignore the rest of my post.)
From my experience it's no "absurdity" but actual (sensible) normality
to use multiple compilers and other software generators in SW-projects.
kalevi@kolttonen.fi (Kalevi Kolttonen) writes:
Eric Pozharski <apple.universe@posteo.net> wrote:
Yay! The joy of building redhat. Expect your
build dependencies being inadequate, missing,
or plainly wrong. Just saying.
After some minor spec file tweaking, I managed to do
*one* successful TB build, but because Rust compiler can
hog almost 16GB of memory, most of the time I just
cannot build TB using my modest Lenovo laptop. OOM
killer kicks in and destroys the build.
I never could have believed that having 16GB of
RAM and 8GB of swap is not enough for building TB!
You did it. Thanks for sharing the experience.
Salvador Mirzo <smirzo@example.com> wrote:
kalevi@kolttonen.fi (Kalevi Kolttonen) writes:
Eric Pozharski <apple.universe@posteo.net> wrote:
Yay! The joy of building redhat. Expect your
build dependencies being inadequate, missing,
or plainly wrong. Just saying.
After some minor spec file tweaking, I managed to do
*one* successful TB build, but because Rust compiler can
hog almost 16GB of memory, most of the time I just
cannot build TB using my modest Lenovo laptop. OOM
killer kicks in and destroys the build.
I never could have believed that having 16GB of
RAM and 8GB of swap is not enough for building TB!
You did it. Thanks for sharing the experience.
With some incredible luck, it worked out *once*. :-)
That also explains why some people were skeptical here. Even with a sophisticated system to make the compilation succeed, it's still not
without a thrill.
Eric Pozharski <apple.universe@posteo.net> wrote:
Yay! The joy of building redhat. Expect your
build dependencies being inadequate, missing,
or plainly wrong. Just saying.
After some minor spec file tweaking, I managed to do
*one* successful TB build, but because Rust compiler can
hog almost 16GB of memory, most of the time I just
cannot build TB using my modest Lenovo laptop. OOM
killer kicks in and destroys the build.
I never could have believed that having 16GB of
RAM and 8GB of swap is not enough for building TB!
br,
KK
On Sun, 12/29/2024 1:59 PM, Kalevi Kolttonen wrote:
Eric Pozharski <apple.universe@posteo.net> wrote:
Yay! The joy of building redhat. Expect your
build dependencies being inadequate, missing,
or plainly wrong. Just saying.
After some minor spec file tweaking, I managed to do
*one* successful TB build, but because Rust compiler can
hog almost 16GB of memory, most of the time I just
cannot build TB using my modest Lenovo laptop. OOM
killer kicks in and destroys the build.
I never could have believed that having 16GB of
RAM and 8GB of swap is not enough for building TB!
br,
KK
Try a chain saw next time :-)
It's one of the first practical tests the machine got.
The RPMBuild phase was awfully slow (it spoiled the fun).
But the compiles and linking behaved well. RPM compression
seems to run on one core.
[Picture] During compile phase...
https://i.postimg.cc/44qRrgxb/Thunderbird-Fedora41-Build-From-Source-via-Mock.gif
I think it's possible the build slows down, the longer it runs.
Like "something" is fragmenting.
Even on this machine, the process does not encourage
interactive operation. It takes too long. Adjusting the
command a bit so it just compiles and links, would be
better, if that's possible.
mock --resultdir=/tmp/results --rootdir=/tmp/mock --rebuild thunderbird-128.5.2-1.fc41.src.rpm | tee /tmp/build_out.txt
I picked Fedora for the job, because it only takes two commands
in a terminal, to do it. In simplified terms...
dnf download --source packagename # Downloading source doesn't need root. >mock --rebuild packagename # User account belongs to "mock" group, doesn't build as root
But I need to do something else to that Mock command,
to get what I want (a "portable" copy of Thunderbird,
there should be a dir created with that sitting in it).
Summary: No question, a bit of RAM helps. Some of the RAM
accounting in Linux is just weird (process resident
seen rising, graph in system monitor remains flat).
I was expecting to see a "hump" while linking, but
the graph was relatively flat and featureless.
Paul
Why would you expect the link step to require a lot of
memory? The linker builds an elf executable from the contents
of ELF object files, one ELF section at a time. It doesn't
construct the entire ELF executable in memory before writing it out.
I've built Thunderbird on both Windows and Linux.
It was the Windows build that left a bad taste.
Once you repeatedly have build failures during linking, you are always looking for it.
On Thu, 1/2/2025 11:29 AM, Scott Lurndal wrote:
Why would you expect the link step to require a lot of
memory? The linker builds an elf executable from the contents
of ELF object files, one ELF section at a time. It doesn't
construct the entire ELF executable in memory before writing it out.
It's based on experience, not imagination.
I've built Thunderbird on both Windows and Linux.
It was the Windows build that left a bad taste.
Once you repeatedly have build failures during linking,
you are always looking for it.
Paul <nospam@needed.invalid> writes:
On Thu, 1/2/2025 11:29 AM, Scott Lurndal wrote:
Why would you expect the link step to require a lot of
memory? The linker builds an elf executable from the contents
of ELF object files, one ELF section at a time. It doesn't
construct the entire ELF executable in memory before writing it out.
It's based on experience, not imagination.
I've built Thunderbird on both Windows and Linux.
It was the Windows build that left a bad taste.
Once you repeatedly have build failures during linking,
you are always looking for it.
Ah, well windows. You need not elaborate.
I've been fortunate to have never built software in a
microsoft environment (aside an optical jukebox driver
for NT3.51 once on a contract job - even then I did
all the editing on unix and just compiled and tested
on the windows box).
On Fri, 03 Jan 2025 18:15:25 GMT
scott@slp53.sl.home (Scott Lurndal) gabbled:
Paul <nospam@needed.invalid> writes:
On Thu, 1/2/2025 11:29 AM, Scott Lurndal wrote:
Why would you expect the link step to require a lot of
memory? The linker builds an elf executable from the contents
of ELF object files, one ELF section at a time. It doesn't
construct the entire ELF executable in memory before writing it out.
It's based on experience, not imagination.
I've built Thunderbird on both Windows and Linux.
It was the Windows build that left a bad taste.
Once you repeatedly have build failures during linking,
you are always looking for it.
Ah, well windows. You need not elaborate.
I've been fortunate to have never built software in a
microsoft environment (aside an optical jukebox driver
for NT3.51 once on a contract job - even then I did
all the editing on unix and just compiled and tested
on the windows box).
I did a Windows C++ job for a year. I still can't believe how complicated Visual Studio (2017 IIRC) made the most basic things such as setting library and include paths which were buried 2 or 3 levels down in some sub menu not to mention all the "project" BS which forced a certain structure on to your code filesystem layout which I didn't particularly want. Also the fact that console and GUI apps require a totally different project setup and boiler plate
code from the start is just mind boggling.
Muttley@dastardlyhq.com writes:
and include paths which were buried 2 or 3 levels down in some sub menu not >> to mention all the "project" BS which forced a certain structure on to your >> code filesystem layout which I didn't particularly want. Also the fact that >> console and GUI apps require a totally different project setup and boiler >plate
code from the start is just mind boggling.
They always try to make things pretty and easy to use, but you end up
with that. I think the only way to tolerate that is to be born and
raised in such thing. Modularization is likely the most important thing
in programming and it's hard to minimally praise Microsoft on
modularization. For instance, is there any Windows software that
handles a TCP connection in an accept-fork-exec fashion?
For instance, is there any Windows software that
handles a TCP connection in an accept-fork-exec fashion?
On Sat, 04 Jan 2025 08:31:05 -0300, Salvador Mirzo wrote:
For instance, is there any Windows software that
handles a TCP connection in an accept-fork-exec fashion?
Almost certainly not. Because process creation is an expensive operation
on Windows.
Windows NT was masterminded by Dave Cutler, who was previously responsible for the VMS OS at his previous employer, DEC. He was a Unix-hater, part of
a bunch of them at DEC. They would instinctively turn away from Unix ways
of doing things, like forking multiple processes. So the systems they created did not encourage such techniques.
Lawrence D'Oliveiro <ldo@nz.invalid> writes:
Windows NT was masterminded by Dave Cutler ...
Is that Dave with a YouTube channel?
On Sat, 04 Jan 2025 08:31:05 -0300, Salvador Mirzo wrote:
For instance, is there any Windows software that
handles a TCP connection in an accept-fork-exec fashion?
Almost certainly not. Because process creation is an expensive operation
on Windows.
Windows NT was masterminded by Dave Cutler, who was previously responsible >for the VMS OS at his previous employer, DEC. He was a Unix-hater, part of
a bunch of them at DEC. They would instinctively turn away from Unix ways
of doing things, like forking multiple processes. So the systems they >created did not encourage such techniques.
On Sat, 4 Jan 2025 22:13:05 -0000 (UTC)
Lawrence D'Oliveiro <ldo@nz.invalid> gabbled:
On Sat, 04 Jan 2025 08:31:05 -0300, Salvador Mirzo wrote:
For instance, is there any Windows software that
handles a TCP connection in an accept-fork-exec fashion?
Almost certainly not. Because process creation is an expensive operation >>on Windows.
Windows NT was masterminded by Dave Cutler, who was previously responsible >>for the VMS OS at his previous employer, DEC. He was a Unix-hater, part of >>a bunch of them at DEC. They would instinctively turn away from Unix ways >>of doing things, like forking multiple processes. So the systems they >>created did not encourage such techniques.
Presumably VMS relied heavily on multithreading then like Windows or was a >process expected to everything itself sequentially?
Lawrence D'Oliveiro <ldo@nz.invalid> gabbled:
On Sat, 04 Jan 2025 08:31:05 -0300, Salvador Mirzo wrote:
For instance, is there any Windows software that
handles a TCP connection in an accept-fork-exec fashion?
Almost certainly not. Because process creation is an expensive operation >>on Windows.
Windows NT was masterminded by Dave Cutler, who was previously responsible >>for the VMS OS at his previous employer, DEC. He was a Unix-hater, part of >>a bunch of them at DEC. They would instinctively turn away from Unix ways >>of doing things, like forking multiple processes. So the systems they >>created did not encourage such techniques.
Presumably VMS relied heavily on multithreading then like Windows or was a >process expected to everything itself sequentially?
In article <vlecm0$1465i$1@dont-email.me>, <Muttley@dastardlyhq.com> wrote: >>On Sat, 4 Jan 2025 22:13:05 -0000 (UTC)
Lawrence D'Oliveiro <ldo@nz.invalid> gabbled:
On Sat, 04 Jan 2025 08:31:05 -0300, Salvador Mirzo wrote:
For instance, is there any Windows software that
handles a TCP connection in an accept-fork-exec fashion?
Almost certainly not. Because process creation is an expensive operation >>>on Windows.
Windows NT was masterminded by Dave Cutler, who was previously responsible >>>for the VMS OS at his previous employer, DEC. He was a Unix-hater, part of >>>a bunch of them at DEC. They would instinctively turn away from Unix ways >>>of doing things, like forking multiple processes. So the systems they >>>created did not encourage such techniques.
Presumably VMS relied heavily on multithreading then like Windows or was a >>process expected to everything itself sequentially?
Many system services on VMS are asynchronous, and the system
architecture provides a mechanisms to signal completion; ASTs,
mailboxes, etc. Thus, many programs (not all) on VMS are
written in a callback/closure style.
cross@spitfire.i.gajendra.net (Dan Cross) wibbled:
In article <vlecm0$1465i$1@dont-email.me>, <Muttley@dastardlyhq.com> wrote: >>>On Sat, 4 Jan 2025 22:13:05 -0000 (UTC)
Lawrence D'Oliveiro <ldo@nz.invalid> gabbled:
On Sat, 04 Jan 2025 08:31:05 -0300, Salvador Mirzo wrote:
For instance, is there any Windows software that
handles a TCP connection in an accept-fork-exec fashion?
Almost certainly not. Because process creation is an expensive operation >>>>on Windows.
Windows NT was masterminded by Dave Cutler, who was previously responsible >>>>for the VMS OS at his previous employer, DEC. He was a Unix-hater, part of >>>>a bunch of them at DEC. They would instinctively turn away from Unix ways >>>>of doing things, like forking multiple processes. So the systems they >>>>created did not encourage such techniques.
Presumably VMS relied heavily on multithreading then like Windows or was a >>>process expected to everything itself sequentially?
Many system services on VMS are asynchronous, and the system
architecture provides a mechanisms to signal completion; ASTs,
mailboxes, etc. Thus, many programs (not all) on VMS are
written in a callback/closure style.
I imagine that could become complicated very quickly and presumably relies
on the OS providing the signalling mechanisms for everything you might
want to do - eg waiting for a socket connection (or whatever the decnet >equivalent was).
In article <vlg4mb$1hi6d$1@dont-email.me>, <Muttley@DastardlyHQ.org> wrote: >>On Sun, 5 Jan 2025 21:09:55 -0000 (UTC)
cross@spitfire.i.gajendra.net (Dan Cross) wibbled:
In article <vlecm0$1465i$1@dont-email.me>, <Muttley@dastardlyhq.com> wrote: >>>>On Sat, 4 Jan 2025 22:13:05 -0000 (UTC)
Lawrence D'Oliveiro <ldo@nz.invalid> gabbled:
On Sat, 04 Jan 2025 08:31:05 -0300, Salvador Mirzo wrote:
For instance, is there any Windows software that
handles a TCP connection in an accept-fork-exec fashion?
Almost certainly not. Because process creation is an expensive operation >>>>>on Windows.
Windows NT was masterminded by Dave Cutler, who was previously responsible
for the VMS OS at his previous employer, DEC. He was a Unix-hater, part of
a bunch of them at DEC. They would instinctively turn away from Unix ways >>>>>of doing things, like forking multiple processes. So the systems they >>>>>created did not encourage such techniques.
Presumably VMS relied heavily on multithreading then like Windows or was a >>>>process expected to everything itself sequentially?
Many system services on VMS are asynchronous, and the system
architecture provides a mechanisms to signal completion; ASTs,
mailboxes, etc. Thus, many programs (not all) on VMS are
written in a callback/closure style.
I imagine that could become complicated very quickly and presumably relies >>on the OS providing the signalling mechanisms for everything you might
want to do - eg waiting for a socket connection (or whatever the decnet >>equivalent was).
It's a fairly common way to structure software even today. As I
On Sun, 5 Jan 2025 21:09:55 -0000 (UTC)
cross@spitfire.i.gajendra.net (Dan Cross) wibbled:
In article <vlecm0$1465i$1@dont-email.me>, <Muttley@dastardlyhq.com> wrote: >>>On Sat, 4 Jan 2025 22:13:05 -0000 (UTC)
Lawrence D'Oliveiro <ldo@nz.invalid> gabbled:
On Sat, 04 Jan 2025 08:31:05 -0300, Salvador Mirzo wrote:
For instance, is there any Windows software that
handles a TCP connection in an accept-fork-exec fashion?
Almost certainly not. Because process creation is an expensive operation >>>>on Windows.
Windows NT was masterminded by Dave Cutler, who was previously responsible >>>>for the VMS OS at his previous employer, DEC. He was a Unix-hater, part of >>>>a bunch of them at DEC. They would instinctively turn away from Unix ways >>>>of doing things, like forking multiple processes. So the systems they >>>>created did not encourage such techniques.
Presumably VMS relied heavily on multithreading then like Windows or was a >>>process expected to everything itself sequentially?
Many system services on VMS are asynchronous, and the system
architecture provides a mechanisms to signal completion; ASTs,
mailboxes, etc. Thus, many programs (not all) on VMS are
written in a callback/closure style.
I imagine that could become complicated very quickly and presumably relies
on the OS providing the signalling mechanisms for everything you might
want to do - eg waiting for a socket connection (or whatever the decnet >equivalent was).
On Mon, 6 Jan 2025 14:08:44 -0000 (UTC)
cross@spitfire.i.gajendra.net (Dan Cross) wibbled:
In article <vlg4mb$1hi6d$1@dont-email.me>, <Muttley@DastardlyHQ.org> wrote: >>>On Sun, 5 Jan 2025 21:09:55 -0000 (UTC)
cross@spitfire.i.gajendra.net (Dan Cross) wibbled:
In article <vlecm0$1465i$1@dont-email.me>, <Muttley@dastardlyhq.com> wrote:
On Sat, 4 Jan 2025 22:13:05 -0000 (UTC)
Lawrence D'Oliveiro <ldo@nz.invalid> gabbled:
On Sat, 04 Jan 2025 08:31:05 -0300, Salvador Mirzo wrote:
For instance, is there any Windows software that
handles a TCP connection in an accept-fork-exec fashion?
Almost certainly not. Because process creation is an expensive operation >>>>>>on Windows.
Windows NT was masterminded by Dave Cutler, who was previously responsible
for the VMS OS at his previous employer, DEC. He was a Unix-hater, part of
a bunch of them at DEC. They would instinctively turn away from Unix ways
of doing things, like forking multiple processes. So the systems they >>>>>>created did not encourage such techniques.
Presumably VMS relied heavily on multithreading then like Windows or was a
process expected to everything itself sequentially?
Many system services on VMS are asynchronous, and the system >>>>architecture provides a mechanisms to signal completion; ASTs, >>>>mailboxes, etc. Thus, many programs (not all) on VMS are
written in a callback/closure style.
I imagine that could become complicated very quickly and presumably relies >>>on the OS providing the signalling mechanisms for everything you might >>>want to do - eg waiting for a socket connection (or whatever the decnet >>>equivalent was).
It's a fairly common way to structure software even today. As I
In Windows yes, which frankly is probably not a coincidence. Not so much
in unix unless you're writing a GUI program.
cross@spitfire.i.gajendra.net (Dan Cross) wibbled:
In article <vlg4mb$1hi6d$1@dont-email.me>, <Muttley@DastardlyHQ.org> wrote: >>>On Sun, 5 Jan 2025 21:09:55 -0000 (UTC)
cross@spitfire.i.gajendra.net (Dan Cross) wibbled:
In article <vlecm0$1465i$1@dont-email.me>, <Muttley@dastardlyhq.com> wrote:
On Sat, 4 Jan 2025 22:13:05 -0000 (UTC)
Lawrence D'Oliveiro <ldo@nz.invalid> gabbled:
On Sat, 04 Jan 2025 08:31:05 -0300, Salvador Mirzo wrote:
For instance, is there any Windows software that
handles a TCP connection in an accept-fork-exec fashion?
Almost certainly not. Because process creation is an expensive operation >>>>>>on Windows.
Windows NT was masterminded by Dave Cutler, who was previously responsible
for the VMS OS at his previous employer, DEC. He was a Unix-hater, part of
a bunch of them at DEC. They would instinctively turn away from Unix ways
of doing things, like forking multiple processes. So the systems they >>>>>>created did not encourage such techniques.
Presumably VMS relied heavily on multithreading then like Windows or was a
process expected to everything itself sequentially?
Many system services on VMS are asynchronous, and the system >>>>architecture provides a mechanisms to signal completion; ASTs, >>>>mailboxes, etc. Thus, many programs (not all) on VMS are
written in a callback/closure style.
I imagine that could become complicated very quickly and presumably relies >>>on the OS providing the signalling mechanisms for everything you might >>>want to do - eg waiting for a socket connection (or whatever the decnet >>>equivalent was).
It's a fairly common way to structure software even today. As I
In Windows yes, which frankly is probably not a coincidence. Not so much
in unix unless you're writing a GUI program.
Muttley@DastardlyHQ.org writes:
In Windows yes, which frankly is probably not a coincidence. Not so much
in unix unless you're writing a GUI program.
ASTs and unix signals have similar semantics. It's certainly possible to >use, for example, SIGIO in a similar manner to the VMS AST, where the
AST signals I/O completion and the AST handler initiates a subsequent >operation.
In article <vlgots$1le5s$1@dont-email.me>, <Muttley@DastardlyHQ.org> wrote: >>In Windows yes, which frankly is probably not a coincidence. Not so much
in unix unless you're writing a GUI program.
Very much in Unix, actually. The kernel is highly asynchronous
(it must be, to match the hardware), and has been since the
early 1970s. Many user programs similarly.
Historically, many systems have provided direct support for
asynchronous programming on Unix. Going back to the early
commerical Unix days, masscomp's real time Unix had ASTs, not
signals, to support asynch IO directly from userspace. More
recently, POSIX.1b and POSIX AIO are widely supported. Polling
interfaces like kqueue and epoll, etc, exist largely to support
cross@spitfire.i.gajendra.net (Dan Cross) wibbled:
In article <vlgots$1le5s$1@dont-email.me>, <Muttley@DastardlyHQ.org> wrote: >>>In Windows yes, which frankly is probably not a coincidence. Not so much >>>in unix unless you're writing a GUI program.
Very much in Unix, actually. The kernel is highly asynchronous
(it must be, to match the hardware), and has been since the
early 1970s. Many user programs similarly.
Historically, many systems have provided direct support for
asynchronous programming on Unix. Going back to the early
commerical Unix days, masscomp's real time Unix had ASTs, not
signals, to support asynch IO directly from userspace. More
recently, POSIX.1b and POSIX AIO are widely supported. Polling
interfaces like kqueue and epoll, etc, exist largely to support
Multiplexing is not asychronous, its simply offloading status checking to
the kernel.
The program using is still very much sequential , at least at
that point.
Posix AIO is not asynch in the strict sense , its more "ok kernel, go do this >and I'll check how you're doing later". Proper asynch where the program >execution path gets bounced around between various callbacks is something >else entirely.
On Mon, 06 Jan 2025 15:05:33 GMT
scott@slp53.sl.home (Scott Lurndal) wibbled:
Muttley@DastardlyHQ.org writes:
In Windows yes, which frankly is probably not a coincidence. Not so much >>>in unix unless you're writing a GUI program.
ASTs and unix signals have similar semantics. It's certainly possible to >>use, for example, SIGIO in a similar manner to the VMS AST, where the
AST signals I/O completion and the AST handler initiates a subsequent >>operation.
Unix signals should only be used to set flags that are then read later.
Muttley@DastardlyHQ.org writes:...
Unix signals should only be used to set flags that are then read later.
You're opinion is not widely shared. Note that the POSIX specification carefully notes which interfaces are not signal-safe.
Unix signals should only be used to set flags that are then read later. Doing anything complicated in a signal handler is asking for trouble as you have
no idea where the program was when the signal occured and there can be all sorts of re-entrant issues or even deadlocks if using mutexes.
On 1/6/25 11:46, Scott Lurndal wrote:
Muttley@DastardlyHQ.org writes:...
Unix signals should only be used to set flags that are then read later.
You're opinion is not widely shared. Note that the POSIX specification
carefully notes which interfaces are not signal-safe.
What precisely does "signal-safe" mean? As I understand it, it is
supposed to be safe for a signal to interrupt standard library routines,
but that it's not safe for a signal handler to call most of those
functions. There's just a few exceptions, described below.
The C standard says the following about signal handlers:
"The functions in the standard library are not guaranteed to be
reentrant and may modify objects with static or thread storage duration. >239)" (7.1.4p4)
Footnote 239 says "Thus, a signal handler cannot, in general, call
standard library functions."
[snip]
"If a signal occurs other than as the result of calling the abort or
raise functions, the behavior is undefined if the signal handler reads
or modifies an atomic object that has an indeterminate representation." >(7.17.2p2)
"If a signal occurs other than as the result of calling the abort or
raise functions, the behavior is undefined if the signal handler calls
the atomic_init generic function." (7.17.2.1p4)
The POSIX standard claims that its version of <signal.h> conforms to the
C standard, and as far as I can see, the POSIX standard doesn't say
anything to define the behavior that is undefined by the C standard.
Could you demonstrate how, within the above restrictions, a signal
handler that doesn't cause the program to exit in one fashion or another >could do anything useful other than "set flags that are read later"?
I'm not saying it cannot be done. I claim no expertise in this kind of >programming - I never needed to write signal handlers.
However, the last
time I considered the matter carefully (which was two or three versions
of the C standard ago) I couldn't figure out how to do much more than
that. At that time I did not consider how POSIX affects the issue, and I >don't know enough about POSIX signals to evaluate that issue.
On 1/6/25 11:46, Scott Lurndal wrote:
Muttley@DastardlyHQ.org writes:...
Unix signals should only be used to set flags that are then read later.
You're opinion is not widely shared. Note that the POSIX specification
carefully notes which interfaces are not signal-safe.
What precisely does "signal-safe" mean?
On 1/6/25 11:46, Scott Lurndal wrote:
Muttley@DastardlyHQ.org writes:...
Unix signals should only be used to set flags that are then read later.
You're opinion is not widely shared. Note that the POSIX specification
carefully notes which interfaces are not signal-safe.
Could you demonstrate how, within the above restrictions, a signal
handler that doesn't cause the program to exit in one fashion or another >could do anything useful other than "set flags that are read later"?
I'm not saying it cannot be done. I claim no expertise in this kind of >programming - I never needed to write signal handlers. However, the last
time I considered the matter carefully (which was two or three versions
of the C standard ago) I couldn't figure out how to do much more than
that. At that time I did not consider how POSIX affects the issue, and I >don't know enough about POSIX signals to evaluate that issue.
Not so much in unix unless you're writing a GUI program.
Posix AIO is not asynch in the strict sense , its more "ok kernel, go do
this and I'll check how you're doing later".
I am no expert, but I guess if you need to do async programming on
UNIX/Linux userspace, your best is to use POSIX Threads.
On Mon, 6 Jan 2025 16:00:33 -0000 (UTC), Muttley wrote:
Posix AIO is not asynch in the strict sense , its more "ok kernel, go do
this and I'll check how you're doing later".
POSIX has rCLreal-time signalsrCY, which are very similar to VMS ASTs.
On Mon, 6 Jan 2025 17:53:20 -0000 (UTC), Kalevi Kolttonen wrote:
I am no expert, but I guess if you need to do async programming on
UNIX/Linux userspace, your best is to use POSIX Threads.
Threads are something you normally want to avoid, unless CPU usage is the >bottleneck in your application.
On Mon, 6 Jan 2025 17:53:20 -0000 (UTC), Kalevi Kolttonen wrote:
I am no expert, but I guess if you need to do async programming on
UNIX/Linux userspace, your best is to use POSIX Threads.
Threads are something you normally want to avoid, unless CPU usage is the >>bottleneck in your application.
Complete and utter nonsense.
I am no expert, but I guess if you need to do async programming
on UNIX/Linux userspace, your best is to use POSIX Threads.
The communication mechanisms between POSIX
threads and Unix I/O are completely alien to each-other: it is not
possible to poll() on a thread condition, nor is it it possible to set
up a condition to be woken by data on a file descriptor.
In article <vlgun1$1minf$1@dont-email.me>, <Muttley@DastardlyHQ.org> wrote: >>On Mon, 6 Jan 2025 15:22:51 -0000 (UTC)
Multiplexing is not asychronous, its simply offloading status checking to >>the kernel.
Of course. It's a means to allow a program to respond to
asynchronous events.
The program using is still very much sequential , at least at
that point.
But the events are not. That's the point. This allows a
program to initiate a non-blocking IO operation (like, say,
establishing a TCP connection using the sockets API), go do
something else, and check it's status later.
Posix AIO is not asynch in the strict sense , its more "ok kernel, go do this >>and I'll check how you're doing later". Proper asynch where the program >>execution path gets bounced around between various callbacks is something >>else entirely.
The POSIX AIO interface allows the kernel to generate a signal
to inform the program that an IO operation has completed, e.g.,
by setting up the `aio_sigevent` and `SIGEV_SIGNAL`. It doesn't
get much more asynchronous than that.
Muttley@DastardlyHQ.org writes:
On Mon, 06 Jan 2025 15:05:33 GMT
scott@slp53.sl.home (Scott Lurndal) wibbled:
Muttley@DastardlyHQ.org writes:
In Windows yes, which frankly is probably not a coincidence. Not so much >>>>in unix unless you're writing a GUI program.
ASTs and unix signals have similar semantics. It's certainly possible to >>>use, for example, SIGIO in a similar manner to the VMS AST, where the
AST signals I/O completion and the AST handler initiates a subsequent >>>operation.
Unix signals should only be used to set flags that are then read later.
You're opinion is not widely shared. Note that the POSIX specification >carefully notes which interfaces are not signal-safe.
Muttley@dastardlyhq.org wrote:
Unix signals should only be used to set flags that are then read later. Doing
anything complicated in a signal handler is asking for trouble as you have >> no idea where the program was when the signal occured and there can be all >> sorts of re-entrant issues or even deadlocks if using mutexes.
That is what I have learned, too, but I cannot remember the
source. Maybe one of Richard Stevens' UNIX books.
I am no expert, but I guess if you need to do async programming
on UNIX/Linux userspace, your best is to use POSIX Threads.
Linux offers signalfd, so you can indeed use poll(2) in a thread to be
woken up by any file descriptor, including a signal one (and that includes POSIX real-time signals).
scott@slp53.sl.home (Scott Lurndal) wibbled:
Muttley@DastardlyHQ.org writes:
On Mon, 06 Jan 2025 15:05:33 GMT
scott@slp53.sl.home (Scott Lurndal) wibbled:
Muttley@DastardlyHQ.org writes:
In Windows yes, which frankly is probably not a coincidence. Not so much >>>>>in unix unless you're writing a GUI program.
ASTs and unix signals have similar semantics. It's certainly possible to >>>>use, for example, SIGIO in a similar manner to the VMS AST, where the >>>>AST signals I/O completion and the AST handler initiates a subsequent >>>>operation.
Unix signals should only be used to set flags that are then read later.
You're opinion is not widely shared. Note that the POSIX specification >>carefully notes which interfaces are not signal-safe.
ITYF it is VERY widely shared and having a signal safe API function is only >step 2 - plenty of the functions in the program itself or 3rd party library >functions are probably not re-entrant safe and even if they are, having
code stomp over itself - eg if in the middle of writing a log message then a >signal is generated which tried to write a log message itself - is a very >poor way to write code.
Kalevi Kolttonen, dans le message <vlh5ag$1nruu$1@dont-email.me>, a
ocrita:
I am no expert, but I guess if you need to do async programming
on UNIX/Linux userspace, your best is to use POSIX Threads.
Very common misconception.
The communication mechanisms between POSIX
threads and Unix I/O are completely alien to each-other: it is not possible >to poll() on a thread condition, nor is it it possible to set up a condition >to be woken by data on a file descriptor. As a result, anybody who tries to >use threads to solve problems of I/O concurrency ends up having to implement >a poll() or equivalent loop in each thread, defeating the purpose.
POSIX threads are good to improve on computation concurrency, but they do
not make I/O concurrency simpler, quite the opposite.
The same might not be true for other kinds of threads.
In article <vlip2c$24ccb$1@dont-email.me>, <Muttley@DastardlyHQ.org> wrote: >>On Mon, 06 Jan 2025 16:46:56 GMT
ITYF it is VERY widely shared and having a signal safe API function is only >>step 2 - plenty of the functions in the program itself or 3rd party library >>functions are probably not re-entrant safe and even if they are, having >>code stomp over itself - eg if in the middle of writing a log message then a >>signal is generated which tried to write a log message itself - is a very >>poor way to write code.
So don't write code that way. It does not follow that the only
thing you can do in a signal handler is an some atomic flag
somewhere.
cross@spitfire.i.gajendra.net (Dan Cross) wibbled:
In article <vlgun1$1minf$1@dont-email.me>, <Muttley@DastardlyHQ.org> wrote: >>>On Mon, 6 Jan 2025 15:22:51 -0000 (UTC)
Multiplexing is not asychronous, its simply offloading status checking to >>>the kernel.
Of course. It's a means to allow a program to respond to
asynchronous events.
Thats not the same as the program itself being asynch.
The program using is still very much sequential , at least at
that point.
But the events are not. That's the point. This allows a
program to initiate a non-blocking IO operation (like, say,
establishing a TCP connection using the sockets API), go do
something else, and check it's status later.
Thats not proper asych, its still sequential. Proper asynch is when the >program execution path is directly modified by external events. Otherwise
you could claim simply using the standard file I/O system is asynchronous >programming as there's no guarantee that any data has been written to the disk
before write(), fprintf() etc return.
Posix AIO is not asynch in the strict sense , its more "ok kernel, go do this
and I'll check how you're doing later". Proper asynch where the program >>>execution path gets bounced around between various callbacks is something >>>else entirely.
The POSIX AIO interface allows the kernel to generate a signal
to inform the program that an IO operation has completed, e.g.,
by setting up the `aio_sigevent` and `SIGEV_SIGNAL`. It doesn't
get much more asynchronous than that.
Sure, but as I've said before, signals should only set flags to be processed >later.
cross@spitfire.i.gajendra.net (Dan Cross) wibbled:
In article <vlip2c$24ccb$1@dont-email.me>, <Muttley@DastardlyHQ.org> wrote: >>>On Mon, 06 Jan 2025 16:46:56 GMT
ITYF it is VERY widely shared and having a signal safe API function is only >>>step 2 - plenty of the functions in the program itself or 3rd party library >>>functions are probably not re-entrant safe and even if they are, having >>>code stomp over itself - eg if in the middle of writing a log message then a
signal is generated which tried to write a log message itself - is a very >>>poor way to write code.
So don't write code that way. It does not follow that the only
thing you can do in a signal handler is an some atomic flag
somewhere.
Just because you can doesn't mean you should. C lets you do a lot of things >that are a Bad Idea.
Lawrence D'Oliveiro , dans le message <vli2lj$1t3lt$8@dont-email.me>, a
ocrita:
Linux offers signalfd, so you can indeed use poll(2) in a thread to be
woken up by any file descriptor, including a signal one (and that includes >> POSIX real-time signals).
Proving my point that you need to use poll() even when doing threads.
In article <vlioum$24bqm$1@dont-email.me>, <Muttley@DastardlyHQ.org> wrote: >>On Mon, 6 Jan 2025 16:39:49 -0000 (UTC)
Thats not the same as the program itself being asynch.
Isn't it? The point is that the program kicks off multiple
Thats not proper asych, its still sequential. Proper asynch is when the >>program execution path is directly modified by external events. Otherwise >>you could claim simply using the standard file I/O system is asynchronous >>programming as there's no guarantee that any data has been written to the >disk
before write(), fprintf() etc return.
This is conflating multiple things. Most IO operations dealing
with the actual hardware _are_ asynchronous (this is what
McIlroy meant in the quote I posted earlier). The system call
interface gives the program the illusion of those happening
sequentially, but that's not how the devices really work.
Sure, but as I've said before, signals should only set flags to be processed >>later.
You said that, but that flies in the face of 50 years of
evidence to the contrary and the letter of the standard. This
In article <vljcbk$27v6l$1@dont-email.me>, <Muttley@DastardlyHQ.org> wrote: >>On Tue, 7 Jan 2025 13:18:54 -0000 (UTC)
cross@spitfire.i.gajendra.net (Dan Cross) wibbled:
In article <vlip2c$24ccb$1@dont-email.me>, <Muttley@DastardlyHQ.org> wrote: >>>>On Mon, 06 Jan 2025 16:46:56 GMT
ITYF it is VERY widely shared and having a signal safe API function is only >>>>step 2 - plenty of the functions in the program itself or 3rd party library >>>>functions are probably not re-entrant safe and even if they are, having >>>>code stomp over itself - eg if in the middle of writing a log message then >a
signal is generated which tried to write a log message itself - is a very >>>>poor way to write code.
So don't write code that way. It does not follow that the only
thing you can do in a signal handler is an some atomic flag
somewhere.
Just because you can doesn't mean you should. C lets you do a lot of things >>that are a Bad Idea.
I have to ask at this point: have you ever written a concurrent
program under Unix? One that used signals? For that matter,
have you ever written a program that used `fork()` and caught a
`SIGCHLD`?
In article <vlioum$24bqm$1@dont-email.me>, <Muttley@DastardlyHQ.org> wrote:
Thats not proper asych, its still sequential. Proper asynch is when the >>program execution path is directly modified by external events. Otherwise >>you could claim simply using the standard file I/O system is asynchronous >>programming as there's no guarantee that any data has been written to the disk
before write(), fprintf() etc return.
This is conflating multiple things. Most IO operations dealing
with the actual hardware _are_ asynchronous (this is what
McIlroy meant in the quote I posted earlier). The system call
interface gives the program the illusion of those happening
sequentially, but that's not how the devices really work.
It turns out the simple model of early research Unix was
insufficient for handling all sorts of important use cases,
hence why interfaces like `select` and `poll` were added.
cross@spitfire.i.gajendra.net (Dan Cross) wibbled:
In article <vljcbk$27v6l$1@dont-email.me>, <Muttley@DastardlyHQ.org> wrote: >>>On Tue, 7 Jan 2025 13:18:54 -0000 (UTC)
cross@spitfire.i.gajendra.net (Dan Cross) wibbled:
In article <vlip2c$24ccb$1@dont-email.me>, <Muttley@DastardlyHQ.org> wrote:
On Mon, 06 Jan 2025 16:46:56 GMT
ITYF it is VERY widely shared and having a signal safe API function is only
step 2 - plenty of the functions in the program itself or 3rd party library
functions are probably not re-entrant safe and even if they are, having >>>>>code stomp over itself - eg if in the middle of writing a log message then >>a
signal is generated which tried to write a log message itself - is a very >>>>>poor way to write code.
So don't write code that way. It does not follow that the only
thing you can do in a signal handler is an some atomic flag
somewhere.
Just because you can doesn't mean you should. C lets you do a lot of things >>>that are a Bad Idea.
I have to ask at this point: have you ever written a concurrent
program under Unix? One that used signals? For that matter,
have you ever written a program that used `fork()` and caught a
`SIGCHLD`?
Is that supposed to be a serious question?
The only thing that should ever be done in a child exit handler is a wait*() >or set a flag.
In article <vljgbg$28o6f$1@dont-email.me>, <Muttley@DastardlyHQ.org> wrote: >>On Tue, 7 Jan 2025 14:14:38 -0000 (UTC)
cross@spitfire.i.gajendra.net (Dan Cross) wibbled:
In article <vljcbk$27v6l$1@dont-email.me>, <Muttley@DastardlyHQ.org> wrote: >>>>On Tue, 7 Jan 2025 13:18:54 -0000 (UTC)
cross@spitfire.i.gajendra.net (Dan Cross) wibbled:
In article <vlip2c$24ccb$1@dont-email.me>, <Muttley@DastardlyHQ.org> >wrote:
On Mon, 06 Jan 2025 16:46:56 GMT
ITYF it is VERY widely shared and having a signal safe API function is >only
step 2 - plenty of the functions in the program itself or 3rd party >library
functions are probably not re-entrant safe and even if they are, having >>>>>>code stomp over itself - eg if in the middle of writing a log message then
a
signal is generated which tried to write a log message itself - is a very >>>>>>poor way to write code.
So don't write code that way. It does not follow that the only
thing you can do in a signal handler is an some atomic flag >>>>>somewhere.
Just because you can doesn't mean you should. C lets you do a lot of things >>>>that are a Bad Idea.
I have to ask at this point: have you ever written a concurrent
program under Unix? One that used signals? For that matter,
have you ever written a program that used `fork()` and caught a >>>`SIGCHLD`?
Is that supposed to be a serious question?
Yes.
The only thing that should ever be done in a child exit handler is a wait*() >>or set a flag.
I think perhaps you should try to write some complex programs in
the Unix environment before making such categorial statement.
This, however, does not follow. I don't see why "poll" is
strictly required for IO concurrency.
Dan Cross, dans le message <vljbvv$gl9$1@reader2.panix.com>, a ocrita:
This, however, does not follow. I don't see why "poll" is
strictly required for IO concurrency.
Well, try to do implement anything non-trivial involving I/O concurrency, >including timeouts, clients causing other clients to abort, etc., with
the common denominator of POSIX threads and come back telling us how you >managed that.
I tried, and stopped trying using threads for I/O concurrency.
cross@spitfire.i.gajendra.net (Dan Cross) wibbled:
In article <vlioum$24bqm$1@dont-email.me>, <Muttley@DastardlyHQ.org> wrote: >>>On Mon, 6 Jan 2025 16:39:49 -0000 (UTC)
Thats not the same as the program itself being asynch.
Isn't it? The point is that the program kicks off multiple
Not, it isn't. Using operating system facilities is standard programming, its >not asych programming whereby the program execution will be automatically
be diverted when an operation completes.
Thats not proper asych, its still sequential. Proper asynch is when the >>>program execution path is directly modified by external events. Otherwise >>>you could claim simply using the standard file I/O system is asynchronous >>>programming as there's no guarantee that any data has been written to the >>disk
before write(), fprintf() etc return.
This is conflating multiple things. Most IO operations dealing
with the actual hardware _are_ asynchronous (this is what
McIlroy meant in the quote I posted earlier). The system call
interface gives the program the illusion of those happening
sequentially, but that's not how the devices really work.
And? By your definition its still asynchronous programming.
Sure, but as I've said before, signals should only set flags to be processed >>>later.
You said that, but that flies in the face of 50 years of
evidence to the contrary and the letter of the standard. This
Please don't just make stuff up.
cross@spitfire.i.gajendra.net (Dan Cross) wibbled:
In article <vljgbg$28o6f$1@dont-email.me>, <Muttley@DastardlyHQ.org> wrote: >>>>[snip]
I have to ask at this point: have you ever written a concurrent
program under Unix? One that used signals? For that matter,
have you ever written a program that used `fork()` and caught a >>>>`SIGCHLD`?
Is that supposed to be a serious question?
Yes.
The only thing that should ever be done in a child exit handler is a wait*() >>>or set a flag.
I think perhaps you should try to write some complex programs in
the Unix environment before making such categorial statement.
Don't be patronising.
I've probably written more unix software in 30 years
than you've had hot dinners including a fully featured telnetd and numerous >other servers for work and play. And in the places I've worked which included >finance/banking, aerospace and government,
the advice was almost always NOT to
use signals in the first place unless there was no choice - eg SIGCHLD - but if
you did then do very little in the handler and nothing that could cause any >re-entrancy issues.
I suspect its you who needs a bit more practice at writing large multi process >and multi threaded applications.
there is no reason you cannot, say, have a signal handler that
broadcasts on a condition variable after an asynchronous IO operation completes, thus waking up a thread.
Dan Cross, dans le message <vljbvv$gl9$1@reader2.panix.com>, a ocrita:
This, however, does not follow. I don't see why "poll" is
strictly required for IO concurrency.
Well, try to do implement anything non-trivial involving I/O concurrency, >including timeouts, clients causing other clients to abort, etc., with
the common denominator of POSIX threads and come back telling us how you >managed that.
I tried, and stopped trying using threads for I/O concurrency.
In article <vljg72$28nj0$1@dont-email.me>, <Muttley@DastardlyHQ.org> wrote: >>On Tue, 7 Jan 2025 14:13:29 -0000 (UTC)
cross@spitfire.i.gajendra.net (Dan Cross) wibbled:
This is conflating multiple things. Most IO operations dealing
with the actual hardware _are_ asynchronous (this is what
McIlroy meant in the quote I posted earlier). The system call
interface gives the program the illusion of those happening
sequentially, but that's not how the devices really work.
And? By your definition its still asynchronous programming.
In the kernel, it sure is. Unix programmers have been writing
asynchronous programs (using e.g. `fork`) since 1970.
Please don't just make stuff up.
Hmm. I wonder what shell you use, if you use Unix at all.
Here for example is the signal handler for SIGINT in bash: >https://git.savannah.gnu.org/cgit/bash.git/tree/sig.c?h=devel#n691
Here's the SIGWINCH handler for good 'ol `script` from
OpenBSD: >https://github.com/openbsd/src/blob/6d253f95424ee0054c798f493d12377911cd3668/us
r.bin/script/script.c#L224
Those are just a few examples. If one cares to look, one will
find many more in non-trivial programs used in production daily.
cross@spitfire.i.gajendra.net (Dan Cross) writes:
[...]
there is no reason you cannot, say, have a signal handler that
broadcasts on a condition variable after an asynchronous IO operation
completes, thus waking up a thread.
The pthread_cond_* calls are not async-signal safe and hence, this is
either undefined behaviour (newly introduced with POSIX.1-2024) or
undefined behaviour if the signal handler interrupted something that
isn't async-signal safe (prior to POSIX.1-2024 and still retained in the >current text).
However, POSIX semaphores can safely be used for that.
In article <vljiml$296n5$1@dont-email.me>, <Muttley@DastardlyHQ.org> wrote: >>On Tue, 7 Jan 2025 15:35:44 -0000 (UTC)
I think perhaps you should try to write some complex programs in
the Unix environment before making such categorial statement.
Don't be patronising.
Wow, that's rich coming from you, my guy.
I've probably written more unix software in 30 years
than you've had hot dinners including a fully featured telnetd and numerous >>other servers for work and play. And in the places I've worked which included >>finance/banking, aerospace and government,
"For play" implies things that could be, or are, open source.
So post a link to code, then.
Bluntly, I don't believe that any of this is true. Your posts
here show a distinct lack of relevant experience and knowledge.
*shrug* Feel free to look up some things that I've written, if
you like. Perhaps you'll learn something.
"For play" implies things that could be, or are, open source.
So post a link to code, then.
Bluntly, I don't believe that any of this is true. Your posts
here show a distinct lack of relevant experience and knowledge.
cross@spitfire.i.gajendra.net (Dan Cross) wibbled:
In article <vljg72$28nj0$1@dont-email.me>, <Muttley@DastardlyHQ.org> wrote: >>>On Tue, 7 Jan 2025 14:13:29 -0000 (UTC)
cross@spitfire.i.gajendra.net (Dan Cross) wibbled:
This is conflating multiple things. Most IO operations dealing
with the actual hardware _are_ asynchronous (this is what
McIlroy meant in the quote I posted earlier). The system call >>>>interface gives the program the illusion of those happening >>>>sequentially, but that's not how the devices really work.
And? By your definition its still asynchronous programming.
In the kernel, it sure is. Unix programmers have been writing
asynchronous programs (using e.g. `fork`) since 1970.
Thats not what we're discussion here and you know it.
Please don't just make stuff up.
Hmm. I wonder what shell you use, if you use Unix at all.
Stupid comments really are your forte arn't they.
Here for example is the signal handler for SIGINT in bash: >>https://git.savannah.gnu.org/cgit/bash.git/tree/sig.c?h=devel#n691
Basically sets flags.
Here's the SIGWINCH handler for good 'ol `script` from
OpenBSD: >>https://github.com/openbsd/src/blob/6d253f95424ee0054c798f493d12377911cd3668/us
r.bin/script/script.c#L224
Not a clever way to do it because an xterm and other terminal progs can >indirectly cause a whole load of SIGWINCH to be created if someone is resizing
it and only the final one really needs the ioctl call done. Better to set a >flag then manually do a call when appropriate.
Those are just a few examples. If one cares to look, one will
find many more in non-trivial programs used in production daily.
There are always exceptions to every rule. You seem to be so desperate to
win this argument I can only assume your fragile ego has been burst by >someone having the temerity to disagree with you. Tough, suck it up.
cross@spitfire.i.gajendra.net (Dan Cross) wibbled:
In article <vljiml$296n5$1@dont-email.me>, <Muttley@DastardlyHQ.org> wrote: >>>On Tue, 7 Jan 2025 15:35:44 -0000 (UTC)
I think perhaps you should try to write some complex programs in
the Unix environment before making such categorial statement.
Don't be patronising.
Wow, that's rich coming from you, my guy.
"My guy?" LOL, how old are you, 12? :)
I've probably written more unix software in 30 years
than you've had hot dinners including a fully featured telnetd and numerous >>>other servers for work and play. And in the places I've worked which included
finance/banking, aerospace and government,
"For play" implies things that could be, or are, open source.
So post a link to code, then.
Nope, I like my relative anonymity here and I don't need to prove anything to >some twat with a chip on his shoulder getting worked up over technical trivia.
Bluntly, I don't believe that any of this is true. Your posts
Believe what you like, I couldn't give a rats arse.
here show a distinct lack of relevant experience and knowledge.
Whatever you say genius.
*shrug* Feel free to look up some things that I've written, if
you like. Perhaps you'll learn something.
Is this yours?
https://github.com/dancrossnyc
Am I supposed to be impressed?
cross@spitfire.i.gajendra.net (Dan Cross) writes:
In article <vlioum$24bqm$1@dont-email.me>, <Muttley@DastardlyHQ.org> wrote:
Thats not proper asych, its still sequential. Proper asynch is when the >>>program execution path is directly modified by external events. Otherwise >>>you could claim simply using the standard file I/O system is asynchronous >>>programming as there's no guarantee that any data has been written to the disk
before write(), fprintf() etc return.
This is conflating multiple things. Most IO operations dealing
with the actual hardware _are_ asynchronous (this is what
McIlroy meant in the quote I posted earlier). The system call
interface gives the program the illusion of those happening
sequentially, but that's not how the devices really work.
Indeed, and it was subsequently recognized that more than
the 'sync'[*] system call was required for applications to
ensure data was successfully written to the underlying
device.
Applications in those days (e.g. fsck) would access the
raw character device using the unbuffered read() and
write() system calls rather than using stdio. A key
characteristic of raw devices were that the hardware DMA would
use the application buffer directly rather than copying
the data to the kernel buffer pool first.
[*] I recall using 'sync;sync;sync' from the Sixth Edition
command line more than once, before rebooting.
Subsequently APIs like fdatasync(2) and open flags
such as O_DIRECT and O_DSYNC were added.
It turns out the simple model of early research Unix was
insufficient for handling all sorts of important use cases,
hence why interfaces like `select` and `poll` were added.
Although to be fair, select(2) originated with BSD and is
a bit less flexible than poll(2).
In article <vljjmf$g76$2@reader2.panix.com>,
Dan Cross <cross@spitfire.i.gajendra.net> wrote:
...
"For play" implies things that could be, or are, open source.
So post a link to code, then.
Bluntly, I don't believe that any of this is true. Your posts
here show a distinct lack of relevant experience and knowledge.
Or dementia. Lot of that going around in the world today.
Many Usenet posters fall into this category. They may have been >smart/accomplished once upon a time, but that was years/decades ago, and
now they're just living on memories.
Seriously, I've seen a lot of this over the years, and we should cut this
guy some slack.
In article <vGbfP.54357$XfF8.7280@fx04.iad>,
Scott Lurndal <slp53@pacbell.net> wrote:
cross@spitfire.i.gajendra.net (Dan Cross) writes:
In article <vlioum$24bqm$1@dont-email.me>, <Muttley@DastardlyHQ.org> wrote:
Applications in those days (e.g. fsck) would access the
raw character device using the unbuffered read() and
write() system calls rather than using stdio. A key
characteristic of raw devices were that the hardware DMA would
use the application buffer directly rather than copying
the data to the kernel buffer pool first.
They still do!
On 07 Jan 2025 15:54:48 GMT Nicolas George <nicolas$george@salle-s.org> wibbled:
I tried, and stopped trying using threads for I/O concurrency.
For some mad reason it seems to be the way to do it in Windows and also
Java IIRC.
Lawrence D'Oliveiro , dans le message <vli2lj$1t3lt$8@dont-email.me>, a
|-crit-a:
Linux offers signalfd, so you can indeed use poll(2) in a thread to be
woken up by any file descriptor, including a signal one (and that
includes POSIX real-time signals).
Proving my point that you need to use poll() even when doing threads.
On 07 Jan 2025 08:59:28 GMT, Nicolas George wrote:
Lawrence D'Oliveiro , dans le message <vli2lj$1t3lt$8@dont-email.me>, a
|-crit-a:
Linux offers signalfd, so you can indeed use poll(2) in a thread to be
woken up by any file descriptor, including a signal one (and that
includes POSIX real-time signals).
Proving my point that you need to use poll() even when doing threads.
But you said rCLit is not possible to poll() on a thread conditionrCY, when it
fact such usage is commonplace, as I pointed out.
It is perfectly possible to poll() on a thread condition. See pipe(2).
In article <vljmc6$29tkd$1@dont-email.me>, <Muttley@DastardlyHQ.org> wrote: >>On Tue, 7 Jan 2025 16:02:51 -0000 (UTC)
In the kernel, it sure is. Unix programmers have been writing >>>asynchronous programs (using e.g. `fork`) since 1970.
Thats not what we're discussion here and you know it.
Actually, it is.
https://git.savannah.gnu.org/cgit/bash.git/tree/sig.c?h=devel#n691
Basically sets flags.
Did you actually read and understand any of that code?
Not a clever way to do it because an xterm and other terminal progs can >>indirectly cause a whole load of SIGWINCH to be created if someone is >resizing
it and only the final one really needs the ioctl call done. Better to set a >>flag then manually do a call when appropriate.
Ok. You may even be right! But tell me: where would you check
those flags?
Regardless, here you are, again, moving the goalposts in the
face of evidence that contradicted your earlier position.
There are always exceptions to every rule. You seem to be so desperate to >>win this argument I can only assume your fragile ego has been burst by >>someone having the temerity to disagree with you. Tough, suck it up.
Ah, here we go. The classic attempt at an insult.
Look, you made categorical, definitive statements. Those
statements were factually incorrect. I pointed that out. You
Perhaps I am not the one with the fragile ego that needs to suck
it up when disagreed with.
In article <vljmlt$29vt3$1@dont-email.me>, <Muttley@DastardlyHQ.org> wrote: >>On Tue, 7 Jan 2025 16:10:55 -0000 (UTC)
cross@spitfire.i.gajendra.net (Dan Cross) wibbled:
Nope, I like my relative anonymity here and I don't need to prove anything to >>some twat with a chip on his shoulder getting worked up over technical trivia.
Ok. So we're just supposed to take your word for it, I guess.
Got it.
Believe what you like, I couldn't give a rats arse.
You also have no evidence to back up your claims, it seems.
Am I supposed to be impressed?
*shrug* I think my credentials speak for themselves. I really
don't care whether you're impressed or not.
cross@spitfire.i.gajendra.net (Dan Cross) writes:
In article <vGbfP.54357$XfF8.7280@fx04.iad>,
Scott Lurndal <slp53@pacbell.net> wrote:
cross@spitfire.i.gajendra.net (Dan Cross) writes:
In article <vlioum$24bqm$1@dont-email.me>, <Muttley@DastardlyHQ.org> wrote:
Applications in those days (e.g. fsck) would access the
raw character device using the unbuffered read() and
write() system calls rather than using stdio. A key
characteristic of raw devices were that the hardware DMA would
use the application buffer directly rather than copying
the data to the kernel buffer pool first.
They still do!
Well, not on linux. Even O_DIRECT still goes through
the file cache, last I checked.
I submitted a 'raw device' patch to the linux mailing
list in the late 90s while at SGI. It wasn't accepted because
O_DIRECT was considered sufficient, even with the spurious
copy. The overhead of pinning the user space pages was
considered onerous.
On Tue, 7 Jan 2025 15:56:46 -0000 (UTC), Muttley wrote:
On 07 Jan 2025 15:54:48 GMT Nicolas George <nicolas$george@salle-s.org>
wibbled:
I tried, and stopped trying using threads for I/O concurrency.
For some mad reason it seems to be the way to do it in Windows and also
Java IIRC.
Remember the era: it was the 1990s, when threads were still a new thing to >PC OSes, and they were considered the best way to do everything involving >nondeterminism, including GUIs.
cross@spitfire.i.gajendra.net (Dan Cross) wibbled:
In article <vljmlt$29vt3$1@dont-email.me>, <Muttley@DastardlyHQ.org> wrote: >>>On Tue, 7 Jan 2025 16:10:55 -0000 (UTC)
cross@spitfire.i.gajendra.net (Dan Cross) wibbled:
Nope, I like my relative anonymity here and I don't need to prove anything to
some twat with a chip on his shoulder getting worked up over technical trivia.
Ok. So we're just supposed to take your word for it, I guess.
Got it.
In one.
Believe what you like, I couldn't give a rats arse.
You also have no evidence to back up your claims, it seems.
Plenty of evidence out there.
Am I supposed to be impressed?
*shrug* I think my credentials speak for themselves. I really
don't care whether you're impressed or not.
What credentials? You work for some neverheardofit software house and have >mostly done a load of forks of other peoples code. Standard dev stuff, nothing >special.
Scott Lurndal, dans le message <BcmfP.289889$aTp4.50420@fx09.iad>, a
ocrita:
It is perfectly possible to poll() on a thread condition. See pipe(2).
It is possible to write code to wake a thread blocked in poll(). I have not >tried to deny this. It is not possible to poll() directly on a thread >condition. You have not disproved that.
cross@spitfire.i.gajendra.net (Dan Cross) wibbled:
In article <vljmc6$29tkd$1@dont-email.me>, <Muttley@DastardlyHQ.org> wrote: >>>On Tue, 7 Jan 2025 16:02:51 -0000 (UTC)
In the kernel, it sure is. Unix programmers have been writing >>>>asynchronous programs (using e.g. `fork`) since 1970.
Thats not what we're discussion here and you know it.
Actually, it is.
Ah ok, goalposts moved. Why not some straw men while you're at it?
https://git.savannah.gnu.org/cgit/bash.git/tree/sig.c?h=devel#n691
Basically sets flags.
Did you actually read and understand any of that code?
Did you?
Not a clever way to do it because an xterm and other terminal progs can >>>indirectly cause a whole load of SIGWINCH to be created if someone is >>resizing
it and only the final one really needs the ioctl call done. Better to set a >>>flag then manually do a call when appropriate.
Ok. You may even be right! But tell me: where would you check
those flags?
Presuably a genius like you would know most terminal programs have a seperate >thread or a multiplex timeout in order to flash the cursor. You work out
the rest.
Regardless, here you are, again, moving the goalposts in the
face of evidence that contradicted your earlier position.
Irony, love it.
There are always exceptions to every rule. You seem to be so desperate to >>>win this argument I can only assume your fragile ego has been burst by >>>someone having the temerity to disagree with you. Tough, suck it up.
Ah, here we go. The classic attempt at an insult.
If the shoe fits.
Look, you made categorical, definitive statements. Those
statements were factually incorrect. I pointed that out. You
No, I stated the majority approach to using signals. You disagree which is >fine, but don't pretent your view is THE view, it isn't.
Perhaps I am not the one with the fragile ego that needs to suck
it up when disagreed with.
Ego size on usenet is almost always correlated with the verbiage of a reply.
In article <vllcml$2mqb8$1@dont-email.me>, <Muttley@DastardlyHQ.org> wrote: >>On Tue, 7 Jan 2025 17:23:01 -0000 (UTC)
You also have no evidence to back up your claims, it seems.
Plenty of evidence out there.
Plenty of contradictory evidence, you mean.
What credentials? You work for some neverheardofit software house and have >>mostly done a load of forks of other peoples code. Standard dev stuff, nothing
special.
Yeah, ok, sure.
In article <vllcgq$2mphu$1@dont-email.me>, <Muttley@DastardlyHQ.org> wrote: >>On Tue, 7 Jan 2025 17:19:56 -0000 (UTC)
Presuably a genius like you would know most terminal programs have a seperate >>thread or a multiplex timeout in order to flash the cursor. You work out >>the rest.
Right, handwave away those very real concerns. We're talking
about Unix here, not code running on some microcontroller; code
No, I stated the majority approach to using signals. You disagree which is >>fine, but don't pretent your view is THE view, it isn't.
Bluntly, I don't see any evidence that you are qualified enough
to make any statement regarding the "majority approach" to,
Ego size on usenet is almost always correlated with the verbiage of a reply.
I'm not the one who started with dishing out insults at the
first person who disagreed with me.
Feel free to have the last word, but absent some actually
technical point, I'm done with you.
I think it's important to define what you mean when you write,
"thread condition." What, exactly, is that? Perhaps you mean
a condition variable?
If so, that's true, but I fail to see
the relevance: people write multithreaded code that does IO in
multiple all the time; there are some techniques that are common
for this (Scott alluded to the so-called "pipe trick", due to
Bernstein) and some that are less common.
Dan Cross, dans le message <vllql7$sn6$2@reader2.panix.com>, a |-crit-a:
I think it's important to define what you mean when you write,
"thread condition." What, exactly, is that? Perhaps you mean
a condition variable?
Yes, of course that is what rCLthread conditionrCY means in the context of a >discussion about POSIX threads.
If so, that's true, but I fail to see
the relevance: people write multithreaded code that does IO in
multiple all the time; there are some techniques that are common
for this (Scott alluded to the so-called "pipe trick", due to
Bernstein) and some that are less common.
Yes: there are some techniques that are common to implement I/O concurrency >and that work in the context of threads. You are arguing my point for me:
the threads did not make implementing the I/O concurrency simpler; quite the >opposite it they made them harder, as proven by the fact that rCLtechniquesrCY >had to be deployed.
POSIX threads do not make I/O concurrency easier, they are not made for
that, they are for performance.
Dan Cross, dans le message <vllql7$sn6$2@reader2.panix.com>, a |-crit-a:
I think it's important to define what you mean when you write,
"thread condition." What, exactly, is that? Perhaps you mean
a condition variable?
Yes, of course that is what rCLthread conditionrCY means in the context of a >discussion about POSIX threads.
POSIX threads do not make I/O concurrency easier, they are not made for
that, they are for performance.
On Wed, 8 Jan 2025 13:00:01 -0000 (UTC)
I don't need to prove myself to argue with some random troll on a newsgroup. >If you can't handle that thats your problem, not mine.
Muttley@DastardlyHQ.org writes:
On Wed, 8 Jan 2025 13:00:01 -0000 (UTC)
[...]
I don't need to prove myself to argue with some random troll on a
newsgroup. If you can't handle that thats your problem, not mine.
Look in the mirror, nameless troll. [...]
Dan is well known and respected in the Unix world. You, not so much.
I don't need to prove myself to argue with some random troll on a newsgroup. If you can't handle that thats your problem, not mine.
I vaguely remember Oracle complaining about this back in the day meaning
they couldn't guarantee their RDBMS transaction writes on Linux.
On Sat, 04 Jan 2025 19:17:15 -0300, Salvador Mirzo wrote:
Lawrence D'Oliveiro <ldo@nz.invalid> writes:
Windows NT was masterminded by Dave Cutler ...
Is that Dave with a YouTube channel?
No, thatrCOs a different former Microsoftie, but he has had Cutler on his channel for an extended interview.
I found it ironic that there was a PiDP-11, I think it was, placed within armrCOs reach behind the guy during the entire interview. You know, the PDP-11 emulator that runs on a Linux-based Raspberry Pi. I wonder if the Unix-hater ever noticed that ...
Muttley@DastardlyHQ.org writes:
On Wed, 8 Jan 2025 13:00:01 -0000 (UTC)
I don't need to prove myself to argue with some random troll on a newsgroup. >>If you can't handle that thats your problem, not mine.
Look in the mirror, nameless troll.
Dan is well known and respected in the Unix world. You, not so much.
On 2025-01-08, Muttley@DastardlyHQ.org <Muttley@DastardlyHQ.org> wrote:
I don't need to prove myself to argue with some random troll on a newsgroup. >> If you can't handle that thats your problem, not mine.
I have to say, that's pretty tone deaf, as a reply to Dan Cross.
The usual "i don't agree with you so you must be a troll" attitude.
On Wed, 8 Jan 2025 20:27:54 -0000 (UTC)
Kaz Kylheku <643-408-1753@kylheku.com> wibbled:
On 2025-01-08, Muttley@DastardlyHQ.org <Muttley@DastardlyHQ.org> wrote:
I don't need to prove myself to argue with some random troll on a newsgroup.
If you can't handle that thats your problem, not mine.
I have to say, that's pretty tone deaf, as a reply to Dan Cross.
Sorry if I don't hero worship like you. If I think someone's talking bollocks then I'll call it out.
[snip]
Dan Cross being a random troll in a newsgroup is an example of bollocks,
and it's being called out.
Even if Dan happened to be caught talking bollocks, it still wouldn't
make him a troll, or random. It's simply not factual or rational.
On 2025-01-15, Muttley@DastardlyHQ.org <Muttley@DastardlyHQ.org> wrote:
The usual "i don't agree with you so you must be a troll" attitude.
Rather, it is this accusation that is an extremely common trope.
Rarely is it true.
On 2025-01-15, Muttley@DastardlyHQ.org <Muttley@DastardlyHQ.org> wrote:
On Wed, 8 Jan 2025 20:27:54 -0000 (UTC)
Kaz Kylheku <643-408-1753@kylheku.com> wibbled:
On 2025-01-08, Muttley@DastardlyHQ.org <Muttley@DastardlyHQ.org> wrote:
I don't need to prove myself to argue with some random troll on a >newsgroup.
If you can't handle that thats your problem, not mine.
I have to say, that's pretty tone deaf, as a reply to Dan Cross.
Sorry if I don't hero worship like you. If I think someone's talking bollocks
then I'll call it out.
Glad you understand the concept.
Dan Cross being a random troll in a newsgroup is an example of bollocks,
and it's being called out.
Even if Dan happened to be caught talking bollocks, it still wouldn't
make him a troll, or random. It's simply not factual or rational.
Given that he looks late 20s in his picture he's
certaiunly no greybeard with a long history of contributions.
Its very often true. Calling someone a troll in a newsgroup is a drop-the-mic and walk off because you've lost the argument.
In article <vmakbg$3eqtn$1@dont-email.me>, <Muttley@DastardlyHQ.org> wrote: >>[snip]
Given that he looks late 20s in his picture he's
certaiunly no greybeard with a long history of contributions.
I wish I were still in my late 20s. Perhaps my knees would hurt
less.
And if only my hair (and beard) were more colorful, but sadly, I
went almost totally gray in Afghanistan. Perhaps I'll turn out
In article <vmakbg$3eqtn$1@dont-email.me>, <Muttley@DastardlyHQ.org> wrote: >>[snip]
Given that he looks late 20s in his picture he's
certaiunly no greybeard with a long history of contributions.
I wish I were still in my late 20s. Perhaps my knees would hurt
less.
cross@spitfire.i.gajendra.net (Dan Cross) writes:
In article <vmakbg$3eqtn$1@dont-email.me>, <Muttley@DastardlyHQ.org> wrote: >>>[snip]
Given that he looks late 20s in his picture he's
certaiunly no greybeard with a long history of contributions.
I wish I were still in my late 20s. Perhaps my knees would hurt
less.
Weren't you at Murray Hill, before the move to Summit?
On Thu, 16 Jan 2025 14:51:40 -0000 (UTC)
cross@spitfire.i.gajendra.net (Dan Cross) wibbled:
And if only my hair (and beard) were more colorful, but sadly, I2 of my family also served there and they don't act like dicks in online forums.
went almost totally gray in Afghanistan. Perhaps I'll turn out
| Sysop: | Amessyroom |
|---|---|
| Location: | Fayetteville, NC |
| Users: | 63 |
| Nodes: | 6 (0 / 6) |
| Uptime: | 492924:49:32 |
| Calls: | 840 |
| Calls today: | 1 |
| Files: | 1,300 |
| D/L today: |
5 files (16,259K bytes) |
| Messages: | 258,313 |