git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH] cleans up builtin-mv

From
Junio C Hamano <junkio@cox.net>
Date
Aug 18, 2006, 19:33 UTC
Message-ID
<7vbqqh96v2.fsf@assigned-by-dhcp.cox.net>
In-Reply-To
<Pine.LNX.4.63.0608181137000.28360@wbgn013.biozentrum.uni-wuerzburg.de>
Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
Show 13 quoted lines
> What you cleverly did not mention: It was inside a
>
> 	if (!bad &&
> 		(length = strlen(source[i])) >= 0 &&
> 		!strncmp(destination[i], source[i], length) &&
> 		(destination[i][length] == 0 || destination[i][length] == '/'))
>
> construct. So, we assign the "length" variable only if we have to. And the 
> ">= 0" trick is a common one. I could have done
>
> 		!strncmp(destination[i], source[i], (length = strlen(source[i])))
>
> but even I find that ugly.
I usually side with you but on this I can't.
There are 2 ways to generate branch instructions in C.
 - compound statements specifically designed for expressing
   control structure: if () ... else ..., for (), while (),
   switch (), etc.
 - expressions using conditional operators or logical operators
   that short circuit: ... ? ... : ..., ... && ... || ...

The latter form may still be readable even with simple side effects inside its terms, but "(l = strlen(s)) >= 0" is done solely for the side effect, and its computed value does not have anything to do with the logical operation &&.

THIS IS UGLY. And do not want to live in a world where this ugliness is a "common one", as you put it.

And this avoiding one call to strlen(source[i]) is unnecessary even as an optimization -- you end up calling strlen() on it later in the code anyway, as David points out.

I think this part is far easier to read if you did it like this:
 
		length = strlen(source[i]);
		if (lstat(source[i], &st) < 0)
			bad = "bad source";
		else if (!strncmp(destination[i], source[i], length) &&
			 (destination[i][length] == 0 ||
			  destination[i][length] == '/'))
			bad = "can not move directory into itself";
		if (S_ISDIR(st.st_mode)) {
			...

Note that the above is an absolute minimum rewrite. Other things I noticed are:

 - source[i] and destination[i] are referenced all the time; the
   code would be easer to read if you had something like this
   upfront:
                /* Checking */
                for (i = 0; i < count; i++) {
                        const char *bad = NULL;
			const char *src = source[i];
                        const char *dst = destination[i];
                        int srclen = strlen(src);
                        int dstlen = strlen(dst);
   You might end up not using dstlen in some cases, but I think
   this would be far easier to read.  Micro-optimizing by saying
   "this is used only in this branch of this later if()
   statement but in that case it is always set in that branch of
   that earlier if() statement" makes unmaintainably confusing
   code.
 - I do not think you need "const char *dir, *dest_dir" inside
   the "source is directory" branch; I would just use src and dst
   consistently;
 - You muck with dest_dir by calling add_slash(dest_dir) but
   call prefix_path() with dst_len you computed earlier;
   prefix_path() may know what to do, but is this intended?
Previous: David RientjesNext: Johannes Schindelin
Message 7 of 8 in “cleans up builtin-mv”
  1. cleans up builtin-mvDavid Rientjes, Aug 18, 2006
  2. David RientjesAug 18, 2006
  3. Johannes SchindelinAug 18, 2006
  4. David RientjesAug 18, 2006
  5. Josef WeidendorferAug 18, 2006
  6. David RientjesAug 18, 2006
  7. Junio C HamanoAug 18, 2006
  8. Johannes SchindelinAug 19, 2006

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.