Implementing strstr

R

Rob Kendrick

In my defense, I may have spent a *tiny* bit less than two full hours
thinking about that.

That, and I don't know of any news readers with built-in C syntax
checkers. And it's not as if anybody writes valid C perfectly first
time all the time.

(Time to go off and patch Claws, I think...)

B.
 
S

Seebs

That, and I don't know of any news readers with built-in C syntax
checkers. And it's not as if anybody writes valid C perfectly first
time all the time.

I'm particularly prone to trivial and obvious mistakes, while I tend
to get other stuff right more easily. This is apparently stereotypical
for severe ADHD. As a result, I'm quite likely to, say, have fencepost
errors in string processing, or try to compile something only to discover
that I changed the name for a variable halfway through an implementation.
On the other hand, I added thread safety to pseudo, using a part of the
POSIX thread API I'd probably seen maybe once before, and (once I got past
the obvious and trivial errors) the actual thread safety design worked
flawlessly on the first try.

The hard part is easy; the easy part is hard. This pattern has been with me
all my life.

-s
 
S

spinoza1111

I did not claim that = in place of == was a bug.  In fact it is
obvious that putting == back introduces more bugs.  My point was that
you did not know what your code was doing: you reported favourably on
a bug fix that could not possibly have any effect.  You can't fix (or
do pretty much anything with) code you don't understand.


I don't expect you to change your style -- you've evolved it to
provoke a response here rather than make your code clear -- but if
there are any people learning C who are tempted to copy it: please
don't -- it confuses even the author of it.

I'm afraid you don't know what you're talking about, and you seem to
have little experience in actual debugging outside of the corporate
environment, one in which people are simultaneously pressured and
mollycoddled so as to get Seebach's eternal sunshine of the spotless
mind, where he, after what he claims to is several years of
experience, gets && out of order in a common pattern. I already fixed
the other bug as noted above, and make no claim that the code is bug
free. In fact, I shall be making an informal correctness proof in
order to make that claim in the future, and above I mention this fact,
along with my plan to test more comprehensively.

You're an idiot, Bacarisse. To relax on a 30 minute ferry ride, I get
my notebook out and spend a little time documenting and then writing
code that even with bugs is better than any of the crap posted here.
You find a typo but now that you've been infantilized and deskilled
from last year, probably from a combination of this ng and some silly
job, you don't suggest a fix like the pros here, nor alternatives. The
bug was fixed, along with my own off by one, which resulted not from
the incompetence of a Seebach but from an excess of diligence.

This is what collective programming is all about. Finding and fixing
bugs without this adolescent behavior which results from your
emotional and sexual anxieties; most programmers fail and any number
of actual living tasks (Seebach being exhibit A) and for them, making
a mistake in programming is the last straw, something they fear and a
fault, therefore, they transfer to scapegoats like Schildt.
 
S

spinoza1111

You can.

However, the statement by Nilges above highlights a particular kind of
madness.

Why doesn't he use string.h?  From the rest of what he's written, I'd guess
that it's because he thinks null-terminated strings are error-prone and
poorly designed.

Duh yeah.
So.  Avoiding null-terminated strings?  A plausible solution.

Writing your own code to manipulate them, demonstrating repeatedly that,
at least for you, the design is indeed highly error-prone, and simply beyond
your abilities to debug in a reasonable amount of time?  Stupid.

Amazing. You act as if I work for you since the corporate mindset has
so "colonized your lifeworld" as in Habermas you have no other mental
model beyond that. Dear Peter, I do not work for you and would never
hire you.

You are unable to hold down any other job besides the mollycoddled
paraprogrammer who's been snugly fit into a corporate role where he
can do the least amount of damage, and in that role, you have chosen
not to grow up, and start addressing your serious personal issues. You
can't clean houses on a corporate schedule, you'd fail as a
telemarketer, and you cannot teach I'd wot. You're a loser, and you
know it, on artificial life support in a matrix (the American
corporation which has been bought by Intel) prone to fail.

For despite the mythos of the lower middle class, that "programming is
a secure job", corporations design programming jobs very, very
carefully to ensure that at any time, should Wall Street so desire,
entire chunks/modules/assemblies of programmers and similar drones can
be unplugged neatly even as the astronaut unplugs "memory modules"
from Hal to have Hal only gracefully degrade.

This is in fact why you lack the skill to see (in the case of your
absurd %s tool) that starting with strchr and not strstr was an error.
Corporations (in my direct experience: also cf. Kraft 1878,
Programmers and Managers) people with end to end skills who, when
designing a filter for %s would see that %s is a string, and not two
characters, are precisely the kind of people who, especially if women,
were hounded out of the field (or left in disgust) in 1980s, once the
class war of the rich on the middle class got under way.

This is why you lack the skill to create code that, if buggy,
converges on nonbuggy. Your ridiculous filter for %s is precisely the
kind of code that diverges from nonbuggy because it starts off on the
wrong foot. And because you've never seen code whose developers have
been given enough time to converge on nonbuggy and documented by the
literate programmers themselves, you mistake the bug rate in 1.0 for a
linear function.
If you have to use null-terminated strings, the sane thing to do would
be to use the *already debugged* standard tools, reducing your exposure
to the sorts of errors that crop up when you start messing with strings
directly.

Well, dear Peter, far be it from you to put yourself in any situation
of risk where the fact that you've become a nonprogramming and
overpaid programmer through script kiddiedom, backstabbing, and
posting attacks on people like Schildt is something you seek to hide
at all costs.

Bacarisse, who used to be a good programmer but has been corrupted by
the ethos of this newsgroup, found a bug: I assigned zero to ptrHandle
and did not compare it to zero as was planned, which meant that
release 1.0 would never find overlap strings. I fixed the bug (which
results from a bug in the design in C: as I've said, there are
different types of bugs including your far less competent genre) and
also found that I was incorrectly incrementing the char handle. At
that point, the code resumed giving correct results for a test suite
which is smaller than my test suite for replace() but useful for
others here, but I did not claim the code is correct, since this is
collective debugging which is meant to allow others to participate and
hone their skills.

[You don't come here to participate and hone your skills though God
knows they could use a good honing. You come here to claim that
although you can't write a strlen bug free you are nonetheless a Great
Programmer, which you really aren't. You are here as a paid (indeed,
overpaid) employee of Wind River Systems to have unpaid slaves debug
your incompetent code.]

