Implementing strstr

S

spinoza1111

[ snip ]

There are any number of ways a person might know the assignments in
a first-year CS class without ever having taken one.  Do I really need
to list them?

I find it amusing, by the way, that even though Seebs has never
taken a CS course he on many occasions produces paragraphs that
I could almost have written myself for inclusion in something to
be distributed as part of such a course -- the academic party
line about choosing variable names well, for example, or not
optimizing before you know you need to.  I guess it *could*
be coincidence ....

It's talking the talk, but he cannot walk the walk. This is evident in
the code he's submitted here: an off by one one line strlen, a string
replace program which didn't work that he was proud of, and in his
queue.c program, case statements falling through to error on non-error
cases.

He is in fact a published writer who writes "clearly" both in the
sense that he admits Schildt writes, and possibly in the sense that he
knows what he's talking about when he writes about scripts.

But he cannot claim to base his claims on programming on other than
tertiary and some secondary sources IF the best writers on programming
are real programmers, like Knuth.

And this is fine, save for his utter dishonesty and uncollegiality.
Which in my mind would make him at best a rather closely supervised
academic gofer in your case. And if you hire him, watch your back.
 
S

spinoza1111

For suitable definitions of "understand", I would claim.  At a
previous place of employment I developed some skill at fixing
bugs in code I understood just well enough to figure out where it
was going wrong.  Not that I'm claiming that ignorance is good,
exactly, only that if complete understanding is not feasible,
it is often useful to be able to proceed from partial understanding.

Indeed, it is often in corporate programming necessary to do this, but
this is, I claim, part of the problem. And in Dweebach's case, it
gives him no standing to criticize Schildt.

Contrary to the mythos, it is possible to "understand" large systems
by way of separation of concerns. But, this full understanding
increases the control of real stakeholders, including low level
employees and customers, vis a vis top management, and in American
business this is a no-no.

Which isn't to say that many top managements "understand" their
systems. In fact, the case of Ken Lay at Enron and in the 2008 crash,
it became clear that the managers, by preventing others from getting
this understanding (and its concomitant control), had also blinded
themselves.

Bell Northern Research at Mountain View responded to Ottawa's layoff
of the SL/1 compiler team by hiring me and saddling me with the
responsibility of not only discovering but actually fixing bugs, as
well as creating new versions and creating a rational installer. I
struggled to understand "everything". But in the management playbook,
I should have whined and nagged for employees to work for me so that
they and I could go to Hooters, since our collective ignorance would
mean that no one person would be "indispensable".

Years later I got the job of making something reasonable out of a DNA
assembly system. I documented everything in sight, got it more or less
working, and when given an assistant installed a regime of extreme
pair programming. But because the former Navy man who'd invented the
system but didn't know software thought I was a homo, I was thanked
effusively and demoted to tech writer while still expected to manage.
I trained my assistant up to the point where he could take over, and
split for China.

Nonetheless, I still prefer end to end creation as opposed to sitting
around some office sending bugs on to Timbuctoo and back-stabbing.
 
S

spinoza1111

[ snip ]





[ snip ]




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.

I'm quoting this because while I haven't read it all carefully some
of it sounds like possibly-legitimate critique, and I'm curious about
what Seebs has to say about it.  (I'm guessing that he's still not
reading your posts directly.)
Is this what Open Source has come to?
I would have given db_header an initial null value.

Ah, but would you?  The bug I found in your code -- wasn't that
a matter of not always assigning an initial value to a variable?
Just sayin'.

Commodity fetishism generates this type of thinking. Yes, I've
forgotten to initialize variables...but after two months work? Not
hardly.

Don't presume to classify me with Dweebach. I am not a gadget.
 
S

spinoza1111

(Thanks for quoting this, I never see his garbage except when quoted.)


The most obvious:  Most of my college friends did CS.  I used to kibitz
and offer advice.  Furthermore, having read a number of books on C,
including their exercises, I have the luxury of knowing what kinds of
exercises they contain.

Yes, but did you do them? On time?
Basically, if I were teaching people who had about the cognitive skills
and study abilities I'd expect from first-year college students C, I'd
have expected them to be able to do something like that well before the
end of the first semester, and if a substantial fraction couldn't, I'd
think it reflected badly on me as an instructor.

