domenica 29 dicembre 2013

Define TRUE and FALSE in C

What is FALSE and TRUE in C?


The C standard does not explicitly define TRUE and FALSE, you have to do it somewhere in your headers. Which is the best practice to define them?
It's not such a dumb question, because you may fall in this case:
  #define MASKBIT_0    0x01
  #define MASKBIT_1    0x02
  #define MASKBIT_2    0x04
  ...
  
  unsigned int bits;
  ...
  
  if (bits & MASKBIT_2) {
  ...
  }
  
The example above works correctly, but if you are somewhere absent and you accidentally write:
  #define FALSE         0
  #define TRUE          1
  
  if ((bits & MASKBIT_2) == TRUE) {
  ...
  }
The "if" test will fail, also if MASKBIT_2 is set. This is because ((bits & MASKBIT_2) == 4), that is not 1 (your defined TRUE).

To be honest, the problem is that writing if ((bits & MASKBIT_2) == TRUE) is not correct (you should use the if (bits & MASKBIT_2) semantics), but it's obvious what it means and I'd prefer there was a way to define TRUE and FALSE so that this kind of test would be supported.

Approach 1

  #define FALSE         0
  #define TRUE          1

As shown above, it's not a so good approach, although works in most cases.

Approach 2

Some experienced programmer ("The Linux Programming Interface", not exactly a johnny-come-lately...) suggest the following:
  typedef enum { FALSE, TRUE } Boolean;

The reasons for that are good: enum will add some static-assign-checking of the Boolean declared variables. Not so much checking indeed, enum is not a great checker in C: can't check dinamically assigned varibles, and enum variables are typically int.

Approach 3

Other experienced programmer (i.e. gnome glib) suggest that:
  #define FALSE         0
  #define TRUE          (!(FALSE))

This is another good approach: the FALSE condition in C/C++ is ALWAYS == 0; on the contrary, TRUE condition is not always 0, but usually is a "NOT 0" condition. On the other side, the if ((bits & MASKBIT_2) == TRUE) test will fail anyway: (!(FALSE)) is expanded as a constant (usually 1). There is no static-assign-checking.

Beside that, someone suggest:
  #define TRUE         (1==1)
  #define FALSE        (!TRUE)

Rather than this, I like more:
  #define FALSE        (1==0)
  #define TRUE         (!(FALSE))
  
In this way, you automatically assign the FALSE value also if (for a strange, rare case) your compiler DOES NOT use 0 as a FALSE value, and you assign a TRUE as the negation. This is "logically" good, but does not solve che if ((bits & MASKBIT_2) == TRUE) problem.

The MIX

So what I could do to mix-up the best practices?
Here it is:
  typedef enum { FALSE = (1==0), TRUE = (1==1) } boolean;

In order to avoid the if ((bits & MASKBIT_2) == TRUE) problem, I suggest the following solutions:
1) Use the following function or a similar macro:
  boolean test (int val)
  {
      return (val > 0);
  }
usage: if (test(bits & MASKBIT_2))

2) Do not use bitmask #defines such as MASKBIT_2, instead use the following function or a similar macro:
  boolean test (unsigned int bitpool, int bitnr)
  {
      return ((bitpool & (1 << bitnr)) != 0);
  }
usage: if (test(bits, 2))
I like the solution (2) more, because not defining any MASKBIT, you are forced to use the test() function. You can always define verbose bit names such as:
  #define MYBIT   2

Using the solution (2), you may want to use also the following small functions/MACRO to set and clear bits:
  unsigned int set (unsigned int bitpool, int bitnr)
  {
      return (bitpool | (1 << bitnr));
  }
  
  unsigned int clr (unsigned int bitpool, int bitnr)
  {
      return (bitpool & ~(1 << bitnr));
  }

(or you can pass a pointer to bitpool, if you prefer).

(!(FALSE)) or (1==1)?

It's better to use this?:
  #define TRUE     (!(FALSE))
or this?:
  #define TRUE     (1==1)

They are quite the same. The result is exactly the same. I think that it's slightly better #define TRUE (1==1) only because reading (!(FALSE)) may let you think that the result is anything else than FALSE, which is not correct.

Theoretically, you can't know how the compiler expand (!(FALSE)). Remember that FALSE is an int value you defined before: hypotetically, the compiler could expand (!(FALSE)) with a different value than (1==1); for example, it could expand #define FALSE (1==0) with 0, and (!(FALSE)) with -1 or 0xFFFFFFFF, and on the contrary expand (1==1) with 1. I don't think that any compiler do that, anyway.

Best Practices

I found the following "Best Practices" on a forum discussion:

Given the de facto rules that zero is interpreted as FALSE and any non-zero value is interpreted as TRUE, you should never compare boolean-looking expressions to TRUE or FALSE. Examples:
  if (thisValue == FALSE)  // Don't do this!
  if (thatValue == TRUE)   // Or this!
  if (otherValue != TRUE)  // Whatever you do, don't do this!
Why? Because many programmers use the shortcut of treating ints as bools. They aren't the same, but compilers generally allow it. So, for example, it's perfectly legal to write
  if (strcmp(yourString, myString) == TRUE)  // Wrong!!!
That looks legitimate, and the compiler will happily accept it, but it probably doesn't do what you'd want. That's because the return value of strcmp() is
   0 if yourString == myString
  <0 if yourString < myString
  >0 if yourString > myString
So the line above returns TRUE only when yourString > myString.
The right way to do this is either
  // Valid, but still treats int as bool.
  if (strcmp(yourString, myString))
or
  // Better: lingustically clear, compiler will optimize.
  if (strcmp(yourString, myString) != 0)
Similarly:
  if (someBoolValue == FALSE)     // Redundant.
  if (!someBoolValue)             // Better.
  return (x > 0) ? TRUE : FALSE;  // You're fired.
  return (x > 0);                 // Simpler, clearer, correct.
  if (ptr == NULL)                // Perfect: compares pointers.
  if (!ptr)                       // Sleazy, but short and valid.
  if (ptr == FALSE)               // Whatisthisidonteven.
You'll often find some of these "bad examples" in production code, and many experienced programmers swear by them: they work, some are shorter than their (pedantically?) correct alternatives, and the idioms are almost universally recognized. But consider: the "right" versions are no less efficient, they're guaranteed to be portable, they'll pass even the strictest linters, and even new programmers will understand them.
Isn't that worth it?

Conclusions

I'm not sure that my considerations are defintely good. I may ignore something that is important for this topic. Discussion is open.

mercoledì 10 luglio 2013

Chrome: problema audio ("saltellante") nelle riproduzioni video

Soluzione:
  • Scrivere chrome://plugins nella barra degli indirizzi; premere invio
  • A destra, cliccate su "+ Dettagli"
  • Nella categoria di plugins Flash ci saranno 2 o 3 plugins; bisogna disabilitare quello in cui nel percorso c'è scritto "Pepperflash"
  • Chiudere Chrome e riaprirlo
  • Se ci sono ancora dei problemi, cliccare sulla chiave inglese -> strumenti -> cancella dati di navigazione -> selezionare solo la cache e dare l' OK

giovedì 4 luglio 2013

Disabling reverse DNS lookups in ssh


Disabling reverse DNS lookups in ssh

Reverse DNS lookup is the procedure used by sshd and other login daemons (i.e. telnet, ftp, etc.) for checking the truth of IP addresses of the incoming connection.

Often in embedded systems networks there is no Internet connection, and no DNS server: in this case, ssh login may require a lot of time (30 sec. or more) or can even be impossible (if sshd has been compiled with the PARANOID option).

Reverse DNS lookup can be disabled on the sshd server side:
First of all, you can make "UseDNS no" in /etc/ssh/sshd_config file, default answer is yes and if this line not shown in your config file, just add it to as below:

UseDNS no

This directive tells sshd process to check resolved host name for the connected client's ip address maps back to the very same ip address or not.

However, it does not prevent the sshd server from performing any DNS lookups at all. That's not the purpose of that directive.

In order to remove dns lookups completely, you have to use -u0 options when starting sshd server. You can easily add this options to /etc/default/ssh or /etc/sysconfig/sshd or elsewhere suitable for your distribution.

-u0 option's means that it will not put hostnames into the utmp structure (i.e. what you see when you type "who" at the shell prompt), which means that sshd will not perform DNS lookups for that purpose. However there are still cases where a lookup has to be performed when a user has

"from=<hostname>"

like entries in his authorized_keys file, or when authentication methods or configuration directives are used that involve hostnames.

With this method you can disable ssh reverse DNS lookup for most situations; it's not a system-wide disable, anyway.
For a system-wide solution, you should consider installing a local DNS cache server like dnsmasq and configure it to false the DNS check results in local networks (bogus-priv option), like described here:

http://forums.gentoo.org/viewtopic-t-455597-start-0.html
http://wiki.debian.org/HowTo/dnsmasq



martedì 18 giugno 2013

The printf recursive substitution trap (bug)

Working with embedded linux boards make me use systems that are often not so much up-to-dated.
Kernel is often dated, compiler is often dated, libraries are often dated.

On a system I'm using, the cross compiler is gcc 3.3.2 and the glibc version is 2.2.5.
On this system I've found a bug in the glibc printf family functions, quite difficult to track.

The bug seems to be caused by a recursive substitution in the printf arguments: in printf("%s", text), if the text string includes itself the string "%s" again, the program on my embedded system crashes (with a no more specified "Killed" message).