As I've said, the next step for me is twofold: to make the test suite
more exacting, and to post an informal correctness proof in English of
the sort used in extreme pair programming and structured walkthroughs
after people like you have been asked to leave.
 
S

spinoza1111

That can be a very good idea.


I probably will until either I can confirm the specific insanity or
come up with a rational explanation.  Nilges does not write like someone
who thinks he is trying to learn to avoid mistakes; he writes like
someone who is trying to prove that everyone else is wrong about how
to do things.

No, not everyone else, merely people like you, who in my experience
are strikingly common. As common as dirt.

It is to me an amusing paradox that I'm the best C programmer in this
newsgroup while not really knowing dick about C.
 
S

spinoza1111

What's the point of defining TRUTH as -1, instead of accepting the
language-defined truth value of 1, especially since the only thing
you ever do with this value (based on an admittedly quick scan of your
code) is assign it, under some conditions, to booFound, whose value
is then tested by "if (booFound)"?
Likewise, why obfuscate things by defining your own NULLITY macro
instead of using the standard-defined NULL?

...>               (*ptrMaster==*ptrTarget ? TRUTH : FALSITY)

If TRUTH were defined in the expected way, this would be equivalent to
                 (*ptrMaster == *ptrTarget)
which would be much clearer to the reader.  The larger expression,


appears to have been composed solely for its confusion factor, since as
a boolean expression it's equivalent to
      (*ptrTarget && *ptrMaster && (*ptrMaster == *ptrTarget))
or the even simpler
      (*ptrTarget && (*ptrTarget == *ptrMaster))
--
Morris Keesan -- (e-mail address removed)


What's the point of defining TRUTH as -1, instead of accepting the
language-defined truth value of 1, especially since the only thing
you ever do with this value (based on an admittedly quick scan of your
code) is assign it, under some conditions, to booFound, whose value
is then tested by "if (booFound)"?

Well, if you must know, I have three reasons.

One is a desire to offend pompous idiots who've confused their
knowledge of C with knowledge of computer science, and who actually
believe that coding in shibboleth style exhibits great genius.

The other is that today I teach English (and history, law, and
politics at uni level), and true is an adjective whereas the use of
the preprocessor symbol is as a NOUN.

The third is the fable of the sheep, who demanded to be hanged as
sheep and not as a lamb. There's really no point in coding for
localized and shibboleth understandability for people who don't
understand English over a small lower bound of complexity, and who,
like dear Peter Seebach, claim to have ADHD when asked to pay
attention to something that doesn't fit their mental patterns, mental
patterns outside of which they cannot think because they were
mollycoddled in school.


Likewise, why obfuscate things by defining your own NULLITY macro
instead of using the standard-defined NULL?

...>               (*ptrMaster==*ptrTarget ? TRUTH : FALSITY)

Good point: that particular subexpression was what was left over as
the container expression was modified and of course, it can be
simplified (it might be by an optimizing compiler, but we cannot count
on that). It will be fixed in the next release and you shall be
credited.
If TRUTH were defined in the expected way, this would be equivalent to
                 (*ptrMaster == *ptrTarget)
which would be much clearer to the reader.  




The larger expression,
appears to have been composed solely for its confusion factor, since as
a boolean expression it's equivalent to
      (*ptrTarget && *ptrMaster && (*ptrMaster == *ptrTarget))

This is to me at this time the most sensible simplification. OK, let's
try it out.

No it doesn't work. That is because you got the original statement
wrong:

*ptrTarget
?
(*ptrMaster ?
*ptrMaster==*ptrTarget
:
FALSITY)
:
(booFound = TRUTH, FALSITY)

You omitted the part where I need to assign booFound, and that need is
why the expression was designed as above. You omitted the second colon
subexpression.

You see, the above was composed not for shibboleth readability but
based on the actual need in the code to avoid evaluating the wrong
things. Your basic question is whether you're out of target.

If you have come to the end of the target, it seems unavoidable that
you must indicate that ONLY IN THIS SITUATION do you have booFound. In
other words, we never have a found unless we get to end of target.

If you have not then the question is whether you have come to the end
of the master string. If you have not then, and only then, it is safe
to compare the chars in the master and target, breaking out of the
loop if they fail to match and continuing if not.

But if you have come to the end of the master string, then it's Miller
time.

Nope, my code is best, and the reason is that it follows the logic of
the problem as expressed in an outline or complex sentence. The reason
it is not popular is that younger programmers, as products of a racist
educational system declining in quality at both the high and low ends,
no longer have to make outlines in English class, and half-educated
teachers, who can neither write nor parse English above a low lower
bound, actively discourage higher level sentence construction in their
students lest they have to grade papers the teachers themselves do not
understand.

In a talk at the defunct Data Processing Management Association in
1976, I pointed out that "understandability of code" is a function of
education, therefore, no set of stylistic standards or shibboleths can
create truly understandable code. For this reason, I write for
understandability not as a denizen of a real world (which contains
people like Seebach whom I cannot stand and who won't read my code
because iddums has ADHD) but as what Kant called the citizen of a
better world, in which people think in outlines and use and understand
complex sentences.
or the even simpler
      (*ptrTarget && (*ptrTarget == *ptrMaster))

Wow, a Harvard alumni, faculty or student. I'm honored. But you're
wrong about the second change unless I don't know what the hell I'm
talking about, which is possible at all times for all of us, for all
men are mortal, even Harvard men.
 
S

spinoza1111

~TRUTH == FALSITY;
also, if booleans are one bit, a set bit is -1 in two's complement
notation.
As an added bonus you get an error if you try to get the root of
TRUTH, unless you accept that the answer is complex.

Also, Truth is all ones and no zeroes which looks terrific on a blue
screen of death.
 
S

spinoza1111

He's an idiot.

**** you, asshole.
Specifically, he's picked it because, on some machines, it's all-bits-one,
thus "less like zero".  However, this is overwhelmed by the much stronger
arguments in favor of 1:
        * It's what boolean operators generate for truth.
        * It's not a negative value -- which values are often used
          to indicate failure, by contrast to meaningful yes/no values.