Actually, even exercises in CS classes tend on the whole to be more
challenging than Korporate Kode.
Most of it's honestly pretty obvious if you do any programming and
think about it -- or if you read a lot of books on the topic of
software design and development.  Reading things like _The Practice
of Programming_, or the _Programming on Purpose_ series, will do a
lot towards covering the material that would otherwise have been
scattered in among the basic language syntax.

Also, I have to say, several friends have gone far above and beyond
in teaching me about programming (hi Mike!), to say nothing of the
excellent advice and handholding I got from comp.lang.c regulars back
in the late 80s and early 90s.  I think it's safe to say that people like
Chris Torek and Steve Summit did a lot to teach me about effective use
of C.

....in a world without grownups...like Peter Pan.
As to whether it's worked... I have published my latest project, and
I continue to push updates to the public git tree before running them
through the internal code review process, in the interests of leaving
a public record.

It seems to me that you over-rely on others to fix your bugs and then
take the credit, based on queue.c.
 
S

spinoza1111

It is intended, although I have since started consistently adding
        /* FALLTHROUGH */
comments to such cases.

Well hoo fucking ray: but it's bad style to /* FALLTHROUGH */, Alice
in Wonderland. It happens to be a basic violation of structured
programming rules, and it's rarely necessary. The resulting switch
cannot with fallthrough be recoded as if then else, and switch isn't
one of the Bohm Jacopini primitives.
The reason for this is that ACK and NAK are responses that are by
DEFINITION sent only by the server.  The client MUST NOT generate either
such message.  Therefore, they are an "invalid message", as is any
other message of an unknown type.

Then you should have indicated this, Alice, in the structure of the
code, by calling an error routine or using a macro, since there was no
reason to be unstructured. Your style is unprofessional and
amateurish.

Not when multiple cases are intentionally handled by the same code.

But I will go add the /* FALLTHROUGH */ comments to make it more
explicit.  I'd say "good catch" if it weren't so stunningly obvious
that Nilges hadn't read, say, the documentation provided with the
project which clearly indicates what ACK and NAK mean and when
they are valid.

I'd rather not read your "documentation". As it is, I decided to focus
on queue.c in the same superficial style in which you went through
Schildt. How does it feel, asshole?

Each separate module, after TWO MONTHS work, should be readable
standalone. Not by random silly comments by architectonally. If ACK
and NAK were invalid from the client, and that is client code, then
don't put cases in for them. It's misleading, and far worse than
anything you accuse Schildt.
 
S

spinoza1111

Very simple:  You cannot ACK or NAK without having been sent a request.
Requests are never sent to the client, therefore a message from the
client must never be an ACK or NAK.

So why are there cases for them in the first case?
Don't hold your breath.

Just my nose, Dweebach.
Apparently Nilges is not aware of the convention of using a switch statement
to express things analaguous to:
        else if (x == VALUE_ONE || x == VALUE_TWO || x == VALUE_THREE)

I'm quite aware of your convention of coding explicit cases for things
you never expect with fallthrough to an error. It seems designed to
mislead.

And you haven't answered the question. Why does a mkdir do a mknod?

You're NOT expressing things "analaguous to" (it's "analogous") to the
logical or above. Anyone who thinks that doesn't know C. This is
because there's usually no code associated with the Or statement
"cases" UNLESS they are in the form

x == VALUE_ONE ? ( <code>, TRUE) : FALSE

The only "analogy" is that switch like || is lazy, evaluating all
cases down to the first true case.

