| Deutsch English Français Italiano |
|
<20240918024611.000002f3@yahoo.com> View for Bookmarking (what is this?) Look up another Usenet article |
Path: ...!3.eu.feeder.erje.net!feeder.erje.net!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: Michael S <already5chosen@yahoo.com>
Newsgroups: comp.lang.c
Subject: Re: Command line globber/tokenizer library for C?
Date: Wed, 18 Sep 2024 02:46:11 +0300
Organization: A noiseless patient Spider
Lines: 123
Message-ID: <20240918024611.000002f3@yahoo.com>
References: <lkbjchFebk9U1@mid.individual.net>
<vbsmlb$3o6n2$1@raubtier-asyl.eternal-september.org>
<vbsu1d$3p7pp$1@dont-email.me>
<vbtj88$1kpm$1@raubtier-asyl.eternal-september.org>
<vbujak$733i$3@dont-email.me>
<vbum9i$8h2o$1@dont-email.me>
<vbur72$99cr$1@dont-email.me>
<20240912181625.00006e68@yahoo.com>
<vbv4ra$b0hv$2@dont-email.me>
<vbv6r1$bhc9$1@raubtier-asyl.eternal-september.org>
<20240912223828.00005c10@yahoo.com>
<861q1nfsjz.fsf@linuxsc.com>
<20240915122211.000058b1@yahoo.com>
<vcd05n$q3mn$1@paganini.bofh.team>
MIME-Version: 1.0
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 7bit
Injection-Date: Wed, 18 Sep 2024 01:46:14 +0200 (CEST)
Injection-Info: dont-email.me; posting-host="b98425cb3c65aa1e430607c237ac1db3";
logging-data="3926364"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1988cxvrycjEEY/vxK1KdRq116HvFxgCGo="
Cancel-Lock: sha1:ZewXZrNTMJOJZWci5UZxJoyC8E8=
X-Newsreader: Claws Mail 4.1.1 (GTK 3.24.34; x86_64-w64-mingw32)
Bytes: 4937
On Tue, 17 Sep 2024 22:34:33 -0000 (UTC)
antispam@fricas.org wrote:
> Michael S <already5chosen@yahoo.com> wrote:
> > On Fri, 13 Sep 2024 09:05:04 -0700
> > Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:
> >
> >> Michael S <already5chosen@yahoo.com> writes:
> >>
> >> [..iterate over words in a string..]
> >>
> >> I couldn't resist writing some code along similar lines. The
> >> entry point is words_do(), which returns one on success and
> >> zero if the end of string is reached inside double quotes.
> >>
> >>
> >> typedef struct gopher_s *Gopher;
> >> struct gopher_s { void (*f)( Gopher, const char *, const char * );
> >> };
> >>
> >> static _Bool collect_word( const char *, const char *, _Bool,
> >> Gopher ); static _Bool is_space( char );
> >>
> >>
> >> _Bool
> >> words_do( const char *s, Gopher go ){
> >> char c = *s;
> >>
> >> return
> >> is_space(c) ? words_do( s+1, go )
> >> : c ? collect_word( s, s, 1, go )
> >> : /***************/ 1;
> >> }
> >>
> >> _Bool
> >> collect_word( const char *s, const char *r, _Bool w, Gopher go ){
> >> char c = *s;
> >>
> >> return
> >> c == 0 ? go->f( go, r, s ), w
> >> : is_space(c) && w ? go->f( go, r, s ), words_do( s, go )
> >> : /***************/ collect_word( s+1, r, w ^ c == '"', go );
> >> }
> >>
> >> _Bool
> >> is_space( char c ){
> >> return c == ' ' || c == '\t';
> >> }
> >
> >
>
> <snip>
>
> > Tested on godbolt.
> > gcc -O2 turns it into iteration starting from v.4.4
> > clang -O2 turns it into iteration starting from v.4.0
> > Latest icc still does not turn it into iteration at least along one
> > code paths.
> > Latest MSVC implements it as written, 100% recursion.
>
> I tested using gcc 12. AFAICS calls to 'go->f' in 'collect_word'
> are not tail calls and gcc 12 compiles them as normal call.
Naturally.
> The other calls are compiled to jumps. But call to 'collect_word'
> in 'words_do' is not "sibicall" and dependig in calling convention
> compiler may treat it narmal call. Two other calls, that is
> call to 'words_do' in 'words_do' and call to 'collect_word' in
> 'collect_word' are clearly tail self recursion and compiler
> should always optimize them to a jump.
>
"Should" or not, MSVC does not eliminate them.
The funny thing is that it does eliminate all four calls after I rewrote
the code in more boring style.
_Bool
words_do( const char *s, Gopher go ){
char c = *s;
#if 1
if (is_space(c))
return words_do( s+1, go );
if (c)
return collect_word( s, s, 1, go );
return 1;
#else
return
is_space(c) ? words_do( s+1, go ) :
c ? collect_word( s, s, 1, go ):
/***************/ 1;
#endif
}
static
_Bool
collect_word( const char *s, const char *r, _Bool w, Gopher go ){
char c = *s;
#if 1
if (c == 0) {
go->f( go, r, s );
return w;
}
if (is_space(c) && w) {
go->f( go, r, s );
return words_do( s, go );
}
return collect_word( s+1, r, w ^ c == '"', go );
#else
return
c == 0 ? go->f( go, r, s ), w :
is_space(c) && w ? go->f( go, r, s ), words_do( s, go ) :
/***************/ collect_word( s+1, r, w ^ c == '"', go );
#endif
}