Well, in some situations, such as the trial of Socrates or Jesus or
here, Truth is failure whereas you seem to be a success by way of
lies: about Schildt, about your capabilities, about many things.
Perhaps Truth should be negative in order to show that in a world of
lies such as you propagate, it is on the side of the "losers".
He's an idiot.

**** you, asshole.
So far as we can tell, he's become convinced of two things:

1.  He's really good at programming, and will show us all how C should be
used.

Hey, you're getting warmer. Yes, dear heart, I am really, really,
really good at programming, and I shall show you how to use C even
though I don't really know dick about C. You see, deep knowledge of C
corrupts the soul.

2.  Everything C does is wrong.

Not everything.
Therefore, he goes out of his way to avoid using C in a way consistent with
the language's design.  Which is interesting, because even if a language's
design is utter pants, carefully violating that design is one of the few
things you can do that genuinely makes things worse.

That's false.

Barney Stroustrup buttfucked C
And hee hee hee
He created C plus plus
And gave it to the rest of us

C teaches adjustment to a reified administered world. I don't have to
adjust.
Do you honestly think that someone who named variables "ptrIndex0" through
"ptrIndex3" is concerned with "clear to the reader"?

Yes. This is because indexes are used in a certain sequence and have
limited useful life inside the module that declares them, and, for
this reason, are often used for different purposes. Therefore it makes
the most sense, for indexes and only indexes are misleading if labeled
by the name of only one of their uses.
For that matter, note that he's missed the point anyway; he's already
relying on the standard boolean behavior.  What he should do, of course,
is:

        int truth_values_internal = { TRUTH, FALSITY, TRUTH };
        int *truth_of = truth_values_internal[1];

Thus,
        truth_of[TRUTH] == TRUTH
        truth_of[FALSITY] == FALSITY
        truth_of[1 == 1] == TRUTH
appears to have been composed solely for its confusion factor, since as
a boolean expression it's equivalent to
      (*ptrTarget && *ptrMaster && (*ptrMaster == *ptrTarget))
or the even simpler
      (*ptrTarget && (*ptrTarget == *ptrMaster))

Oh, come on.  It's not confusion factor.  It's that when you first learn
about the ternary operator, it's SO COOL.  

Yes, asshole. I learned about lazy evaluation in a UNIVERSITY
CLASSROOM and a class in Logic taught by a brilliant faculty member,
who later asked me to teach that same class. I took this class two
years before I had access to a computer. Had you been man enough to
take Logic as you should have if you wanted to be a programmer, and
had you used as is standard Copi's introduction to logic, and had you
done the work and paid attention instead of running home to Mommy with
ADHD, you would have learned how to make truth tables, and then
simplify them using lazy evaluation.

But you didn't. You were too busy playing computer games.

The fact is that great programmers think that important ideas are
cool, and only important ideas. They don't think that "sequence
points" are cool.
Also, remember, he doesn't want
to rely on the standard boolean operators, because by definition, since
they're part of C, their designs are of course completely wrong.  So he

That might be your logic. But I've been C-aware since the 1970s when
you were probably masturbating to the girl in Scooby Doo, and while it
was better than Cobol, it was not as good or Java, or Visual Basic.
doesn't rely on &&, because if you use &&, that's a pointless premature
optimization because the short-circuiting rule is a stupid optimization that
shows that the language designers were incompetent and the standard has been
driven by autistic twerps.

Got that shit right, asshole.
Read his psychotic-break rants about the meaning of the word "clear" sometime
before you suggest that he would try to write for clarity.  In short, I don't
think it's on the table.

Those "rants" were based in fact on the following sources:

(1) The definition of clarity in the Oxford English Dictionary,
compact edition

(2) The theory of knowledge

Peter's attack on Schildt called Schildt clear. But "clarity" is being
conducive to understanding, and understanding is justified belief in
that which is true. The fact is that most programmers, including
programmers who like Seebach claim they can write, are very, very poor
at language skills, and when they write rely upon urban legends and
shibboleths to get their point across. The fact is that since
corporate life depends on obscuring the real conditions of life from
corporate people, the only metric of "clarity" is a formal adherence
to grammar and orthography which has nothing to do with truth.
 
S

spinoza1111

I'm particularly prone to trivial and obvious mistakes, while I tend

"You, Williamson, I'm talking to you, shithead."
to get other stuff right more easily.  

This is conveniently uncheckable.

As I investigate the large number of facts you have in some cases
inappropriately and to your employers' disadvantage revealed about
yourself I find that at the age of forty, Peter, you've not
accomplished a fraction of what I'd accomplished by the time I was
your age. You've basically, like most of us, been able to get and keep
jobs, but as I've said, programming jobs today are carefully designed
to make you a dime a dozen, since Wall Street needs companies like
your employers to be able to shed programmers quickly.
This is apparently stereotypical
for severe ADHD.  

This is false. In fact, in ADHD, the sufferer is good at small, short
and definable tasks such as writing a strlen without errors.

Larry Ellison, currently the CEO of Oracle, had ADHD and received
neither a proper diagnosis nor treatment, nor even a name for his
disease in the classist and racist Chicago public school system of the
1960s. This was compounded by the collapse of his family owing to the
beginnings of the deindustrialization of Chicago and the betrayal of
its lower middle class.

Nonetheless, Ellison succeeded beyond his expectations in an infamous
Fortran class at the University of Illinois which many of my friends
took, BECAUSE he found that he could (like me) get the first problem,
which was making change in code for a ten dollar bill. In my class
which was designed like the U of I, I wrote the code in Northwestern's
library on a cold January night, and it had one bug, for I decided to
load the (IBM 1401 machine code in my case, not Fortran) on top of
where the professor had independently chosen to store his loader for
our code. After we fixed this my code ran perfectly.

Crazy men like me use sources, so my source for my facts about Larry
Ellison is
Softwar: An Intimate Portrait of Larry Ellison and Oracle by Matthew
Symonds and Larry Ellison.

In fact, people who write big programs end to end, removing the bugs
steadily albeit in some cases slowly depending on other duties, also
tend not to make silly mistakes (apart from typos based on poor
language design) in one line and small programs. Nor do they, after
making each such mistake, hasten to tell people (without being able to
give EXAMPLES) that they do big, wonderful things offstage or out
back; if they do so consistently, sensible men, even crazy homeless
men with the sense of King Lear or Tom o' Bedlam, tend to laugh at
them.