[Parenthetically, one wonders what a pseudo root is for.

Same thing as fakeroot -- to let you create things like package archives
or disk images which reflect specified ownership, permissions, or device
nodes, without requiring root privileges on the machine where you create
them.

If this was useful, it exists coded by someone competent.
That's because you don't understand the semantics of switch().

What ev er. I've written compilers for language with switch(). You
haven't.
Pretty much.


What error?  There is no possible error.  by_ino and by_path are not
pointers, they're objects.  They are initialized at the top of the
function.  If data of either type have been found, we copy the best
fit into db_header.

A competent programmer would know that under two circumstances, the
"data" DOESN'T HAVE to be be of "either" type. Either an external
error or a modification to the surrounding code would falsify this,
and as far as I can see you failed to plan for this.

The usage, later, is:

                if (found_ino || found_path) {
                        *msg = db_header;
                } else {
                        msg->result = RESULT_FAIL;
                }

Which is to say, IF we found either of them, we copy its data in, otherwise,
the operation has failed.

We're not talking about the later code. The upper code leaves
db_header with an undetermined value in the formal sense.

Good guess.


I see no reason to assign it a null value, when I am guaranteed that
I will always assign it one or another of two values, both of which
are necessarily initialized.

But: you don't.
No, there's at least two others.  There's fakeroot (which we used to
use) and fakeroot-ng.  Both are, for various reasons, unsuitable to
our purposes.


Yes.

        /* warning:  GNU getopt permutes arguments, which is just plain
         * wrong.  The + suppresses this annoying behavior, but may not
         * be compatible with sane option libraries.
         */

The issue here is as follows:

1.  GNU's implementation of getopt() defaults to reordering arguments,
    which violates both the POSIX spec and reasonable (IMHO, but also
    in the HO of many other perhaps better-qualified people) expectations.
2.  This program is necessarily run on systems where the system getopt()
    is GNU getopt().
3.  To suppress the undesired behavior, I use the GNU getopt() extension
    which removes this behavior.
4.  Because a future porter might migrate this code to a system wherein
    this extension doesn't exist (and isn't needed), I explain what
    extension I'm using and why I'm using it.

I stand by the comment and implementation choice at this time.

(Note that getopt() is a POSIX extension, not a standard C feature, so
this is only marginally topical; however, I think the general question of
what to comment on when different implementations respond to a spec
differently is worth talking about.)


There's no default handler because the function's spec is defined very
clearly to never produce values other than the option characters specified,
a question mark, or -1.  Since -1 was handled above, ? is the only other
possibility.  I suppose I should have a default: case for the possible
case where a new option is added to the option string but not to the switch
statement, but it hasn't yet come up.

After two months we would expect you to have one, Dweebach.

Great programmers anticipate even endogenous errors, meaning that they
code so that any statement that is not changed in a future release has
a high probability of still working when other statements are changed!
This means that you're not thorough enough in logical analysis or case
statement analysis or layout to be considered competent. You put in
silly and misleading cases for ack and nak when they are invalid and
you used non-structured fallthrough logic when you should have called,
in each case besides the default where the case was an error, a macro
or subroutine to call and report the error...perhaps with an addendum
as to the specific case such as "ack from client".

You seem to handle user and exogenous systems errors with minimal
competence, but as to creating a SUSTAINABLE program, one whose text
can be changed with a minimum of effort and research, you have failed
again, failing as you failed when you scanned for %s.

Go back to school.
 
S

spinoza1111

Me.  It's a stereotypical trait of ADHD, especially fairly extreme
ADHD.  Basically, if I'm not fully engaged, my mind starts wandering
fast -- and simple tasks aren't very engaging.

(Gag reflex) (Eye roll) (Crotch grab) (Tongue waggle)

You'd never get an entry level job with Mies van Der Rohe. God, he
said, is in the details. He'd fire you if you turned in a sloppy
drawing for a cornice in one of his buildings. He'd fire you for cause
if you told him that "but Mies, poor widdle me gots ADHD and you must
give me high level tasks so me isn't bored!"

We now know that you refuse to lay out a case statement properly. We
know that you REFUSE to apply what we have learned about structured
programming's power and elegance to a switch(). We know that you have
so little care about detail that simultaneously, in queue.c, you
copyright your code on behalf of Wind River and claim it's GNU public
license.

But you are, because white and middle class, a legend in your own mind
destined for higher things, I suppose.

It's **** or walk, Dweebach. You're almost forty, aren't you? I
searched for accomplishments from you beyond the Apress book about
scripting, yawn, and found fifth place in some contest. At your age,
I'd written compilers and the first version of a hydrostatic stability
program that is now in common use in oceangoing research. At your age,
I'd taught C at Princeton and assisted guess the **** who.

But I wouldn't be saying these howwible things to you save for one
reason, and one reason alone: I say them because you seem to me to be
a vicious backstabber who advanced his career by starting the Schildt
canard. Add to that your calling me "insane" and a "moron", the gloves
are off. The blood and glass was on the street long before I started
on you.
 
S

spinoza1111

spinoza1111  said:
In the replace() program of last month's flame festival, a little
program was trying to get out. Here it is: an implementation of strstr
including a call that returns the offset of the found substring. Two
hours including all comments and dedicatory ode, written for this
occasion.

If I were going to put as much effort into writing comments as you
appear to have done with this program, I would explicitly discuss
the function's parameters and return value -- i.e., I would say
how the return value depends on the function's inputs and also
describe any side effects [*].  

