On Fri, 2009-06-19 at 21:24 -0400, Duane Ellis wrote: > Zach Welch wrote: > > On Fri, 2009-06-19 at 20:31 -0400, Duane Ellis wrote: > > > >> duane> FYI - I committed several cygwin specific printf() warning fixes. > >> duane> Simple cast to fix > >> duane> these where causing "-Werror" failures on cygwin. > >> > >> zach> I was just about to post some patches to show how to fix all of these > >> zach> correctly, as casts are not the right way to do it. > >> > >> In some cases, I can agree, but in others - I don't agree. A cast is by > >> far the most simplest solution. > >> > >> For instance, look at this: > >> > >> LOG_WARNING("writing %d bytes only - as image section is %d > >> bytes and bank is only %d bytes", \ > >> (int)(c->base + c->size - run_address), > >> (int)(run_size), (int)(c->size)); > >> > >> (a) look at what is being printed > >> (b) the possible ranges of numbers > >> (c) the number of parameters involved in the expressions > >> > >> At some point - having to dig back 20 to 30 -lines- to *random* places - > >> because some variables are: > >> > >> (1) function parameters > >> (2) defined at the top most block > >> (3) defined locally to the local block > >> (4) defined a few lines down from the top most block > >> (5) often simplistic 'i/j/k' type vars that are reused because they are > >> handy. > >> (6) By the time I personally dig through the above, and determine all > >> types involved > >> (7) Then understand the underlying arithmetic integer promotion order... > >> *note* this set of equations are simple... > >> (8) a cast to a basic type is truly a very *simple* solution, > >> (9) a cast to a basic type in this case is the K.I.S.S. solution. > >> > >> Either that - or we *need* a different solution here, the above is absurd. > >> > >> Comments? > >> > > > > The simple solution is not the correct one in this case. The problem > > is that your assumptions about ranges are not portable; that is the > > point in using these macros. > > > > > > ==== > > You miss an important point, it is *NOT* the possible range of values > the *TYPE* may take on. > > It is the range of values the **ACTUAL*DATA** might take on that is > important here. > Consider: > > uint32_t x; > void funny_function( uint32_t ); > > for( x = 0 ; x < 10 ; x++ ){ > printf(" X = %d, Calling funny function\n", (int)(x)); > funny_function( x ) ; > } > > In the above, I have several choices, (a) I could have used an "int" > variable - then *cast* it to a uint32_t at the function call (note here: > I am partial to x as a loop control variable, others like i/j/k) or - > because (b) the value will never be negative, I just choose 'uint32_t' > because it was convient. > > Is the printf() statement *WRONG* - or is the printf() statement > *CORRECT* in this senario.
It is wrong if you want to be safe when the ranges change, and with general purpose functions the ranges may be set outside the scope of a function that uses them. Safe code would not be making such assumptions about the actual data; even if they hold today, they may not tomorrow. That said, your pedantic example would work acceptably, though I would argue the cast would be more correct to 'unsigned' using format '%u'. > ==== > > If we had to fix this, what would we do to fix this: > > Today - we do not have macros, or types like GDB/GCC/GAS. > GDB for instance uses CORE_ADDR - and has infrastructure behind it. > > Here, under OpenOCD we generally: > > (1) assume that all embedded openocd targets are *32bit* at most... Today maybe, but this is an unacceptable shortcoming. > (2) assume all host platforms are at least 32bit host platforms Again, this is a fair assumption today, but I do not think it again to be a shortcoming that C99 types are designed to overcome. > (3) and thus, target addresses are generally equal to - or smaller then > the host "unsigned integers" This is why we have intptr_t. The code shouldn't care. It's a bug if it does. > (4) In most, if not all of the "u32" cases, the format string specifies > "%08x" or equal. It should... an audit would be required to confirm this is the case. > Are these assumptions *wrong*? If so, we have major other problems we > must deal with. We have major other problems that we must deal with. > ==== > > There are numerous examples of this where - for instance the code does > the following: > > LOG_ERROR("Verfication error address 0x%08x, read back 0x%02x, > expected 0x%02x", address + wrote + i, readback[i], chunk[i]); > > In this specific case, the *correct* fix is something else. > > The "address" parameter really needs a *function* that handles the width > value. Otherwise, a "64bit" target will not work. We are not proposing > to fix these situations today are we? Doing so would really be better > served by a function something like: > > char *target_address_as_hex( CORE_ADDR address_value ); > > One can 'question' the two 8bit values printed, allow me to make my > point another way. Yup. I am definitely not advocating for completely pedantic replacement of all format strings. Certainly, the single byte values can probably be cast to unsigned. :) I was saying that -- if you saw a warning -- the correct fix is probably to use the PRI macros. Otherwise, I am not suggesting changing all instances of these strings. > ==== > > Here is another example: > > LOG_INFO( "device id = 0x%08x (manuf 0x%03x dev 0x%02x, ver 0x%03x)", > device_id, (device_id>>1)&0x7ff, (device_id>>12)&0xff, > (device_id>>20)&0xfff ); > > The format strings alone tell me that a 32bit unsigned *INTEGER* is > sufficient. > As does the math operators. > > Since our *basic* assumption of the host platform is at least a "32bit > unsigned int" > A simple cast is valid here. > > Are you suggesting that our *basic* host assumption is wrong? If we want OpenOCD to work on more C99-compatible targets, yes. > ==== > > duane> 9) a cast to a basic type in this case is the K.I.S.S. > solution.duane> > > zach> I don't care one white about KISS if the code is wrong. > > Is this a pedantic position/point you are trying to make? Clearly. The real world will never be so clear cut, no matter how hard anyone tries to make it. ;) > The code today has *major* problems if/when we have a 64bit target. > The code is more *wrong* when we have 32bit hosts and 64bit targets. Yup, and yup. Cheers, Zach _______________________________________________ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development