Really great programmers are also unafraid of revisiting simple
programs to find unexpected depths for the same reason great
mathematicians like integer number theory and, in some cases, such as
John Horton Conway, recreational math.

I conclude that you're incompetent in the large and in the small,
Peter, and that you've learned to claim ADHD (which claim is a call
for a charity you do not extend others when you call them "morons",
asshole), and today, you come here to get your awful code in "pseudo"
repaired by unwitting slaves.
As a result, I'm quite likely to, say, have fencepost
errors in string processing, or try to compile something only to discover
that I changed the name for a variable halfway through an implementation.
On the other hand, I added thread safety to pseudo, using a part of the
POSIX thread API I'd probably seen maybe once before, and (once I got past
the obvious and trivial errors) the actual thread safety design worked
flawlessly on the first try.

And so Peter, a vain and foolish man, raises the cry,
But my important code works flawlessly on the first try.
He's too much the Fool to see he's deceived:
For a good Programmer, when such a gift, he's received
Will not slaughter a bullock, nor quaff of the grape
But get to work in order his own Vanity to Rape:
Yea, he shall desire if good and if competent
The clothes of his Goddess, his pride, to remove in an instant
By designing more tests to show that he's wrong
So that real satisfaction will last and be long.


I'm willing to wager that we will never see these versions of Peter
that work, after he's stolen the work of people like Ersek Laszlo in
pointing out Peter's failure to get a test for an index's usability.
Despite his claim that his employer (client?) Wind River Systems will
let him release the code for free, we'll get the versions with the
bugs left in in return for versions with Laszlo's unpaid slave labor,
which Wind River will make proprietary.

I have long noticed that this is how Open Source works. Content is
stolen from people in many cases in an environment of bullying, as in
Wikipedia. Jaron Lanier, in "You Are Not a Gadget" calls this "digital
Maoism".

"**** you, Dave. You know you got a big mouth. You make a close, this
whole place stinks with your farts for a week - how much you just
ingested. Oh, what a big man you are! 'Hey, let me buy you a pack of
gum. I'll show you how to chew it.' Whoof! Your pal closes, and all
that comes out of your mouth is bile. Ooh, how fucked-up you are! "

- David Mamet, Glengarry Glen Ross
The hard part is easy; the easy part is hard.  This pattern has been with me
all my life.

Oh, **** off.
 
S

spinoza1111

I'm particularly prone to trivial and obvious mistakes, while I tend
to get other stuff right more easily.  This is apparently stereotypical
for severe ADHD.  As a result, I'm quite likely to, say, have fencepost
errors in string processing, or try to compile something only to discover
that I changed the name for a variable halfway through an implementation.
On the other hand, I added thread safety to pseudo, using a part of the
POSIX thread API I'd probably seen maybe once before, and (once I got past
the obvious and trivial errors) the actual thread safety design worked
flawlessly on the first try.

The hard part is easy; the easy part is hard.  This pattern has been with me
all my life.

-s

The following code, from Peter's "pseudo root simulator", is submitted
to this discussion group as evidence that he is incompetent, and is
unethically using this newsgroup to get debugging assistance for code
that he will then claim as his own. And because he is incompetent, he
has defamed Herb Schildt and myself in a legally actionable sense.

If I am wrong I will apologize for basing this charge on this evidence
but will not withdraw the charge, since other evidence exists. I am
the best programmer in this newsgroup, but by no means the best C
programmer, so I may have missed something.

Sources: the thread starts at http://groups.google.com.hk/group/comp.lang.c/msg/54dfb34c84373f26?hl=en
("A hunk of not-very-portable code I've written"). This post
references code in github at http://github.com/wrpseudo/pseudo/blob/master/pseudo.c
line 664 at this moment in time.


int
pseudo_server_response(pseudo_msg_t *msg, const char *tag) {
switch (msg->type) {
case PSEUDO_MSG_PING:
msg->result = RESULT_SUCCEED;
if (opt_l)
pdb_log_msg(SEVERITY_INFO, msg, tag, "ping");
return 0;
break;
case PSEUDO_MSG_OP:
return pseudo_op(msg, tag);
break;
case PSEUDO_MSG_ACK:
case PSEUDO_MSG_NAK:
default:
pdb_log_msg(SEVERITY_WARN, msg, tag, "invalid message");
return 1;
}
}

OK. My understanding of C is that for ACK and NAK, the code will fall
through to "invalid message", and this is not intended. Good style
alone demands a break after the ack and nak cases. The same sort of
error is repeated above the code at github above this code, therefore
this isn't "ADHD". It is, as far as I can see, incompetence which
taken together to an out of order and in the same code, means that
Seebach has not mastered the C programming language as of this year,
and did not know C when he published "C: The Complete Reference", his
defamatory attack on Herb Schildt.

I am making very serious charges involving legal liability to Peter or
myself, and possibly involving Wind River Systems, so due diligence is
essential.

First as to authorship: this is from Peter's readme for the pseudo
root simulator:

"My various coworkers, both engineering and management, made this
possible.
While I did most of the actual typing, this code has benefitted
greatly
from detailed code reviews, excellent reproducers for bugs, and the
consistent support of the whole group for the project. It's been a
great
deal of fun, and I'm pretty happy that we're finally ready to make it
available for other people to look at."

The claim that there were "detailed code reviews" appears to be a lie.
This use of case is a common bug but one that never is concealed in
testing and one that is typically found in code reviews. Furthermore,
Seebach's online conduct here in this ng demonstrates that in a code
review, he is probably disruptive and cannot function.

I believe that Peter, hopefully without authorization from Wind River
Systems, who is either a client or former employer or something else
in relation to him (the relation is not clear) is submitting
unacceptable code to this newsgroup for review by competent people in
a relationship of slave labor. As in the case of wikipedia editors,
who are like him masquerading as competent, he knows enough to
recognize competent people who can write such as myself, and he fears
these people because they may expose his scam. This is the reason for
his vicious attacks on me.

