writing usb drivers under 8.x

Jim Bryant kc5vdj.freebsd at gmail.com
Mon Aug 30 02:26:46 UTC 2010


but then gnu does it's own thing too.  my point stands though.  any 
actual evaluation of thirtytwok into something OTHER THAN (1<<15) in the 
actual emitted code is IMPLEMENTATION-SPECIFIC.

in the case if gnu, you do appear to be right though, in disregard to K&R.

one could also argue that my return(0) is implementation-specific, as 
exit(0) would be proper by the numbers.

my point still stands, that although it may be cute to have (1<<15) in 
the define, it is not good practice.

 9:21:33pm  orb(13): cat bs4.c
#include <stdio.h>

#define thirtytwok (1<<15)

int main(void)
{
  int toshiftornottoshift = thirtytwok;

  printf("%d\n", toshiftornottoshift);

  return(0);
}
 9:21:39pm  orb(14): cc -S -O2 -o bs4.s bs4.c
 9:21:56pm  orb(15): cat bs4.s
        .file   "bs4.c"
        .section        .rodata.str1.1,"aMS", at progbits,1
.LC0:
        .string "%d\n"
        .text
        .p2align 4,,15
.globl main
        .type   main, @function
main:
.LFB3:
        subq    $8, %rsp
.LCFI0:
        movl    $32768, %esi
        movl    $.LC0, %edi
        xorl    %eax, %eax
        call    printf
        xorl    %eax, %eax
        addq    $8, %rsp
        ret
.LFE3:
        .size   main, .-main
        .section        .eh_frame,"a", at progbits
.Lframe1:
        .long   .LECIE1-.LSCIE1
.LSCIE1:
        .long   0x0
        .byte   0x1
        .string "zR"
        .uleb128 0x1
        .sleb128 -8
        .byte   0x10
        .uleb128 0x1
        .byte   0x3
        .byte   0xc
        .uleb128 0x7
        .uleb128 0x8
        .byte   0x90
        .uleb128 0x1
        .align 8
.LECIE1:
.LSFDE1:
        .long   .LEFDE1-.LASFDE1
.LASFDE1:
        .long   .LASFDE1-.Lframe1
        .long   .LFB3
        .long   .LFE3-.LFB3
        .uleb128 0x0
        .byte   0x4
        .long   .LCFI0-.LFB3
        .byte   0xe
        .uleb128 0x10
        .align 8
.LEFDE1:
        .ident  "GCC: (GNU) 4.2.1 20070719  [FreeBSD]"
 9:22:00pm  orb(16):