No help with core dump, strace and dbg: I had to track down step by step to find that the crash happens on a snprintf call, ONLY if the substitution argument string contains a "%s".

So, what I think happens (but I'm not 100% sure) is that the substitution is made recursively also on the second "%s" found, and the program is killed by the kernel OOM Killer (Out-Of-Memory Killer) because the resulting string can't be allocated.

Nice.

Experimenting workarounds, I've found that the bug affects also the strcat functions (maybe it's based on sprintf). I had to use memcpy.

This bug is not present on another embedded system I'm using with a more recent glibc.

lunedì 17 giugno 2013

Nexus7: WiFi Hotspot app (che funziona!)

L'abilitazione delle opzioni per Tethering/WiFi Hotspot sul Nexus7 e' stato un problema fin dalla sua uscita.

Ora finalmente e' disponibile una app che rende il WiFi Hotspot attivo e funzionante: WiFi Tether Router di Fabio Grasso.

Lo sviluppatore e' italiano, attivo e disponibile a rispondere alle email degli utenti rapidamente e con efficienza.
Il router WiFi creato e' di tipo "infrastruttura" e quindi supporta la connessione di piu' dispositivi client.

L'applicazione richiede i permessi di root, e a tal proposito rimando al mio articolo relativo: Nexus 7: rooting da un PC Linux

Con questa applicazione si completano le capacita' di tethering del Nexus7:

martedì 19 marzo 2013

ARM7 GNU Toolchain: GCC 4.3.3


Here are some updated (090615) informations for 4.3.3 GNU gcc arm-elf compilation; this time I want to rebuild the toolchain with strip dead code abilty enabled in newlib.
Please read the previous 4.2.2 compilation info before, because this is only an update.

sabato 2 marzo 2013

Nexus 7: Linux Tethering Bluetooth DUN con PdaNet & wvdial


DUN e' l'interfaccia bluetooth per il Dial Up Networking, cioe' per usare il dispositivo bluetooth (in questo caso il Nexus 7) come se fosse un modem per collegarsi in ppp (point-to-point protocol) ad Internet, uno dei metodi che possono essere usati per il tethering.
Bluetooth offre diversi tipi di servizi, divisi su canali differenti; solitamente l'interfaccia DUN viene fornita sul canale bluetooth 3.
Non tutti i telefoni/smatrphone/tablet offrono l'interfaccia DUN: per esempio il Nexus 7, se non si e' installata la patch XDA non-ufficiale per il tethering Abilitazione delle opzioni per Tethering/WiFi Hotspot, non la fornisce. E' possibile pero' installare una app che la aggiunge, che non necessita dei permessi di root: PdaNet.


giovedì 28 febbraio 2013

ARM7 GNU Toolchain for Linux


Moooolto tempo fa (2008) ho lavorato alla compilazione di una toolchain cross-compiler per ARM7 su Linux (che tutt'ora utilizzo), e da questo ne ho tratto una specie di how-to che ho gia' allora pubblicato sul sito della mia azienda PRECMA S.r.l.

Quella qui di seguito e' la prima parte, a cui segue la seconda relativa alla compilazione della toolchain 4.3.3 GNU con abilitata l'opzione "strip dead code"  in newlib.

giovedì 21 febbraio 2013

Nexus 7: Abilitazione delle opzioni per Tethering/WiFi Hotspot

Nel Nexus 7 3G non sono abilitati i menu di impostazione per il tethering e per il WiFi Hotspot. Non ne capisco il motivo, ma Google ha deciso di non presentarli. Forse perche' sono una funzionalita' che non sempre funziona, o forse perche' si e' asservito alle volonta' dei gestori telefonici, che combattono sempre l'uso del tethering piu' o meno apertamente.

E' possibile utilizzare Bluetooth DUN (Dial Up Networking) con la app "PdaNet"  e l'USB tethering con "AziLink".

UPDATE (130617): e' finalmente disponibile una app che abilita il router access point WiFi del Nexus7: WiFi Hotspot app (che funziona!).
Non e' piu' necessario quindi avventurarsi nelle complicate patch non ufficiali di Android descritte nel post che segue, che mantengo solo come reference di questo tipo di attivita'.

martedì 19 febbraio 2013

Nexus 7: rooting da un PC Linux

Per installare programmi Android speciali a livello di sistema e' necessario accedere al "root level" del dispositivo, cosa che non e' possibile fare senza sbloccare il bootloader e installare una "custom recovery image". Queste operazioni comportano la cancellazione dei dati personali sul dispositivo (programmi, impostazioni, cache, ecc.) quindi conviene farle prima possibile, se si ritiene necessario per il proprio utilizzo del tablet.