My "due diligence" was to reread the 2005 C99 standard PDF, since good
programmers, unlike Seebach, always put breaks in null cases so that
they can forget in part just how poorly the switch statement was
designed by Ritchie, or Pike, or Kernighan, or Kermit the Frog. This
means we're not always "up to speed" on the actual rules of C, which
are in some part, mistakes masquerading as rules.

The standard has an example of a fallthrough, but it may be that
Seebach believes that the logic doesn't fall through if there is no
code in the case. So, I tested this using Microsoft C++ .Net in C
mode:

switch(1)
{
case 1:
case 2:
default: printf("foo\n");
};

The above code printed foo.
 
M

Moi

I'm particularly prone to trivial and obvious mistakes, while I tend to
get other stuff right more easily. This is apparently stereotypical for
severe ADHD. As a result, I'm quite likely to, say, have fencepost
errors in string processing, or try to compile something only to

I think most of us do, actually.
First, you get the basics right (the "skeleton" of the algorithm/program)
, then you polish the corner cases and tackle the fencepost errors.
See for example Knuth's "never getting binary search right the first time"
musing.
discover that I changed the name for a variable halfway through an
implementation. On the other hand, I added thread safety to pseudo,
using a part of the POSIX thread API I'd probably seen maybe once
before, and (once I got past the obvious and trivial errors) the actual
thread safety design worked flawlessly on the first try.

The hard part is easy; the easy part is hard. This pattern has been
with me all my life.

Focussing on the hard part at first and leaving the trivialities
for the future is a good strategy, IMHO. Trivial things will show up.
For a two-loop problem (like strstr()) there are four possible corner-cases.
You could even enumerate them!

AvK
 
W

Willem

Moi wrote:
) I think most of us do, actually.
) First, you get the basics right (the "skeleton" of the algorithm/program)
) , then you polish the corner cases and tackle the fencepost errors.
) See for example Knuth's "never getting binary search right the first time"
) musing.

Some of the time I even don't bother figuring out which way a corner case
should fall; I just code it up one way, run a test against the corner case,
and then if it fails, I just flip the case. Easy-peasy.

Same with 'should this be greater than or smaller than ?' questions.
Run a test, if the order seems reversed, flip the comparison.


Of course, you have to know when to do this and when not (cue the story
about the idiot^Wprogrammer who, after a 99% test success, saw a test
failure report, where a complex expression did the opposite of what was
expected, and put a 'not' at the base of said expression, resulting in
that one test being passed.)


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
S

spinoza1111

"Dr Malcolm McLean" <[email protected]> ha scritto nel messaggio



A quick and nasty strstr should only take a minute or so to write.
/*
  quick and nasty strstr. Untested. Posted to comp.lang.c "as is"
without warrantry or guarantee of any kind, including implied
warrantry of merchanability or fitness for any particular purpose.
*/
char *mystrstr(char *str, char *sub)
{
 size_t i; /* If you think this is ugly, join the campaign for 64-bit
ints */
 while(*str)
 {
   for(i=0;str==sub && str;i++);
   if(!sub)
      return str;
   str++;
 }
 return 0;
}


char*  mystrstrr(char *str, char *sub)
{size_t     i;

 if(str==0||sub==0)
        return  0;
 while(*str)
   {for(i=0; str==sub && str!=0; ++i);
    if(sub==0)
       return str;
    str++;
   }
 return 0;

}

char*  mystrstrr(char *str, char *sub)
{  char  *p, *r;

   if(str==0||sub==0||*sub==0)
                return 0;
a: p=str; r=sub; goto  c;
b: ++p, ++r;
c: if(*r==0)  return str;
   if(*p==*r) goto     b;
   ++str;
   if(*str)   goto     a;
   return  0;}

the only bug is when str==""
but this below seems pass all tests

#include <stdio.h>
#define  R  return
#define  G  goto
#define  uns  unsigned

#define TRUTH -1
#define FALSITY 0
#define NULLITY 0

char*  strstrr(char *str, char *sub)
{  char  *p, *r, *v;

   v=str;
   if(sub==0||*sub==0||v==0||*v==0)
              R  0;
a: p=v; r=sub;G  c;
b: ++p, ++r;
c: if(*r== 0) R  v;
   if(*p==*r) G  b;
   ++v;
d: if(*v)     G  a;
   R  0;

}

char*  strstrrWithIndex(char* a, char*  b, uns*  i)
{char  *r;
 if(i==0)  R  0;
 r=strstrr(a,b);
 if(r==0)  {*i=-1;  R  0;}
 else      {*i=r-a; R  r;}

}

int main(void)
{
    char *ptrIndex1 = NULLITY;
    uns   intIndex1 = 0;
    printf("strstr Simplified\n\n");
    printf("Expect 0: %d\n", strstrr("", ""));
    printf("Expect 0: %d\n", strstrr("0123456789", ""));
    printf("Expect 0: %d\n", strstrr("", "0"));
    printf("Expect 0: %d\n", strstrr("Here", "There"));
    ptrIndex1 = strstrrWithIndex("There", "here", &intIndex1);
    printf("Expect 1: %d\n", intIndex1);
    ptrIndex1 = strstrrWithIndex("They seek him here",
                                "here",
                                &intIndex1);
    printf("Expect 14: %d\n", intIndex1);
    ptrIndex1 = strstrrWithIndex("They seek him there",
                                "here",
                                &intIndex1);
    printf("Expect 15: %d\n", intIndex1);
    ptrIndex1 = strstrrWithIndex
                ("The clc regs seek him everywhere",
                 "here",
                 &intIndex1);
    printf("Expect 28: %d\n", intIndex1);
    printf("Expect 'h': %c\n", *ptrIndex1);
    ptrIndex1 = strstrrWithIndex
                ("Is he in Heaven? Or in Hell?",
                 "?",
                 &intIndex1);
    printf("Expect 15: %d\n", intIndex1);
    printf("Expect '?': %c\n", *ptrIndex1);
    ptrIndex1 = strstrrWithIndex
                ("That damn'd elusive Spinoza won't tell!",
                 "Spinoza",
                 &intIndex1);
    printf("Expect 20: %d\n", intIndex1);
    printf("Expect 'p': %c\n", *(ptrIndex1+1));
    printf("Expect '0': %c\n", *strstrr("0123456789", "0"));
    printf("Expect '1': %c\n", *strstrr("0123456789", "1"));
    printf("Expect '0': %c\n", *strstrr("0123456789", "0"));
    printf("Expect '9': %c\n", *strstrr("0123456789", "9"));
    printf("Expect '5': %c\n", *strstrr("0123456789", "345") + 2);
    printf("Expect '8': %c\n", *strstrr("0123456789", "89"));
    ptrIndex1 = strstrrWithIndex("0123456789A89AB",
                                "89AB",
                                &intIndex1);
    printf("Expect 11: %d\n", intIndex1);
    return 0;



}
However it's a bit cryptic, particularly the for loop.
Whilst there's always the argument that as long as the interfaces are
nice, the code doesn't matter, I'd like to see a rather better job.
Then it  will return a match to the first character if sub is the
empty string. I don't know offhand whether this is allowed. I'd have
to check the standard for a real implementation intended to be shipped
to someone else.
Two hours isn't unreasonable for a production-quality strstr.


