]> Pileus Git - wmpus/blob - wayland.sh
Add home grown wayland protocol
[wmpus] / wayland.sh
1 #!/bin/bash
2
3 # Formatting helpers
4 function comment {
5         echo "/* $* */"
6 }
7
8 function banner {
9         echo "/***********************************************************"
10         echo " * $1"                                                  
11         echo " ***********************************************************/"
12 }
13
14 function enum {
15         printf "\t%-30s = %s,\n" "$(upper $1)" "$2"
16 }
17
18 function upper {
19         echo $1 | tr 'a-z' 'A-Z'
20 }
21
22 # XPath Helpers
23 function xpath {
24         xmllint --xpath $1 wayland.xml
25 }
26
27 function xpathv {
28         xpath $1 | sed -r 's/\w+="([^"]+)"/\1/g'
29 }
30
31 function exists {
32         xpath "$1" > /dev/null 2>&1
33 }
34
35 function isarray {
36         exists "$1/arg[@type='string']|$1/arg[@type='array']|$1/arg[@type='fd']"
37 }
38
39 # Message helpers
40 function msg_field {
41         case $1 in
42                 int)    echo -e "\tint32_t     $2;"  ;;
43                 uint)   echo -e "\tuint32_t    $2;"  ;;
44                 new_id) echo -e "\tuint32_t    $2;"  ;;
45                 object) echo -e "\tuint32_t    $2;"  ;;
46                 fixed)  echo -e "\twl_fixed_t  $2;"  ;;
47                 array)  echo -e "\twl_array_t  $2;"  ;;
48                 string) echo -e "\twl_string_t $2;"  ;;
49                 fd)     ;;
50         esac
51 }
52
53 function msg_array {
54         for t in $(xpathv "$1"); do
55                 case $t in
56                         array)  echo -n "a" ;;
57                         string) echo -n "s" ;;
58                         fd)     echo -n "f" ;;
59                         *)      echo -n "-" ;;
60                 esac
61         done
62 }
63
64 # Interface functions
65 function print_iface_vers {
66         local vers
67         for i in $IFACES; do
68                 vers=$(xpath "string(/protocol/interface[@name='$i']/@version)")
69                 printf "#define %-32s %s\n" "$(upper ${i}_version)" "$vers"
70         done
71 }
72
73 function print_iface_enum {
74         local cnt
75         cnt=0
76         for i in $IFACES; do
77                 enum "${i}" $((cnt++))
78         done
79         enum "wl_num_interfaces" $((cnt++))
80 }
81
82 # Enumeration functions
83 function print_enums {
84         local base k v
85         base="/protocol/interface[@name='$i']/enum"
86         if exists "$base"; then
87                 comment $1
88                 for e in $(xpathv "$base/@name"); do
89                         echo "typedef enum {"
90                         for n in $(xpathv "$base[@name='$e']/entry/@name"); do
91                                 k="$base[@name='$e']/entry[@name='$n']/@value"
92                                 v=$(xpath "string($k)")
93                                 printf "\t%-40s = %s,\n" \
94                                         "$(upper "${i}_${e}_${n}")" "$v"
95                         done
96                         echo "} ${i}_${e};"
97                         echo
98                 done
99         fi
100 }
101
102 # Message functions
103 function print_msg_ids {
104         local cnt base
105         cnt=0
106         base="/protocol/interface[@name='$IFACE']/$2"
107         if exists "$base"; then
108                 comment $1
109                 echo "typedef enum {"
110                 for r in $(xpathv "$base/@name"); do
111                         enum "${IFACE}_${r}" $((cnt++))
112                 done
113                 enum "${IFACE/wl/wl_num}_${2}s" $((cnt++))
114                 echo "} ${IFACE}_${2}_t;"
115                 echo
116         fi
117 }
118
119 function print_msg_defs {
120         local base msgs args k t
121         base="/protocol/interface[@name='$IFACE']/$2"
122         if exists "$base/arg"; then
123                 comment $1
124                 msgs=$(xpathv "$base/@name")
125                 for m in $msgs; do
126                         if exists "$base[@name='$m']/arg"; then
127                                 echo "typedef struct {"
128                                 args=$(xpathv "$base[@name='$m']/arg/@name")
129                                 for a in $args; do
130                                         k="$base[@name='$m']/arg[@name='$a']/@type"
131                                         t=$(xpath "string($k)")
132                                         msg_field "$t" "$a"
133                                 done
134                                 echo "} ${IFACE}_${m}_t;"
135                                 echo
136                         fi
137                 done
138         fi
139 }
140
141 function print_msg_union {
142         local base t n
143         for IFACE in $IFACES; do
144                 base="/protocol/interface[@name='$IFACE']/$1"
145                 if exists "$base"; then
146                         for r in $(xpathv "$base/@name"); do
147                                 if exists "$base[@name='$r']/arg"; then
148                                         t="${IFACE}_${r}_t"
149                                         n="${IFACE}_${r/wl_/}"
150                                         printf '\t%-50s %s;\n' "$t" "$n"
151                                 fi
152                         done
153                 fi
154         done
155 }
156
157 function print_msg_table {
158         local base size idx str
159         for IFACE in $IFACES; do
160                 base="/protocol/interface[@name='$IFACE']/$1"
161                 size="$(upper "${IFACE/wl/wl_num}_${1}s")"
162                 if isarray "$base"; then
163                         echo -e "\t[$(upper $IFACE)] (const char *[$size]) {"
164                         for r in $(xpathv "$base/@name"); do
165                                 if isarray "$base[@name='$r']"; then
166                                         idx="$(upper "${IFACE}_${r}")"
167                                         str="$(msg_array "$base[@name='$r']/arg/@type")"
168                                         printf '\t\t%-30s "%s",\n' "[$idx]" "$str"
169                                 fi
170                         done
171                         echo -e "\t},"
172                 fi
173         done
174 }
175
176 # Main
177 IFACES=$(xpathv "/protocol/interface/@name")
178
179 cat <<EOF
180 #ifndef WAYLAND_H
181 #define WAYLAND_H
182
183 #include <stdint.h>
184
185 $(banner "Common Types")
186
187 #define WL_MESSAGE_LEN 4096
188
189 typedef struct {
190         uint32_t id;
191         uint32_t len : 16;
192         uint32_t op  : 16;
193 } wl_header_t;
194
195 typedef struct {
196         uint32_t len;
197         char    *str;
198 } wl_string_t;
199
200 typedef struct {
201         uint32_t len;
202         void    *data;
203 } wl_array_t;
204
205 typedef struct {
206         uint32_t num  : 24;
207         uint32_t frac : 8;
208 } wl_fixed_t;
209
210 $(banner "Interfaces")
211
212 /* Interface Versions */
213 $(print_iface_vers)
214
215 /* Interface IDs */
216 typedef enum {
217 $(print_iface_enum)
218 } wl_interface_t;
219
220 $(for IFACE in $IFACES; do
221         banner "Interface $(upper $IFACE)"
222         echo
223         print_msg_ids  "Request IDs"       request
224         print_msg_ids  "Event IDs"         event
225         print_enums    "Enumerations"      
226         print_msg_defs "Requests Messages" request
227         print_msg_defs "Events Messages"   event
228 done)
229
230 /* Union messages */
231 typedef union {
232 $(print_msg_union request)
233 } wl_request_t;
234
235 typedef union {
236 $(print_msg_union event)
237 } wl_event_t;
238
239 $(banner "Arrays and Strings")
240
241 /* Constants */
242 #define WL_ARRAY_NONE   '-'
243 #define WL_ARRAY_STRING 's'
244 #define WL_ARRAY_ARRAY  'a'
245 #define WL_ARRAY_FD     'f'
246
247 extern const char **wl_rarray[WL_NUM_INTERFACES];
248 extern const char **wl_earray[WL_NUM_INTERFACES];
249
250 /* Request Array */
251 #ifdef WL_DEFINE_TABLES
252 const char **wl_rarray[WL_NUM_INTERFACES] = {
253 $(print_msg_table request)
254 };
255 #endif
256
257 /* Event Array */
258 #ifdef WL_DEFINE_TABLES
259 const char **wl_earray[WL_NUM_INTERFACES] = {
260 $(print_msg_table event)
261 };
262 #endif
263
264 #endif
265 EOF