Subject: Re: bug#16578: Wish: Support for non-native endianness in od

From: Pádraig Brady <[email-masked]>
Date: Sun, 02 Feb 2014 02:20:11 +0100

On 01/31/2014 09:44 AM, Niels Möller wrote:
> [email-masked] (Niels Möller) writes:
> 
>> Pádraig Brady <[email-masked]> writes:
>>> I agree this would be useful and easy enough to add.
>>> I suppose the interface would be --endian=little|big
>>
>> Maybe I can have a look at what it takes.
> 
> Below is a crude patch (missing: usage message, tests cases, docs,
> translation). I think it should work fine for floats too. I see no
> obvious and more beautiful way to do it. 
> 
> (And I think I have copyright assignment papers for coreutils in place,
> since work on factor some year ago).
> 
> Regards,
> /Niels
> 
> diff --git a/src/od.c b/src/od.c
> index 514fe50..a71e302 100644
> --- a/src/od.c
> +++ b/src/od.c
> @@ -259,13 +259,16 @@ static enum size_spec integral_type_size[MAX_INTEGRAL_TYPE_SIZE + 1];
>  #define MAX_FP_TYPE_SIZE sizeof (long double)
>  static enum size_spec fp_type_size[MAX_FP_TYPE_SIZE + 1];
>  
> +bool input_swap;
> +
>  static char const short_options[] = "A:aBbcDdeFfHhIij:LlN:OoS:st:vw::Xx";
>  
>  /* For long options that have no equivalent short option, use a
>     non-character as a pseudo short option, starting with CHAR_MAX + 1.  */
>  enum
>  {
> -  TRADITIONAL_OPTION = CHAR_MAX + 1
> +  TRADITIONAL_OPTION = CHAR_MAX + 1,
> +  ENDIAN_OPTION,
>  };
>  
>  static struct option const long_options[] =
> @@ -278,6 +281,7 @@ static struct option const long_options[] =
>    {"strings", optional_argument, NULL, 'S'},
>    {"traditional", no_argument, NULL, TRADITIONAL_OPTION},
>    {"width", optional_argument, NULL, 'w'},
> +  {"endian", required_argument, NULL, ENDIAN_OPTION },
>  
>    {GETOPT_HELP_OPTION_DECL},
>    {GETOPT_VERSION_OPTION_DECL},
> @@ -406,7 +410,21 @@ N (size_t fields, size_t blank, void const *block,                      \
>      {                                                                   \
>        int next_pad = pad * (i - 1) / fields;                            \
>        int adjusted_width = pad_remaining - next_pad + width;            \
> -      T x = *p++;                                                       \
> +      T x;                                                              \
> +      if (input_swap && sizeof(T) > 1)                                  \
> +        {                                                               \
> +          int j;                                                        \
> +          union {                                                       \
> +            T x;                                                        \
> +            char b[sizeof(T)];                                          \
> +          } u;                                                          \
> +          for (j = 0; j < sizeof(T); j++)                               \
> +            u.b[j] = ((const char *) p)[sizeof(T) - 1 - j];             \
> +          x = u.x;                                                      \
> +        }                                                               \
> +      else                                                              \
> +        x = *p;                                                         \
> +      p++;                                                              \
>        ACTION;                                                           \
>        pad_remaining = next_pad;                                         \
>      }                                                                   \
> @@ -1664,6 +1682,24 @@ main (int argc, char **argv)
>            traditional = true;
>            break;
>  
> +        case ENDIAN_OPTION:
> +          if (!strcmp (optarg, "big"))
> +            {
> +#if !WORDS_BIGENDIAN
> +              input_swap = true;
> +#endif
> +            }
> +          else if (!strcmp (optarg, "little"))
> +            {
> +#if WORDS_BIGENDIAN
> +                input_swap = true;
> +#endif
> +            }
> +          else
> +            error (EXIT_FAILURE, 0,
> +                   _("bad argument '%s' for --endian option"), optarg);
> +          break;
> +
>            /* The next several cases map the traditional format
>               specification options to the corresponding modern format
>               specs.  GNU od accepts any combination of old- and

That looks good.
I'll adjust slightly to use XARGMATCH and add some docs/tests.
I'm travelling at the moment but merge this soon.

thanks!
Pádraig.