You don't appear to have done this, and while based on your
comments I infer that the function returns a pointer to the
first occurrence of *strTarget in *strMaster, I have no idea
what the third parameter is for, and I don't really know what the
function does if the "target" is not a substring of the "master".
I can make a guess about the latter based on the behavior of the
standard-library function with the same name, but that's what it
is -- a guess.

[*] The only case in which I would omit such discussion would be
when the names of the function and/or parameters are so descriptive
as to make discussion superfluous.  In that regard, I find the
names used in the man-page documentation of strstr ("needle" and
"haystack") more descriptive if less formal than your "target"
and "master".

Please don't credit me by name if you make changes based on the
above critique, or on the (half-hearted) one that follows the code.




#include <stdlib.h>
#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                       *
// *                                                             *
// * ----------------------------------------------------------- *
// *                                                             *
// * 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;
    int booFound = FALSITY;
    if (!*strMaster || !*strTarget) return 0;
    for (ptrMaster = strMaster; *ptrMaster;)
    {
        for (;
             *ptrMaster && *ptrMaster != *strTarget;
             ptrMaster++);
        ptrTarget = strTarget;
        *ptrIndex = ptrMaster - strMaster;
        ptrHandle = 0;
        for (;
             *ptrTarget
             ?
             (*ptrMaster
              ?
              (*ptrMaster==*ptrTarget ? TRUTH : FALSITY)
              :
              FALSITY)
             :
             (booFound = TRUTH, FALSITY);
             ptrMaster++, ptrTarget++)
        {
            if (ptrHandle = 0
                &&
                ptrMaster > strMaster
                &&
                *ptrMaster == *strTarget)
                ptrHandle = ptrTarget;
        }
        if (booFound) return strMaster + *ptrIndex;
        if (ptrHandle) ptrMaster = ptrHandle + 1;
    }
    *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 Simplified\n\n");
    printf("Expect 0: %d\n", strstr("", ""));
    printf("Expect 0: %d\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;
}

Still printing the output and asking the human to check it rather
than having the program check itself ....  

Yes, since any time you write checking code you are risking more bugs.
The final approval of a computer system cannot be the computer itself.
Instead, because computers were invented for both an evil purpose (in
order to slaughter the people of Hiroshima and Nagasaki by calculating
what would be needed at Alamogordo) and a good purpose (to ease the
burden of calculation on people), the good purpose would demand that
they not be left to run by themselves and check their own output.

It takes in fact seconds to read the output and approve it. I find
your comments offensive since I don't see this level of "regression
testing" anywhere else in this intellectual slum and looney bin, and I
suspect that you, like many academic and corporate females, are trying
to normalize deviance with sweet talk.

Well, now that I think about it, I suppose that's not as bad as
it might be, since it would be easy enough -- in my preferred
development environment anyway [*] -- to copy the expected output
into a text file, capture actual output in another text file,
and have the computer compare the two.

Get Dweebach to write you the script.
[*] For short C programs -- text-based tools under Linux.
 
S

spinoza1111

spinoza1111  said:
In the replace() program of last month's flame festival, a little
program was trying to get out. Here it is: an implementation of strstr
including a call that returns the offset of the found substring. Two
hours including all comments and dedicatory ode, written for this
occasion.

If I were going to put as much effort into writing comments as you
appear to have done with this program, I would explicitly discuss
the function's parameters and return value -- i.e., I would say
how the return value depends on the function's inputs and also
describe any side effects [*].  

I wuv it: you see some effort, so you suggest something less useful as
an outlet for my energies. No, dear heart, a thousand times no.

I teach poetry, based on the Norton Anthology and John Lennard's The
Poetry Handbook. I note in my classes that there ain't no such thing
as free verse. Instead, a poet like TS Eliot and Ginsberg uses old
forms, and new forms, in new ways instead of trying to meet the
requirements of a traditional form.

In so doing, the poet sets up certain expectations which he either
meets or disappoints in the reader's first reading of the poem. When
he disappoints them, this means something. For example, Lennard shows
how a poem starts out like a sonnet and contains fourteen lines: but
some lines are fragmentary like a bombed city, since the sonnet is
about a Holocaust victim in a time when Adorno said we can't write any
more goddamn poetry.

