[Toybox] [PATCH] Fix flags that don't fit in 32 bits.

Rob Landley rob at landley.net
Tue Feb 25 11:07:52 PST 2020


On 2/23/20 1:25 PM, enh via Toybox wrote:
> Fixes https://github.com/landley/toybox/issues/164.

I'm out with my laptop somewhere I can't get net (for some reason the broken
wifi here interferes with my phone associating as an access point, and I only
brought a normal USB cable, not USB-C). I thought I'd look at the patch itself
to see if that had a description of what it was fixing, but no. (Did I need to
pass a second flag to reproduce this, or...)

Luckily I figured it out, but locality of context vs external references are a
thing.

> --- a/scripts/mkflags.c
> +++ b/scripts/mkflags.c
> @@ -220,7 +220,7 @@ int main(int argc, char *argv[])
>      out += strlen(out);
>  
>      while (aflist) {
> -      char *llstr = bit>31 ? "LL" : "", *s = (char []){0, 0, 0, 0};
> +      char *s = (char []){0, 0, 0, 0};
>        int enabled = 0;

The smallest fix is replacing the "31" with a "30", since 1<<31 as a signed int
becomes unsigned and sets lots more flags. (That's the bug, an off-by-one.)

>        // Output flag macro for bare longopts
> @@ -235,8 +235,8 @@ int main(int argc, char *argv[])
>          if (flist && flist->command && *aflist->command == *flist->command)
>            enabled++;
>        }
> -      out += sprintf(out, "#define FLAG_%s (%s%s<<%d)\n",
> -                       s, enabled ? "1" : "FORCED_FLAG", llstr, bit++);
> +      out += sprintf(out, "#define FLAG_%s (%sULL<<%d)\n",
> +                       s, enabled ? "1" : "FORCED_FLAG", bit++);

How... does that ever work at all?

  printf("#undef FORCED_FLAG\n#undef FORCED_FLAGLL\n"
    "#ifdef FORCE_FLAGS\n#define FORCED_FLAG 1\n#define FORCED_FLAGLL 1ULL\n"
    "#else\n#define FORCED_FLAG 0\n#define FORCED_FLAGLL 0\n#endif\n\n");

You're printing out #define FLAG_%s (FORCED_FLAGULL<<1), is it ignoring the
FORCED_FLAGLL macro and instead having FORCED_FLAGULL match the shorter macro
and then the ULL append to it?

cat > hello.c << EOF
#include <stdio.h>

#define WALRUS 1

int main(int argc, char *argv[])
{
  dprintf(2, "%ld\n", WALRUSULL);
}
EOF
$ gcc hello.c
hello.c: In function ‘main’:
hello.c:7:23: error: ‘WALRUSULL’ undeclared (first use in this function)
   dprintf(2, "%ld\n", WALRUSULL);

No? That's not it? And I can't append a space to force the macro resolution
becaue "1 ULL" isn't parsed the same as "1ULL". Hmmm...

Rob

P.S. I didn't want to have the constants all be long long because when it _can_
use shorter math in the flag macros (which is the common case) I want it to. But
I guess you're trusting the optimizer to notice that?



More information about the Toybox mailing list