Jim Bryant wrote:
> well, i can't speak for K&R 1978, as i can't currently find my copy, 
> but, for a quick brush up, you might want to read pages 80 and 81 from 
> K&R 2nd Ed. 1988.
>
> your idea that the preprocessor will evaluate
>
> #define thirtytwok (1<<15)
>
> into 0x8000
>
> at compile time is totally incorrect, and in fact wouldn't be in 
> compliance with standards.  i have iso and fips handy, care for quotes?
>
> microsoft used to do compile-time eval of preprocessor statements 
> instead of substitution, but that was implementation-specific and 
> non-standard.
>
> From K&R, 2nd Ed. pp80-81 (1988):
>
> 4.11.2 Macro Substitution
>
> A definition has the form
>
> #define name replacement text
>
> It calls for a macro substitution of the simplest kind - subsequent 
> occurrences of the token
> name will be replaced by the replacement text. The name in a #define 
> has the same form as a
> variable name; the replacement text is arbitrary. Normally the 
> replacement text is the rest of
> the line, but a long definition may be continued onto several lines by 
> placing a \ at the end of
> each line to be continued. The scope of a name defined with #define is 
> from its point of
> definition to the end of the source file being compiled. A definition 
> may use previous
> definitions. Substitutions are made only for tokens, and do not take 
> place within quoted
> strings. For example, if YES is a defined name, there would be no 
> substitution in
> printf("YES") or in YESMAN.
>
> Any name may be defined with any replacement text. For example
>
> #define forever for (;;) /* infinite loop */
>
> defines a new word, forever, for an infinite loop.
>
> It is also possible to define macros with arguments, so the 
> replacement text can be different
> for different calls of the macro. As an example, define a macro called 
> max:
>
> #define max(A, B) ((A) > (B) ? (A) : (B))
>
> Although it looks like a function call, a use of max expands into 
> in-line code. Each occurrence
> of a formal parameter (here A or B) will be replaced by the 
> corresponding actual argument.
>
> Thus the line
>
> x = max(p+q, r+s);
>
> will be replaced by the line
>
> x = ((p+q) > (r+s) ? (p+q) : (r+s));
>
> So long as the arguments are treated consistently, this macro will 
> serve for any data type;
> there is no need for different kinds of max for different data types, 
> as there would be with
> functions.
>
> 81
>
> If you examine the expansion of max, you will notice some pitfalls. 
> The expressions are
> evaluated twice; this is bad if they involve side effects like 
> increment operators or input and
> output. For instance
>
> max(i++, j++) /* WRONG */
>
> will increment the larger twice. Some care also has to be taken with 
> parentheses to make sure
> the order of evaluation is preserved; consider what happens when the 
> macro
>
> #define square(x) x * x /* WRONG */
>
> is invoked as square(z+1).
>
> Nonetheless, macros are valuable. One practical example comes from 
> <stdio.h>, in which
> getchar and putchar are often defined as macros to avoid the run-time 
> overhead of a
> function call per character processed. The functions in <ctype.h> are 
> also usually
> implemented as macros.
>
> Names may be undefined with #undef, usually to ensure that a routine 
> is really a function, not
> a macro:
>
> #undef getchar
> int getchar(void) { ... }
>
> Formal parameters are not replaced within quoted strings. If, however, 
> a parameter name is
> preceded by a # in the replacement text, the combination will be 
> expanded into a quoted string
> with the parameter replaced by the actual argument. This can be 
> combined with string
> concatenation to make, for example, a debugging print macro:
>
> #define dprint(expr) printf(#expr " = %g\n", expr)
>
> When this is invoked, as in
>
> dprint(x/y)
>
> the macro is expanded into
>
> printf("x/y" " = &g\n", x/y);
>
> and the strings are concatenated, so the effect is
>
> printf("x/y = &g\n", x/y);
>
> Within the actual argument, each " is replaced by \" and each \ by \\, 
> so the result is a legal
> string constant.
>
> The preprocessor operator ## provides a way to concatenate actual 
> arguments during macro
> expansion. If a parameter in the replacement text is adjacent to a ##, 
> the parameter is replaced
> by the actual argument, the ## and surrounding white space are 
> removed, and the result is rescanned.
>
> For example, the macro paste concatenates its two arguments:
>
> #define paste(front, back) front ## back
>
> so paste(name, 1) creates the token name1.
>
> The rules for nested uses of ## are arcane; further details may be 
> found in Appendix A.
> Exercise 4-14. Define a macro swap(t,x,y) that interchanges two 
> arguments of type t.
> (Block structure will help.)
>
> Jim Bryant wrote:
>> ummmm.. you were saying???
>>
>> 8:58:44pm  orb(19): cat bs3.c
>> #include <stdio.h>
>>
>> int main(void)
>> {
>>  int toshiftornottoshift = 0x8000;
>>
>>  printf("%d\n", toshiftornottoshift);
>>
>>  return(0);
>> }
>> 8:58:48pm  orb(20): cc -S -O2 -o bs3.s bs3.c
>> 8:58:53pm  orb(21): cat bs3.s
>>        .file   "bs3.c"
>>        .section        .rodata.str1.1,"aMS", at progbits,1
>> .LC0:
>>        .string "%d\n"
>>        .text
>>        .p2align 4,,15
>> .globl main
>>        .type   main, @function
>> main:
>> .LFB3:
>>        subq    $8, %rsp
>> .LCFI0:
>> /*
>> *      this doesn't look like the compiler generates a shift to me.
>> */
>>        movl    $32768, %esi
>>        movl    $.LC0, %edi
>>        xorl    %eax, %eax
>>        call    printf
>>        xorl    %eax, %eax
>>        addq    $8, %rsp
>>        ret
>> .LFE3:
>>        .size   main, .-main
>>        .section        .eh_frame,"a", at progbits
>> .Lframe1:
>>        .long   .LECIE1-.LSCIE1
>> .LSCIE1:
>>        .long   0x0
>>        .byte   0x1
>>        .string "zR"
>>        .uleb128 0x1
>>        .sleb128 -8
>>        .byte   0x10
>>        .uleb128 0x1
>>        .byte   0x3
>>        .byte   0xc
>>        .uleb128 0x7
>>        .uleb128 0x8
>>        .byte   0x90
>>        .uleb128 0x1
>>        .align 8
>> .LECIE1:
>> .LSFDE1:
>>        .long   .LEFDE1-.LASFDE1
>> .LASFDE1:
>>        .long   .LASFDE1-.Lframe1
>>        .long   .LFB3
>>        .long   .LFE3-.LFB3
>>        .uleb128 0x0
>>        .byte   0x4
>>        .long   .LCFI0-.LFB3
>>        .byte   0xe
>>        .uleb128 0x10
>>        .align 8
>> .LEFDE1:
>>        .ident  "GCC: (GNU) 4.2.1 20070719  [FreeBSD]"
>>
>> perryh at pluto.rain.com wrote:
>>> Jim Bryant <kc5vdj.freebsd at gmail.com> wrote:
>>>
>>>  
>>>> what kind of idiot defines a constant assignment for a 32k buffer 
>>>> as a 15 bit left shift of 1?
>>>>
>>>> clever, yes.  but in production, stupid.
>>>>
>>>> a constant should be just that, a constant, and thus require no 
>>>> computation at runtime.
>>>>     
>>>
>>> Er, did you bother to look at the generated code before spouting off?
>>> Most compilers, even as far back as K&R 1st edition, will compute
>>> constant expressions like that at compile time.
>>>
>>>   
>>
>


More information about the freebsd-usb mailing list