Here, the comment block sets up the expectation that Nilges has
written some code and is gonna tell us, overall, what the code does.
So I do. Next, some but by no means all programs in the old days (when
programmers were more literate than today) would often contain a quote
AFTER the intro and BEFORE the code, in the same relative position a
dedicatory quote appears in a book, such as Shakespeare's First Folio,
which contains some dedicatory material AFTER the title page and
BEFORE the first play (which is for some silly reason the last
complete play of Shakespeare, The Tempest).

The reader is then either amused (if civilized and urbane) or outraged
(if like many programmers) but goes on to find, yes, functions without
my usual custom, which is to set up a visual fence as a line comment,
followed by the function name, followed by a statement as to what it
does, and yes indeedy, side effects...although great programmers make
fewer side effects.

But here, no such comments exist because

(1) If the code is small, let it document itself

(2) I would like to give the aliterate programmer-reader a break after
having him eyeball the ode.
You don't appear to have done this, and while based on your
comments I infer that the function returns a pointer to the
first occurrence of *strTarget in *strMaster, I have no idea
what the third parameter is for, and I don't really know what the
function does if the "target" is not a substring of the "master".
I can make a guess about the latter based on the behavior of the
standard-library function with the same name, but that's what it
is -- a guess.
No competent programmer expects commenting to tell her what the code
does. And simply reading the code would show you that the ptrIndex
parameter is needed when we want to get the offset of the string
without an extra calculation. Had you troubled to read the code, which
we must as programmers do whether or not there are comments, you would
find that strstrWithIndex and strstr are in a polymorphic relation to
each other in OO terms.
[*] The only case in which I would omit such discussion would be
when the names of the function and/or parameters are so descriptive
as to make discussion superfluous.  In that regard, I find the
names used in the man-page documentation of strstr ("needle" and
"haystack") more descriptive if less formal than your "target"
and "master".

You've never taught English in China. It's offensive to people with
good English as a second language to use idioms in the cutesy way of
unix man pages.
Please don't credit me by name if you make changes based on the
above critique, or on the (half-hearted) one that follows the code.

I find this very offensive. But of course I won't.
#include <stdlib.h>
#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                       *
// *                                                             *
// * ----------------------------------------------------------- *
// *                                                             *
// * 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;
    int booFound = FALSITY;
    if (!*strMaster || !*strTarget) return 0;
    for (ptrMaster = strMaster; *ptrMaster;)
    {
        for (;
             *ptrMaster && *ptrMaster != *strTarget;
             ptrMaster++);
        ptrTarget = strTarget;
        *ptrIndex = ptrMaster - strMaster;
        ptrHandle = 0;
        for (;
             *ptrTarget
             ?
             (*ptrMaster
              ?
              (*ptrMaster==*ptrTarget ? TRUTH : FALSITY)
              :
              FALSITY)
             :
             (booFound = TRUTH, FALSITY);
             ptrMaster++, ptrTarget++)
        {
            if (ptrHandle = 0
                &&
                ptrMaster > strMaster
                &&
                *ptrMaster == *strTarget)
                ptrHandle = ptrTarget;
        }
        if (booFound) return strMaster + *ptrIndex;
        if (ptrHandle) ptrMaster = ptrHandle + 1;
    }
    *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 Simplified\n\n");
    printf("Expect 0: %d\n", strstr("", ""));
    printf("Expect 0: %d\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;
}

Still printing the output and asking the human to check it rather
than having the program check itself ....  

Well, now that I think about it, I suppose that's not as bad as
it might be, since it would be easy enough -- in my preferred
development environment anyway [*] -- to copy the expected output
into a text file, capture actual output in another text file,
and have the computer compare the two.

[*] For short C programs -- text-based tools under Linux.
 
S

spinoza1111

[ snip ]




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.

I am quite curious about whether in fact the fall-through (which as
far as I know will happen) is intentional or an error.

It was both, because Seebach (because he didn't study computer
science) has no committment to the Copernican revolution of structured
programming, and he thinks it's cute to fall through like Alice in the
Rabbit hole. Most competent instructors would lower his grade for
using this "feature".

My first published work on programming was written because on the IBM
mainframe in 1976 I was able only to use unstructured cobol and
assembler, but in these languages I found that programs with a
"structured flowchart" restricted to the Bohm/Jacopini primitives were
far more reliable than unstructured programs. I would have preferred
to use C at the time because it was structured therefore I have
nothing but the utmost contempt for programmers who think it's cute to
use fallthrough, especially when those clowns go around calling people
morons and insane, you dig me?