Do me the courtesy of a comment acknowledging your reuse of my test
suite if you found it useful.
 
S

spinoza1111

I think most of us do, actually.
First, you get the basics right (the "skeleton" of the algorithm/program)
, then you polish the corner cases and tackle the fencepost errors.
See for example Knuth's "never getting binary search right the first time"
musing.

The problem is that Seebach and Heathfield only apply this to
themselves and never to others, especially to people that anger them
by diverging from their pet prejudices or simply, in my case, being so
obviously more qualified and less corrupted by family and corporate
mollycoddling.
Focussing on the hard part at first and leaving the trivialities
for the future is a good strategy, IMHO. Trivial things will show up.
For a two-loop problem (like strstr()) there are four possible corner-cases.
You could even enumerate them!

This discussion is absurd. In his pseudo chroot, Peter worked on the
code for two months, yet it has case labels with no breaks and out of
order logical Ands. I believe he's here to get fixes to his
incompetent code for free so as to claim he's written something.
 
S

spinoza1111

The following code, from Peter's "pseudo root simulator", is submitted
to this discussion group as evidence that he is incompetent, and is
unethically using this newsgroup to get debugging assistance for code
that he will then claim as his own. And because he is incompetent, he
has defamed Herb Schildt and myself in a legally actionable sense.

If I am wrong I will apologize for basing this charge on this evidence
but will not withdraw the charge, since other evidence exists. I am
the best programmer in this newsgroup, but by no means the best C
programmer, so I may have missed something.

Sources: the thread starts athttp://groups.google.com.hk/group/comp.lang.c/msg/54dfb34c84373f26?hl=en
("A hunk of not-very-portable code I've written"). This post
references code in github athttp://github.com/wrpseudo/pseudo/blob/master/pseudo.c
line 664 at this moment in time.

int
pseudo_server_response(pseudo_msg_t *msg, const char *tag) {
        switch (msg->type) {
        case PSEUDO_MSG_PING:
                msg->result = RESULT_SUCCEED;
                if (opt_l)
                        pdb_log_msg(SEVERITY_INFO, msg, tag, "ping");
                return 0;
                break;
        case PSEUDO_MSG_OP:
                return pseudo_op(msg, tag);
                break;
        case PSEUDO_MSG_ACK:
        case PSEUDO_MSG_NAK:
        default:
                pdb_log_msg(SEVERITY_WARN, msg, tag, "invalid message");
                return 1;
        }

}

OK. My understanding of C is that for ACK and NAK, the code will fall
through to "invalid message", and this is not intended. Good style
alone demands a break after the ack and nak cases. The same sort of
error is repeated above the code at github above this code, therefore
this isn't "ADHD". It is, as far as I can see, incompetence which
taken together to an out of order and in the same code, means that
Seebach has not mastered the C programming language as of this year,
and did not know C when he published "C: The Complete Reference", his
defamatory attack on Herb Schildt.

I am making very serious charges involving legal liability to Peter or
myself, and possibly involving Wind River Systems, so due diligence is
essential.

First as to authorship: this is from Peter's readme for the pseudo
root simulator:

"My various coworkers, both engineering and management, made this
possible.
While I did most of the actual typing, this code has benefitted
greatly
from detailed code reviews, excellent reproducers for bugs, and the
consistent support of the whole group for the project.  It's been a
great
deal of fun, and I'm pretty happy that we're finally ready to make it
available for other people to look at."

The claim that there were "detailed code reviews" appears to be a lie.
This use of case is a common bug but one that never is concealed in
testing and one that is typically found in code reviews. Furthermore,
Seebach's online conduct here in this ng demonstrates that in a code
review, he is probably disruptive and cannot function.

I believe that Peter, hopefully without authorization from Wind River
Systems, who is either a client or former employer or something else
in relation to him (the relation is not clear) is submitting
unacceptable code to this newsgroup for review by competent people in
a relationship of slave labor. As in the case of wikipedia editors,
who are like him masquerading as competent, he knows enough to
recognize competent people who can write such as myself, and he fears
these people because they may expose his scam. This is the reason for
his vicious attacks on me.

My "due diligence" was to reread the 2005 C99 standard PDF, since good
programmers, unlike Seebach, always put breaks in null cases so that
they can forget in part just how poorly the switch statement was
designed by Ritchie, or Pike, or Kernighan, or Kermit the Frog. This
means we're not always "up to speed" on the actual rules of C, which
are in some part, mistakes masquerading as rules.

The standard has an example of a fallthrough, but it may be that
Seebach believes that the logic doesn't fall through if there is no
code in the case. So, I tested this using Microsoft C++ .Net in C
mode:

        switch(1)
        {
        case 1:
        case 2:
        default: printf("foo\n");
        };

The above code printed foo.

In this particular case, it is possible that Seebach never got around
to deciding and coding what ack and nak should do. A nak sounds like
an error in which you should wait until a maximum. But I do not
understand how an ack could be an error. "hey, I'm here! **** you,
you're an error! Mom!"

I am waiting for him to lie about this situation.

Furthermore, there is a command processor switch statement directly
above the code I'm discussing: it seems to want to process pseudo root
commands. Many commands seem "stubbed", yet strangely, not with a
break to get out of the switch statement. As a result, a mkdir will do
a mknod.

