! Given a C header file, generate corresponding Dylan C-FFI declarations. ! ! This file defines a set of text transformation rules for "gema". ! ! This supports the common functionality needed for the Microsoft Windows ! and X Windows header files, but is not expected to handle the full ! C language. ! Copyright (c) 1998 Functional Objects, Inc. All rights reserved. ! $HopeName$ ! $Date: 2004/03/12 00:10:34 $ @set-switch{t;1}@set-switch{w;1} @set-syntax{L;\-\.\(\)} @set-switch{match;1} ! command-line option for name of module: ARGV:\N-module \n=@set{heading;module\: $1\n\n} ! command-line option for file of names to be excluded: ARGV:\N-exclude \n=@load-obsolete{@read{$1}} ! command-line option for literal name(s) to be excluded: ARGV:\N-omit *\n=@load-obsolete{$1} load-obsolete:\I=@define{relevant-name\:$1\=\@fail}\ @define{bad-struct\:_$1\=\$0\@end} load-obsolete:\J\J=\ @define{relevant-function\:@quote{$0}\\J\\\I\=\@fail} load-obsolete:<-A0>=@define{relevant-name\:@quote{$1$3}\=\@fail}\ @define{bad-struct\:@quote{_$1$3}\=\$0\@end} load-obsolete:=@define{relevant-name\:@quote{$1}\=\@fail} load-obsolete:\S=;,= load-obsolete:\/\/*\n= load-obsolete:\/\*\*\/= load-obsolete:= @err{\N"@file" line @line, unrecognized: $1\n} ! command-line option to specify that only those names listed in ! a file are to be translated. ARGV:\N-only \n=@set-switch{t;0}\ @load-only{@read{$1}}@undefine{relevant-name\:\}\ @define{bad-struct\:\_\\\I\=\@fail}\ @define{bad-struct\:tag\\\I\=\$0\@fail}\ @define{nogood\:\\W\\=\$1\@fail} ! additional identifiers to be included (after -only file) ARGV:\N-add *\n=@load-only{$1} load-only:\I=@define{relevant-name\:$1\=\$0\@end} load-only:\J\J=\ @define{relevant-function\:$0\\\I\=\$0\@end} load-only:\J_\J\I=\ @define{relevant-constant\:$1$2_\\\\I\=\$0\@end}\ @define{relevant-name\:$0\=\$0\@end} load-only:=@define{relevant-name\:$1\\\I\=\$0\@end} load-only:\S=;,= load-only:\/\/*\n= load-only:\/\*\*\/= load-only:= @err{\N"@file" line @line, unrecognized: $1\n} opta:\JA=A@end;=@end ! optional name of generated export file: ARGV:\N-exports \n=@set{-exports;$1} wildcard:\*<-I>=@fail wildcard:\?<-I>=@fail wildcard:\J\*=@quote{$1}\\J\$2 wildcard:\J\?=@quote{$1}\\J\$2\\I wildcard:=@terminate wildcard:=@terminate morewild:=\\J@quote{$1} morewild:=@end morewild:=@end ! change underscores to hyphens: map-name:\J_\J=-;?=? @set-wrap{70;\t} ! use variable x to avoid duplication of Foo for FooA and FooW @set{x;} export:\A$x\Z=$x export:*=@set{x;@map-name{$1}}$x\ @write{${export-file};${export-head}@wrap{ $x}}\ @set{export-head;\,}@set{export-tail;\;\n} export-end:=@write{${export-file};${export-tail;}}\ @set{export-head; export}@set{export-tail;} \B=@var{heading;@err{Missing -module\n}}@bind{heading;}\ @set{O;@outpath}@err{\ @file -\> @relative-path{$O;$O} ...\n}\ \/\/ This file is automatically generated from \"@file\"\; do not edit.\n\n\ @bind{export-file;@var{-exports;@mergepath{@outpath;@file;.exp}}}\ @bind{export-head; export}@bind{export-tail;}\ @write{${export-file};\n\ \ \/\/ from \"@file\"\:\n} close-export:=@export-end{}\ @cmps{${-exports;};${export-file};@close{${export-file}};;}\ @unbind{export-file}@unbind{export-head}@unbind{export-tail} \E=\N\n${defer;}@set{defer;}@close-export{}@unbind{heading} ! hack to keep export list from getting too long: \N\/\*\n

\n\*\/\n=@export-end{} \n\n\n=@export-end{} \n\n\Ptypedef=@export-end{} \/\/\n\/\/\L

\n\G\/\/\n=@export-end{} \B\W\/\*\n

\*\/=\n\/\/ Adapted from\:\n$0\n header:\L\CCopyright*\n=\N \/\J\/*\n= \/\J\*\*\J\/= comment:\/\J\*\*\J\/= comment:\/\J\/\P\L*\*\J\/=\/\ \/! To fix BUG 395 ! optional space space:\/\J\/*\n= $0 space:\/\J\*\*\J\/= $0 ; space:=$1 space:\N\W\#*\n=$0 space:=@end \"\"= string:\\?=\\? \'\'= char:\\?=\\?@end;?=?@end matchparen:(#)=(#) matchparen:\{#\}=\{#\} matchparen:\/\J\*\*\J\/= matchparen:\/\J\/*\n= matchparen:\"\"=$0 matchparen:\'\'=$0 matchparen:\#if\J*\n\G\#e\J*\n=$0 matchparen:\P\)=@end matchparen:\P\}=@end ! this one preserves comments matchparen2:\/\J\*\*\J\/=$0 matchparen2:\/\J\/*\n=$0 matchparen2::matchparen ! ---- data types ---- type:struct _\J\W\W=@resolve-type{$2$1}@end type:struct tag\J\W\W=@resolve-type{$2$1}@end type:struct \W\W=@resolve-type{$2$1}@failed{error type struct $1}@end type:struct=@fail type:const = \/\* const \*\/ $1@end type:CONST = \/\* const \*\/ $1@end type:int=\@end type:unsigned long=\@end type:signed long=\@end type:unsigned short=\@end type:unsigned char=\@end type:signed char=\@end type:unsigned int=\@end type:unsigned=\@end type:long int=\@end type:long=\@end type:short int=\@end type:short=\@end type:float=\@end type:double=\@end type:\Cchar\W\*=\@end type:wchar_t\W\*=\@end type:char=\@end type:void=\@end type:0\J=@fail! 0xFFL is not an identifier type:=@resolve-type{$2$1}@end type:\/\*\*\/\W= type:=@fail stars:\*=\* stars:const= \/\* const \*\/ ; stars:\S= stars:volatile= stars:=@end resolve-type:\A\ \/\**\*\/\W=\I\/\**\*\/\ \< resolve-type:\A=\< resolve-type:\Z=\> resolve-type:\J_\J=- resolve-type:\*=$1 resolve-type:\*=$2@map-name{$3}\* resolve-type:\*=@map-name{$2}\*$1\ @err{Warning - possible undefined type\: \<@map-name{$2}\*$1\>\n} resolve-type:\/\**\*\/= resolve-type:=$1 resolve-type:\S= resolve-type:?=@failed{error resolve-type $0}@end ptr-type:\S=\S ptr-type:\/\**\*\/=$0 ptr-type:=@fail ! function types: typedef (\*\W)(\W)\;=\ \Ndefine constant @export{\<$3\>} \=\ \S\\;\n ! general type equivalence: typedef \G\W\G\W,\;=\ @{typedef $1\I$2$3\;typedef $1\I$4\;} typedef \G\W\;=\ \Ndefine inline constant @export{@type{$3}} \= @type{$1$2}\;\n typedef \W\G\W\;=@do-typedef{$2\d$1} do-typedef:*\d*=\Ndefine inline constant @export{@type{$1}} \= $2\;\n ctype:\Cconst\W=$0 ctype:unsigned\W=$0 ctype:signed\W=$0 ctype:struct =$0@end ctype:struct=@fail ctype:=\I$1@end ctype:\S=\I;=@fail optstars:\*=\* optstars:\S=\I optstars:=@end typelist:\W=$1 typelist:\/\J\*\*\J\/= typelist:,=,\s;\S=;=@failed{error typelist $1}@fail ! ---- constants ---- typedefenum \{\}\;= typedefenum\W\{\W\}\W=\N\/\/ enum $5\:\n$4\n\ @set{prev;-1}@cmps{$5;;;;@define{type\:$5\=\\@end}} enumbody:\/\/*\n= enumbody:\/\*\*\/= enumbody:= enumbody:\W\=\W=define inline-only constant @export{\$$1} \= \ $2\;\n@set{prev;$2} enumbody:\W\=\W=\ define inline-only constant @export{\$$1} \= \$$2\;\n@set{prev;\$$1} enumbody:=define inline-only constant @export{\$$1} \= \ ${prev;-1} + 1\;\n@set{prev;\$@map-name{$1}} enumbody:,= enumbody:=@failed{error enumbody $1} term:,=@end;\P\;=@end;\P\}=@end;\P\)=@end;\S=;=@fail number:\J\W\<\<\W=ash($1,$3)@end number:(int)\W=$1@end number:0x0\J\I=\#x0$1@end number:\C0xFFFFFFFF\J\I=\$FFFFFFFF@end number:0x\J\I=as(\, \#x$1)@end number:(\W\|)=logior(@number{$1},$2)@end number:()\W=c-type-cast($1,$2)@end number:(\W)=@fail number:(\W\W)=$1@end number:-\W=-$1@end number:\~\W=lognot($1)@end number:0x\J\I=\#x$1@end number:0\J\I=\#o$1@end number:int=@fail number:\I=$1@end number:\L\W/[-+*]/\W=\$@map-name{$1} $2 $3@end number:\L\W\P\G=\$@map-name{$1}@end number:=@fail optL:\C\JU\J= optL:\C\JL\J= optL:=@end signed-number:\C0xFFFFFFFF\J\I=lognot(0)@end signed-number:(\W#\W)=$1@end signed-number::number or-args:\|=, or-args:\S= or-args:\\\n= or-args:=\S$1 or-args:=@fail termchar:,=@end;\;=@end;\]=@end;\)=@end;\}=@end;\#=@end;\|=@end;=@fail \#define\L =\N$1\N defn:\N=@terminate;=@fail defn:\L =\ @define{link\:\\I$1\\I\=@quote{$2}\@end}@end ! try to avoid forward references: defn:\L\G \W=@append{defer;\ define inline-only constant @export{\$$1} @tab{42}\=@wrap{\s$2\;}\n}@end symconst:\J_\J=\$@map-name{$1_$2}@end symconst:=@fail ! general case for numeric constants: defn:\L\G \W=\ \Ndefine inline-only constant @export{\$$1} @tab{57}\=\ @wrap{\s@right{4;$2}\;}\n@end ! string constants in COMMDLG.H and COMMCTRL.H defn:\L\JA \"\"=\ \Ndefine constant @export{\$$1} @tab{32} \=@wrap{\ \"$2\"\;}\n@end relevant-constant:NULL\I=@fail relevant-constant:TRUE\I=@fail relevant-constant:FALSE\I=@fail relevant-constant::relevant-name relevant-name:FLOAT=@fail! don't try to redefine Dylan relevant-name:=$1@end relevant-name:=@fail endline:\/\/*\n=@end endline:\/\*\*\/= endline:\n=@end endline:^M^J=@end endline:\s=;\t= endline:=@fail ! ---- functions ---- link:=@end reqlink:=$1@terminate args:,=;\S= args:...=\ \ varargs \;\n@fail! C-FFI doesn't implement this yet (Bug 4176) ??? args:va_list=@fail! don't know how to handle this yet ??? args:\#if\I\W=@args{$4} args:\#if\I\W=@args{$3} ! special case for output parameters: args:\G\W\*\W=@outparm{$1\* $2} outparm:\W=\ \ output @putparm{$2,$1} outparm:*=@failed{error outparm *} putparm:,*=parameter @map-name{$1} @tab{24}\:\: $2\;\n putparm:,*=parameter @argname{$1} @tab{24}\:\: $1\;\n ! general case: args:\W=\ \ @putparm{$2,$1} args:void=@end args:\/\J\*\*\J\/= args:\/\J\/*\n= args:*\,=@failed{error args $0}@fail args:*\P\)=@failed{error args $0}@fail arg-id:=$1@end arg-id:=$1@end arg-id:\/\*\W\W\*\/=$1@end arg-id:=@end argname:\/\*\*\/= argname:\*=P argname:=@downcase{$1} argname:\ =\ @err{\N"@file" line @line, failed match for $1\: $2$3...\n}@end failed: *=\ @err{\N"@file" line @line, failed match for $1\: $2\N}@end result:\= result:*=\ \ result value \:\: $1\;\n ! scalar data types: scalar:int=$0@end scalar:long=$0@end scalar:short=$0@end scalar:unsigned =$0 scalar:signed =$0 scalar:=@fail outok:=$1@end outok:=@fail ! ---- structures ---- ! don't want these typedefstruct \{\}\;= typedef union \{\}\;= bad-struct:=$1@fail bad-struct:=@end bad-struct:=@fail nogood:=@end @set{packing;} \#pragma pack()=@set{packing;\ \ pack\:\ $1\;\n} \#pragma pack(push,)=@push{packing;\ \ pack\:\ $1\;\n} \#pragma pack(push)=@push{packing;${packing}} \#pragma pack(pop)=@pop{packing} \#include \Cpshpack\J\.h=@push{packing;\ \ pack\:\ $2\;\n} \#include \Cpoppack.h=@pop{packing} map-ptr-name:*=@map-name{*}\* typedefstruct\I\W\{\}\W*\;=\ @bind{fields;@fields{$4}}\N\n@bind{sclass;@map-name{$5}}\ define C-struct @export{\<${sclass}\>}\n${fields}\N${packing}\ @define{ptr-type\:\\J@quote{$5}\=@quote{@map-ptr-name{${sclass}}}}\ \ \ pointer-type-name\: @export-ptr{\<@map-ptr-name{${sclass}}\>}\;\n\ @cmps{$2;;;;\ \ c-name\: \"struct $2\"\;\n}\ end C-struct \<${sclass}\>\;\ \N@styps{*}\N@unbind{sclass}@unbind{fields} typedef union\I\W\{\}\W*\;=\N\n\ @bind{sclass;@map-name{$4}}\ define C-union @export{\<${sclass}\>}\n$3\N${packing}\ end C-union \<${sclass}\>\;\ \N@styps{*}\N@unbind{sclass} fields:\S= fields:\/\J\/*\n= fields:\/\J\*\*\J\/\W= fields: \[\W\]\;=\ \ \ sealed inline-only array slot @export{$2-array} @tab{42}\:\:\ @wrap{\ @type{$1},}@wrap{\ length\: $3,}\ @ignore{@export{$2-array-setter}}\ @wrap{\ address-getter\: @export{$2-value}\;}\n ! a 1-bit field will never need to be a . fields:int \W\:\W\;=\ \ \ sealed bitfield slot @export-slot{$1} @tab{40}\:\:\ @wrap{\ \, width\: $2\;}\n fields: \W\:\W\;=\ \ \ sealed bitfield slot @export-slot{$2} @tab{42}\:\:\ @wrap{\ @type{$1}, width\: $3\;}\n fields:\G\W\;=\ \ \ sealed inline-only slot @export-slot{$2} @tab{42}\:\: $1\;\n fields:\G\W,\;=\ \ \ sealed inline-only slot @export-slot{$2} @tab{42}\:\: @type{$1}\;\n\ @fields{$1 $3\;} fields:\#if\I\W=@fields{$4} fields:\#if\I\W=@fields{$3} fields:\#ifdef =@fields{$4} fields:\#ifdef =@fields{$3} fields:\#ifndef =@fields{$3} fields:\#ifndef =@fields{$4} @set{gencount;0} fields:union\I\W\{\}\W\W\;=@incr{gencount}\ @out{define C-union \<$3\%${gencount}\>\n$2\N${packing}\ @cmps{$1;;;;\ \ c-name\: \"union $1\"\;\n}\ end\;\n}\ @emit-slots{,$3 $4\d\<$3\%${gencount}\>} fields:struct\I\W\{\}\W\W\;=@incr{gencount}\ @out{define C-struct \<$3\%${gencount}\>\n$2\N${packing}\ @cmps{$1;;;;\ \ c-name\: \"struct $1\"\;\n}\ end\;\n}\ @emit-slots{,$3 $4\d\<$3\%${gencount}\>} emit-slots:\d=@end emit-slots:\S= emit-slots:,\W*\d*=\ \ \ sealed inline-only slot @export{$2-value} @tab{42}\:\:\ \ $4, setter\: \#f\;\n\ @emit-slots{$3\d$4} fields:union\{\}\G\;=@incr{gencount}\ @out{define C-union \\n$1\N${packing}end\;\n}\ \ \ sealed inline-only slot @export-slot{u} @tab{42}\:\:\ \ \\;\n fields:struct\{\}\G\;=@incr{gencount}\ @out{define C-struct \\n$1\N${packing}end\;\n}\ \ \ sealed inline-only slot @export-slot{u} @tab{42}\:\:\ \ \\;\n fields:*\n=@failed{warning fields *}@fail export-slot:\Cspare\J*=$0@end export-slot:*\JReserved\J*=*Reserved*@end export-slot:*=@export{$1-value}@ignore{@export{$1-value-setter}}@end export-ptr:*=@export{$1}@append{defer;\ define sealed domain make (singleton($1))\;\n\ define sealed domain initialize ($1)\;\n} ignore:=@end make-list:\W\W\Z=\#($1) make-list:*=list(*) styps:\S= styps:=define inline constant @export{\<$1\>} \= \<${sclass}\>\;\n styps:\*=@do-typedef{$1\d\<@map-ptr-name{${sclass}}\>} styps:\,= strip-angle-brackets:\<\>=$1 ! ---- conditionals ---- elsepart:\#endif=@end elsepart:\#else \#endif=$1@end elsepart:\#elif=$3@end elsepart:\#elif\W\P\#e\J= elsepart:=@fail def-flag:=@fail ARGV:\N-D\J\W\n=@define{def-flag\:$1\=\$0\@end}@undefine{undef-flag\:$1} \#ifdef =@{$3} \#ifndef =@{$4} \#if\I\W=@{$4} \#if\I=@{$3} false-flag:0=$0@end false-flag:FALSE=$0@end false-flag:defined(\W)=$1 false-flag:\!defined(\W)=$1 false-flag:\!(\L\W)=$0 false-flag:(#)=$1 false-flag:()\&\&(\W)=$0 false-flag:\&\&\L=@end false-flag:\|\|=$0 false-flag:\L= false-flag:=@terminate true-flag:defined(\W)=$1 true-flag:\!defined(\W)=$1 true-flag:\!(\L\W)=$0 true-flag:()\|\|=$2 true-flag:(#)=$1 true-flag:\|\|\L=@end true-flag:\&\&=$0 true-flag:\L= true-flag:=@terminate matchparenline:\P\n=@end matchparenline::matchparen \#ifdef =@{$4} \#ifndef =@{$3} undef-flag:_MIPS_=@end undef-flag:_PPC_=@end undef-flag:_MPPC_=@end undef-flag:_ALPHA_=@end undef-flag:_MAC=@end undef-flag:_68K_=@end undef-flag:__cplusplus=@end undef-flag:=@fail ARGV:\N-U\J\W\n=@define{undef-flag\:$1\=\$0\@end}@undefine{def-flag\:$1} matchcond:\#if\J*\n\G\W=$0 matchcond:\P\#endif=@end matchcond:\P\#else=@end matchcond:\P\#elif=@end matchcond:\#elif\W= matchcond:\#*\n=$0 elsecond:\#endif=$0\n@end elsecond:\#else \#endif=$0\n@end elsecond:\#elif\W=$3@end elsecond:=@fail ! ---- defaults ---- \N\W\#*\n= = \S=