[Toybox] More find cleanup

Rob Landley rob at landley.net
Sun Apr 21 10:38:00 PDT 2013


On 04/20/2013 01:39:10 PM, Felix Janda wrote:
> Hello,
> 
> some more find cleanup in an attached patch.
> 
> The main change was to make some code in build_filter_list() less
> repetitive using a suitable struct and a loop.

Problem: you defined a struct locally, then used that structure  
definition in GLOBALS. This works for buliding find itself, but breaks  
for building every other command, because they haven't got this  
structure definition.

The reason is generated/globals.h defines "struct mycommand_struct" for  
each command, containing the body of your GLOBALS() block. This file  
ends with union global_union containing all those structs. If there's  
an unknown structure type in one of them that's not defined in headers  
#included before globals.h, the compiler can't determine the size of  
the union, and barfs when anything tries to actually use it.

In toys.h we include generated/globals.h near the end, after lib/lib.h.  
So we can use any of the lib.h types in GLOBALS(), but can't use a  
locally defined type. In main.c it declares the actual instances of  
these variables, and then the TT macros (defined in globals.h based on  
the FOR_command defines) expand to this.command thus referencing the  
right structure type out of the global union.

The workaround is to use a void * in globals and typecast it when you  
need to. (In C that's almost never, it auto-typecasts void pointer  
assignments in both directions. I keep thinking it's only one  
direction, but that's C++'s static typechecking paranoia.) Or since  
it's a list use one of the list types, and again typecast it when you  
need it. If all that's actually stored is a pointer, the pointer type  
doesn't hugely matter, it's the same 4/8 bytes.

If you need one instance of a struct, and for some reason you can't  
expand those contents into TT, you can use a chunk of toybuf to hold  
it, or declare an instance on the stack at the start of command_main()  
and store a void * to it in GLOBALS. (The lifetime of main's locals are  
the lifetime of your command. I'd have just had TT be a pointer to a  
struct on the stack in main() but some build environments have a small  
stack. Yes, I used to care more about nommu than I do now. :)

(If there's a good enough reason you can throw the structure definition  
into lib/lib.h but the rule of thumb there is "used by more than one  
command".)

> The command line parsing
> is however now less efficient since after an argument has been tested
> for equality with different strings like "-mtime" and the  
> corresponding
> type (CHECK_MTIME) has been saved, the saved integer has again to be
> checked for equality with stuff to find out what further command line
> parsing is necessary.

An integer check is trivial. String comparisons do an order of  
magnitude more work and evict cache lines in the process. On processors  
with multiple execution units (on x86 that's everything since the  
original pentium) an extra integer operation may even use an otherwise  
idle execution unit so literally take no time at all. (Branches can be  
expensive, it depends.)

I'm sure I've written up the whole spiel about "branch prediction and  
register renaming, and why the embedded world chooses not to" at some  
point. If I was more awake I could probably not only find it but work  
in a joke about at quoted block's structural parallels to the full  
title of The Hobbit. Lemme know if you're curious enough for me to redo  
it here...

> Apart from this I moved around some variables and got rid of the
> unnecessary index "i" in build_filter_list().

Woot.

> Felix
> 
> BTW: POSIX-1.2008 TC1 is out

I might be happy about this if they hadn't deleted the original  
Posix-2008 to post 5 years of updates all at once (Posix-2001 to  
Posix-2008 was only 7 years) without an obvious changelog. (It says the  
rationale has one, but that's just "why we removed tar and cpio in  
favor of a pax command nobody will ever use, why we decided not to  
include chroot, su, mknod, login, dc because who uses _that_..." All  
2008 decisions, no 2013 diffs.)

Instead, I'm kind of annoyed about it. Luckily, I downloaded the old  
one.

(Version control, guys. It's a thing.)

Rob


More information about the Toybox mailing list