[Parenthetically, one wonders what a pseudo root is for. OK, you want
to make directories and stuff without bothering Linux or being in
protected mode? Or maybe you are a programmer only in virtual reality
and you like simulating what the big boys do? Hell, I love writing
simulators myself. But isn't Linux really, really good at making
directories in reality? Are we reinventing the wheel? Don't get me
wrong, I might be The Greatest Programmer in the World but I know dick
about Linux.]

The code, which is too large to include, starts at line 456 at
http://github.com/wrpseudo/pseudo/blob/master/pseudo.c.

I do not understand why the operations he has supported at this time
have a break but the unsupported operations do not. The apparent error
is consistent, and Peter has told us that he gets trivial matters
wrong.

However, programming isn't high level conceptual handwaving. When I
wrote the compiler for "Build Your Own .Net Language and Compiler" I
wrote all 26K lines by myself. Real programmers don't like
collaboration save for pair programming.

I believe that if I'd submitted this code, Peter would have been on me
like a fly on shit, claiming that I am both incompetent and insane,
once others noticed the error. I believe he's no better than somebody
coming here for homework completion, and possibly worse.

Here's another troubling error, in the function containing the
troubling case statements. A "pseudo_msg_t" named db_header is
declared with no initialization, and then assigned using this code:

if (found_ino && (prefer_ino || !found_path)) {
db_header = by_ino;
} else if (found_path) {
db_header = by_path;
}

Hmm...if you have found an ino and you prefer it, or if no path was
found, then you set db_header to by_ino. Otherwise if you have a path
you use that.

[Oh shit, I hope I know how else and if and stuff work. Yup I think
that the above if has sprung a leak.]

OK, perhaps this is an error which "can't happen". However, competent
programmers handle many (but not all) things which can't happen. I
worry in strstr about a null target. I don't worry AT THIS TIME (after
two hours work) about a target or a master that is NULL.

But...Peter says this code has been worked on by him for two months.
It is to me unwise to not put in error checking early so as to "eat
your own dog food" when errors occur.

Nope, I think the code is globally incompetent and was brought here to
be beat into shape by slaves for whom Peter, and Wind River Systems,
have naught but contempt, as indicated by his treatment of dissident,
uppity slaves like me.

Is this what Open Source has come to?

I would have given db_header an initial null value. OK, is this
attention disorder in action, which conceals A Heartbreaking Work of
Staggering Genius? Is this the first pseudo root thingie ever written
for linux, and did many a man try and fail to solve this problem?

Oh, here is a switch statement at line 88. It uses GNU getopt with a
smartass remark to the effect that GNU did it wrong; Peter, at an
early age, seems to have regarded himself as a Superior and Gifted
person who Just Knew that you study calculus before trig, and that you
don't have to take computer science to be a Genius Programmer. Perhaps
big hairy guys that rode motorcycles and looked like Schildt made fun
of him and give him noogies and swirlies.

OK, all cases have a break and all do something. Cool.

Oh crumbs, no default handler, with an error message, perhaps snarkily
blaming the error on GNU.

Two months work? Wow.
 
S

spinoza1111

And once again, he's succeeded. Well done for falling for it, jerk.

Excuse me. I am not here to provoke anyone. Nor am I here, as I
suspect Peter Seebach is, to get really bad code (Peter's pseudo root
simulator) fixed by unwitting slaves.

I just thought it would be fun to plan, pre-document and write strstr
without using string.h. I did so, composing a test suite which at this
writing is being used by others who don't care that they are stealing
intellectual production while not supporting a fellow human being
subject to absurd and unconscionable treatment. I again sparked an
interesting, on topic and useful thread in the best tradition of clc.

But unlike a corporate dweeb who sucks up to the money and shits on
people when he thinks he can get away with it, I am not afraid of a
fight. So don't **** with me.
 
S

spinoza1111

Ben is a knowledgeable contributor to this newsgroup, and most polite
with it. You would do well to try to emulate him rather than insult him.

I agree with Richard Heathfield. Ben is one of the best and most
analytical minds here and he has helped me spot errors in my code.
 
S

spinoza1111

#include <stdlib.h>
Ben Bacarisse tested this code for finding aax in aaax and it failed.

I spent about ten minutes to discover that at the point where I need
to note the "character handle" address in the "master" string, I noted
it in the TARGET string. Oh gee, I am adhd mommie! But I'm rilly
great!

Seriously, that's why the code was submitted, to find and fix errors.
Please note that Seebach does not respond to error reports quickly or
at all, whereas a real programmer treats them as a challenge to fix
the error ... FAST. And, we're talking two months to mess up two case
statements. I still maintain that he's here for fixes and not to
participate in collective debugging, and I say this to avoid tu quoque
arguments.

I do not claim that this strstr is bug free. That awaits my finding
time to compose a correctness proof in natural language, based on
recursion on the length of the string in all probability.

Thanks again to Ben
Who finds so many errors
When I get mail from him
I am filled with nameless terrors
For he finds so much stuff
Which shows my code is a draft that is rough.

#include <stdio.h>