There are, are there not, TWO WAYS to support what used to be called
"open subroutines" in C: preprocessor macros and inline. Therefore, if
the "overhead" of subroutine calling an error handler is too much
(despite the fact that if an error has occured, "efficiency" is
usually not as important as handling the goddamn error), you have TWO
WAYS to call the error handler inside the error case, avoiding
fallthrough, which creates a new control structure, an unnecessary and
confusing control structure.
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.

[ snip ]
 
T

Tim Rentsch

Keith Thompson said:
Ben Bacarisse said:
I was thinking of this: Message-ID: <[email protected]>

I see, my argument was based on bit fields. I had forgotten about
that.

[...]
I am not sure I understand this last remark. Do you mean that no
conforming program can tell the difference between 2 and 1a? If so, I
agree, bit I think a programmer can tell the difference in that a
diagnostic is required for

struct s { _Bool b : 2; };

in the case of 1a.

<snip>

I forgot about bit fields. Yes, that is a difference between cases 1a
and 2. (Well, mostly. Implementations are allowed to produce extra
diagnostics whenever they like, so you can't *really* distinguish the
cases based on that, but you can if you assume that this particular
message is not a lie.)

Given 6.2.6.1p2:

Except for bit-fields, objects are composed of contiguous
sequences of one or more bytes, the number, order, and
encoding of which are either explicitly specified or
implementation-defined.

doesn't it seem like the width of a _Bool must be derivable from
the documentation specifying implementation-defined behavior? I
would think that "the encoding" would have to say which bits
correspond to value bits (or at least which bit settings correspond
to which values, but that still gets us there). Is there anything
wrong with this reasoning?
 
K

Keith Thompson

Tim Rentsch said:
Given 6.2.6.1p2:

Except for bit-fields, objects are composed of contiguous
sequences of one or more bytes, the number, order, and
encoding of which are either explicitly specified or
implementation-defined.

doesn't it seem like the width of a _Bool must be derivable from
the documentation specifying implementation-defined behavior? I
would think that "the encoding" would have to say which bits
correspond to value bits (or at least which bit settings correspond
to which values, but that still gets us there). Is there anything
wrong with this reasoning?

I think you're right.

The gcc documentation I referenced doesn't say anything about padding
vs. value bits for unsigned types. It seems to follow section 3
of Annex J, which begins:

A conforming implementation is required to document its choice of
behavior in each of the areas listed in this subclause. The
following are implementation-defined:
[...]

After some searching, I see that J.3 talks about type representations
in J.3.13, Architecture:

The number, order, and encoding of bytes in any object (when not
explicitly specified in this International Standard) (6.2.6.1).

The phrase "encoding of bytes", I believe, would cover the issue of
value vs. padding bits, though it could stand to be more explicit.

gcc's documentation seems to follow the sequence of J.3. The
corresponding section says:

* `The number, order, and encoding of bytes in any object (when not
explicitly specified in this International Standard) (C99
6.2.6.1).'

Determined by ABI.

Since gcc supports multiple target architectures, defining this by
reference to another document seems reasonable.

On the other hand, I don't know whether ABIs generally define the
encoding of C's type _Bool <OT>and/or C++'s type bool</OT>.

If the ABI for any architecture that gcc supports doesn't
define the encoding of _Bool, then ...

GCC IS NON-CONFORMING! GCC IS NON-CONFORMING! WE'RE ALL DOOMED!!1!
 
S

spinoza1111

(Thanks for quoting this, I never see his garbage except when quoted.)


The most obvious:  Most of my college friends did CS.  I used to kibitz
and offer advice.  Furthermore, having read a number of books on C,
including their exercises, I have the luxury of knowing what kinds of
exercises they contain.

But you lack the ability, it seems, to actually solve those exercises
on your own. You were afraid to submit your fallthrough switch() case
blocks, snarky comments, uninitialized variables, off by one bugs, and
other Coding Horrors to a real instructor, and had you done so, and
had she criticized you, I'd imagine you'd then immediately challenge
her credentials as you challenged Schildt, because widdle Peter
doesn't want to take a look at himself.

Many of what you contemptuously refer to as "first year CS problems"
are far too challenging for the usual corporate dweeb to solve.
Corporate dweebs in the 1990s sued a Pace University instructor for
assigning them a problem involving "Avogadro's number".

My first programming assignment in graduate school was to write a
program to add and subtract polynomials which encased the match-merge
problem for sequential files where the key is the exponent, and, of
course, exponents can be missing at any rank when the constant == 0.
As it happened, in my experience, few of my fellow programmers ever
mastered the problem of matching two ordered lists, which is one
reason why today they more or less blindly use a data base join
operation.

My data base class involved learning the then very new relational
calculus of Date and years later I developed a Visual Basic simulation
of relational calculus for my own students. As it happens, many data
base programmers are incapable of forming wffs in relational calculus
and trust to luck and shibboleth to get actual SQL statements right.

An academic critique of software for securitized mortgages would
immediately ask if there is any provision for cycles such that a
derivative ultimately refers to itself but raising this issue produces
blank, gaping, drool-streaked stares in many MIS "shops".
Basically, if I were teaching people who had about the cognitive skills
and study abilities I'd expect from first-year college students C, I'd
have expected them to be able to do something like that well before the
end of the first semester, and if a substantial fraction couldn't, I'd
think it reflected badly on me as an instructor.

How dare you refer to an academically-confirmed authority when you
have not earned that authority? How would you know anything about the
demands of CS, first year or any other year, if you were, I'd wot,
simply too cowardly to take demanding college classes?
 
O

Old Wolf

// * Arduously and ignobly like unto the meanest Hind            *
// * That knoweth not his Elbow from his Behind.                 *
    printf("Expect '0': %c\n", *strstr("0123456789", "0"));
[etc.]

This is quite possibly the worst C code
I have ever had the misfortune of seeing.
 
S

spinoza1111

// * That knoweth not his Elbow from his Behind.                 *
    printf("Expect '0': %c\n", *strstr("0123456789", "0"));

[etc.]

This is quite possibly the worst C code
I have ever had the misfortune of seeing.

Take me somewhere east of Suez, where the best is like the worst
They're ain't no Ten Commandments and a man can raise a thirst

Seriously, in my direct experience, corporate programmers have over
time steadily exchanged their ass for their elbow, so it stands to
reason, son, that what you think the worst might be the best. Since
Korporate Koders have been regarded by top management since the 1980s
as a cost center and a eunuch class, window dressing, what they thing
"bad" is typically any code that reflects thought.

Everybody in Amerikkka wants to be the thin, "cool", white, blue-eyed
Korporate norm. The trouble is that as a life raft, the Korporate norm
is rather like the upside down one to which men clung after the
Titanic went down.

The code is so bad it's good, and vice-versa, since few people here
are qualified on the subject of literate programming.
 
C

Colonel Harlan Sanders

Korporate Koders have been regarded by top management since the 1980s
as a cost center and a eunuch class, window dressing
Everybody in Amerikkka wants to be the thin, "cool", white, blue-eyed
Korporate norm. The trouble is that as a life raft, the Korporate norm
is rather like the upside down one to which men clung after the
Titanic went down.

The code is so bad it's good, and vice-versa, since few people here
are qualified on the subject of literate programming.

Brought to you by the letter "K" for "Kook".
 
B

blmblm

(Thanks for quoting this, I never see his garbage except when quoted.)

Then you're missing lots and lots of nasty slurs .... I gather
that this doesn't bother you, though, and in any case it's probably
best that I not engage in "let's you and him fight". I'm trying to
only quote when I think there's a technical point that might be of
interest to other readers.

[ snip ]
 
B

blmblm

[ snip ]
Good guess.

Just for the record -- my "Ah, but would you?" was directed not at
you but at spinoza1111, who had said

"I would have given db_header an initial null value."

although evidence suggests that he does not always follow this
rule strictly in his own code.

[ snip ]
 
B

blmblm

[ snip ]
Commodity fetishism generates this type of thinking. Yes, I've
forgotten to initialize variables...but after two months work? Not
hardly.

Don't presume to classify me with Dweebach. I am not a gadget.

Oh, who said you were (a gadget)? As for classifying ....

We can only go by the code you post here (unless you have other
code that's publicly accessible), and in that code you *did* make
just the mistake you say you wouldn't have made. That was my point.

[ snip ]
 
B

blmblm

Yes, but did you do them? On time?

What does "on time" mean if the exercise are not being done in the
context of a formal course? and why would it matter in any case, if
speed of coding is not a virtue, as you keep telling us?

[ snip ]
 

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
474,109
Messages
2,570,671
Members
47,262
Latest member
EffiePju4

Latest Threads

Top