writing usb drivers under 8.x
Jim Bryant
kc5vdj.freebsd at gmail.com
Mon Aug 30 02:20:10 UTC 2010
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