// ***************************************************************
// * *
// * strstr *
// * *
// * This function (strstr) finds a string, probably as fast as *
// * possible without extra memory usage over and above brute *
// * force. *
// * *
// * In searching a Nul terminated string for a substring, there *
// * are logically three possibilities in a left to right *
// * traversal of the master string that (1) looks for the *
// * first character of the target and then (2) matches all the *
// * remaining characters: *
// * *
// * * (Erroneous): on the failure of a partial match, *
// * restart at the first nonmatching character. This is *
// * fast but wrong, since the matching string may *
// * overlap the partial match. *
// * *
// * * (Too slow): on the failure of a partial match, start*
// * one past the first character (of the partial match) *
// * *
// * * (Just right): while matching characters, note the *
// * leftmost character in the searched string, to the *
// * right of the first matched character, that matches *
// * both that character and, of course, the first *
// * character of the target. *
// * *
// * C H A N G E R E C O R D --------------------------------- *
// * DATE PROGRAMMER DESCRIPTION OF CHANGE *
// * -------- ---------- --------------------------------- *
// * 03 18 10 Nilges Version 1.0 *
// * *
// * 03 19 10 Nilges Version 1.1 *
// * *
// * 1. Incorporates Pete's suggestion*
// * that a null target string is *
// * always found at the start of *
// * the master string. *
// * *
// * 2. Results display enhanced *
// * *
// * 03 19 10 Nilges Version 1.11: bug: ptrMaster was *
// * incorrectly set one past the *
// * ptrHandle *
// * *
// * 03 20 10 Nilges Version 1.12 *
// * *
// * 1. Bug (reported by BB): *
// * assignment used in place of *
// * equality test *
// * *
// * 2. Bug: incorrect test for noting *
// * char handle goes all the way *
// * back to start of string *
// * *
// * 03 21 10 Nilges Version 1.13 *
// * *
// * 1. Boolean statement simplified *
// * per Morris Keesan. *
// * *
// * 2. Bug found by Ben Bacarisse: *
// * statement that records char *\
// * handle set it to target and not*
// * master. *
// * *
// * ----------------------------------------------------------- *
// * *
// * To find a string, oh Muse! I sing, inside another String! *
// * Alternatives to me come in Three, ah, that's the thing: *
// * For the one thing for which the Wise must watch is mayhap, *
// * Partial occurences that most melancholy, overlap. *
// * The first is base, mechanical, low, and tragicomical: *
// * It's to restart from the previous beginning plus but One *
// * Oh what Mayhem to true Programming is thereby, done! *
// * But the job it will do, as did Hercules, *
// * His Labors for the Goddess cruel in Seneca's tragedies: *
// * Arduously and ignobly like unto the meanest Hind *
// * That knoweth not his Elbow from his Behind. *
// * The second is worse, a boner, a solecism, and a Seebach: *
// * The second restarts at the character that doth match! *
// * Oh muse! Such hellish Sights before me yawn: *
// * But be assur'd, 'tis darkest just before the Dawn. *
// * Shout for Victory, oh Thrace, and smite the Harp, and Grin: *
// * For lo, we start at the leftmost "handle" of the string *
// * When it occureth in *
// * The tragic partial match that hath failed us. *
// * If no such handle exists, then we can restart *
// * At the point of match failure: no, 'tis not a brain fart. *
// * Now we spy our magic bus: *
// * For this is the best Al Gore ithm *
// * That we can hope for in C, a language without Rhyme, or *
// * for that matter, Oh Muse! rhythm. *
// * *
// ***************************************************************

#define TRUTH -1
#define FALSITY 0
#define NULLITY 0

char * strstrWithIndex(char *strMaster,
char *strTarget,
int *ptrIndex)
{
char *ptrMaster = NULLITY;
char *ptrTarget = NULLITY;
char *ptrHandle = NULLITY;
char *ptrMasterStart = NULLITY;
int booFound = FALSITY;
*ptrIndex = 0; // Rel. 1.1
if (!*strTarget) return strMaster; // Rel. 1.1
if (!*strMaster) return 0; // Rel. 1.1
for (ptrMaster = strMaster; *ptrMaster;)
{
for (;
*ptrMaster && *ptrMaster != *strTarget;
ptrMaster++);
ptrTarget = strTarget;
*ptrIndex = ptrMaster - strMaster;
ptrHandle = 0;
ptrMasterStart = ptrMaster;
for (;
*ptrTarget
?
(*ptrMaster
?
*ptrMaster==*ptrTarget
:
FALSITY)
:
(booFound = TRUTH, FALSITY);
ptrMaster++, ptrTarget++)
{
if (ptrHandle == 0 // Rel 1.12
&&
ptrMaster > ptrMasterStart
&&
*ptrMaster == *strTarget)
ptrHandle = ptrMaster; // Rel. 1.13
}
if (booFound) return strMaster + *ptrIndex;
if (ptrHandle) ptrMaster = ptrHandle; // Rel. 1.11 bug fix
}
*ptrIndex = 0;
return 0;
}

char * strstr(char *strMaster, char *strTarget)
{
int ptrIndex = 0;
return strstrWithIndex(strMaster, strTarget, &ptrIndex);
}

int main(void)
{
char *ptrIndex1 = NULLITY;
int intIndex1 = 0;
printf("strstr Version 1.13\n\n");
printf("Expect 'aax': %s\n",
strstrWithIndex("aaax", "aax", &intIndex1));
printf("Expect 1: %d\n", intIndex1);
printf("Expect 0: %x\n", *strstr("", ""));
printf("Expect '0': '%c'\n", *strstr("0123456789", ""));
printf("Expect 0: %d\n", strstr("", "0"));
printf("Expect 0: %d\n", strstr("Here", "There"));
ptrIndex1 = strstrWithIndex("There", "here", &intIndex1);
printf("Expect 1: %d\n", intIndex1);
ptrIndex1 = strstrWithIndex("They seek him here",
"here",
&intIndex1);
printf("Expect 14: %d\n", intIndex1);
ptrIndex1 = strstrWithIndex("They seek him there",
"here",
&intIndex1);
printf("Expect 15: %d\n", intIndex1);
ptrIndex1 = strstrWithIndex
("The clc regs seek him everywhere",
"here",
&intIndex1);
printf("Expect 28: %d\n", intIndex1);
printf("Expect 'h': '%c'\n", *ptrIndex1);
ptrIndex1 = strstrWithIndex
("Is he in Heaven? Or in Hell?",
"?",
&intIndex1);
printf("Expect 15: %d\n", intIndex1);
printf("Expect '?': '%c'\n", *ptrIndex1);
ptrIndex1 = strstrWithIndex
("That damn'd elusive Spinoza won't tell!",
"Spinoza",
&intIndex1);
printf("Expect 20: %d\n", intIndex1);
printf("Expect 'p': '%c'\n", *(ptrIndex1+1));
printf("Expect '0': '%c'\n", *strstr("0123456789", "0"));
printf("Expect '1': '%c'\n", *strstr("0123456789", "1"));
printf("Expect '0': '%c'\n", *strstr("0123456789", "0"));
printf("Expect '9': '%c'\n", *strstr("0123456789", "9"));
printf("Expect '5': '%c'\n",
*strstr("0123456789", "345") + 2);
printf("Expect '8': '%c'\n", *strstr("0123456789", "89"));
ptrIndex1 = strstrWithIndex("0123456789A89AB",
"89AB",
&intIndex1);
printf("Expect 11: %d\n", intIndex1);
return 0;
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,022
Latest member
MaybelleMa

Latest Threads

Top