3 # This file is Copyright (c) 2010 by the GPSD project
4 # BSD terms apply: see the file COPYING in the distribution root for details.
6 # Never hand-hack what you can generate...
8 # This code generates template declarations for AIS-JSON parsing from a
9 # declarative specification of a JSON structure - and generates those
10 # declarative specification from the Python format strings for
11 # dumping the structures
16 # Here is the information that makes it all work - attribute, type, and
17 # defult information for all fields. We can generate either a JSON
18 # parser template spec or the C code for the correspondong dump functio
19 # from this information. Doing it this way guarantees consistency.
23 "initname" : "json_ais1",
24 "header": "\tAIS_HEADER,",
25 "structname": "ais->type1",
27 # fieldname type default
28 ('status', 'uinteger', '0'),
29 ('turn', 'integer', 'AIS_TURN_NOT_AVAILABLE'),
30 ('speed', 'uinteger', 'AIS_SPEED_NOT_AVAILABLE'),
31 ('accuracy', 'boolean', 'false'),
32 ('lon', 'integer', 'AIS_LON_NOT_AVAILABLE'),
33 ('lat', 'integer', 'AIS_LAT_NOT_AVAILABLE'),
34 ('course', 'uinteger', 'AIS_COURSE_NOT_AVAILABLE'),
35 ('heading', 'uinteger', 'AIS_HEADING_NOT_AVAILABLE'),
36 ('second', 'uinteger', 'AIS_SEC_NOT_AVAILABLE'),
37 ('maneuver', 'uinteger', 'AIS_SEC_INOPERATIVE'),
38 ('raim', 'boolean', 'false'),
39 ('radio', 'uinteger', '0'),
42 # Message types 2 and 3 duplicate 1
44 "initname" : "json_ais4",
45 "header": "\tAIS_HEADER,",
46 "structname": "ais->type4",
48 # fieldname type default
49 ('timestamp', 'string', None),
50 ('accuracy', 'boolean', "true"),
51 ('lon', 'integer', "AIS_LON_NOT_AVAILABLE"),
52 ('lat', 'integer', "AIS_LAT_NOT_AVAILABLE"),
53 ('epfd', 'uinteger', "0"),
54 ('raim', 'boolean', "false"),
55 ('radio', 'uinteger', "0"),
57 "stringbuffered":("timestamp",),
60 "initname" : "json_ais5",
61 "header": "\tAIS_HEADER,",
62 "structname": "ais->type5",
64 # fieldname type default
65 ('imo', 'uinteger', '0'),
66 ('ais_version', 'uinteger', '0'),
67 ('callsign', 'string', None),
68 ('shipname', 'string', None),
69 ('shiptype', 'uinteger', '0'),
70 ('to_bow', 'uinteger', '0'),
71 ('to_stern', 'uinteger', '0'),
72 ('to_port', 'uinteger', '0'),
73 ('to_starboard', 'uinteger', '0'),
74 ('epfd', 'uinteger', '0'),
75 ('eta', 'string', None),
76 ('draught', 'uinteger', '0'),
77 ('destination', 'string', None),
78 ('dte', 'uinteger', '1'),
80 "stringbuffered":("eta",),
83 "initname" : "json_ais6",
84 "header": "\tAIS_HEADER,",
85 "structname": "ais->type6",
87 # fieldname type default
88 ('seqno', 'uinteger', '0'),
89 ('dest_mmsi', 'uinteger', '0'),
90 ('retransmit', 'boolean', 'false'),
91 ('dac', 'uinteger', '0'),
92 ('fid', 'uinteger', '0'),
93 ('data', 'string', None),
95 "stringbuffered":("data",),
98 "initname" : "json_ais7",
99 "header": "\tAIS_HEADER,",
100 "structname": "ais->type7",
102 # fieldname type default
103 ('mmsi1', 'uinteger', '0'),
104 ('mmsi2', 'uinteger', '0'),
105 ('mmsi3', 'uinteger', '0'),
106 ('mmsi4', 'uinteger', '0'),
110 "initname" : "json_ais8",
111 "header": "\tAIS_HEADER,",
112 "structname": "ais->type8",
114 # fieldname type default
115 ('dac', 'uinteger', '0'),
116 ('fid', 'uinteger', '0'),
117 ('data', 'string', None),
119 "stringbuffered":("data",),
122 "initname" : "json_ais9",
123 "header": "\tAIS_HEADER,",
124 "structname": "ais->type9",
126 # fieldname type default
127 ('alt', 'uinteger', 'AIS_ALT_NOT_AVAILABLE'),
128 ('speed', 'uinteger', 'AIS_SPEED_NOT_AVAILABLE'),
129 ('accuracy', 'boolean', 'false'),
130 ('lon', 'integer', 'AIS_LON_NOT_AVAILABLE'),
131 ('lat', 'integer', 'AIS_LAT_NOT_AVAILABLE'),
132 ('course', 'uinteger', 'AIS_COURSE_NOT_AVAILABLE'),
133 ('second', 'uinteger', 'AIS_SEC_NOT_AVAILABLE'),
134 ('regional', 'uinteger', '0'),
135 ('dte', 'uinteger', '1'),
136 ('raim', 'boolean', 'false'),
137 ('radio', 'uinteger', '0'),
141 "initname" : "json_ais10",
142 "header": "\tAIS_HEADER,",
143 "structname": "ais->type10",
145 # fieldname type default
146 ('dest_mmsi', 'uinteger', '0'),
149 # Message type 11 duplicates 4
151 "initname" : "json_ais12",
152 "header": "\tAIS_HEADER,",
153 "structname": "ais->type12",
155 # fieldname type default
156 ('seqno', 'uinteger', '0'),
157 ('dest_mmsi', 'uinteger', '0'),
158 ('retransmit', 'boolean', '0'),
159 ('text', 'string', None),
162 # Message type 13 duplicates 7
164 "initname" : "json_ais14",
165 "header": "\tAIS_HEADER,",
166 "structname": "ais->type14",
168 # fieldname type default
169 ('text', 'string', None),
173 "initname" : "json_ais15",
174 "header": "\tAIS_HEADER,",
175 "structname": "ais->type15",
177 # fieldname type default
178 ('mmsi1', 'uinteger', '0'),
179 ('type1_1', 'uinteger', '0'),
180 ('offset1_1', 'uinteger', '0'),
181 ('type1_2', 'uinteger', '0'),
182 ('offset1_2', 'uinteger', '0'),
183 ('mmsi2', 'uinteger', '0'),
184 ('type2_1', 'uinteger', '0'),
185 ('offset2_1', 'uinteger', '0'),
189 "initname" : "json_ais16",
190 "header": "\tAIS_HEADER,",
191 "structname": "ais->type16",
193 # fieldname type default
194 ('mmsi1', 'uinteger', '0'),
195 ('offset1', 'uinteger', '0'),
196 ('increment1', 'uinteger', '0'),
197 ('mmsi2', 'uinteger', '0'),
198 ('offset2', 'uinteger', '0'),
199 ('increment2', 'uinteger', '0'),
203 "initname" : "json_ais17",
204 "header": "\tAIS_HEADER,",
205 "structname": "ais->type17",
207 # fieldname type default
208 ('lon', 'integer', 'AIS_GNS_LON_NOT_AVAILABLE'),
209 ('lat', 'integer', 'AIS_GNS_LAT_NOT_AVAILABLE'),
210 ('data', 'string', None),
212 "stringbuffered":("data",),
215 "initname" : "json_ais18",
216 "header": "\tAIS_HEADER,",
217 "structname": "ais->type18",
219 # fieldname type default
220 ('reserved', 'uinteger', '0'),
221 ('speed', 'uinteger', 'AIS_SPEED_NOT_AVAILABLE'),
222 ('accuracy', 'boolean', 'false'),
223 ('lon', 'integer', 'AIS_LON_NOT_AVAILABLE'),
224 ('lat', 'integer', 'AIS_LAT_NOT_AVAILABLE'),
225 ('course', 'uinteger', 'AIS_COURSE_NOT_AVAILABLE'),
226 ('heading', 'uinteger', 'AIS_HEADING_NOT_AVAILABLE'),
227 ('second', 'uinteger', 'AIS_SEC_NOT_AVAILABLE'),
228 ('regional', 'uinteger', '0'),
229 ('cs', 'boolean', 'false'),
230 ('display', 'boolean', 'false'),
231 ('dsc', 'boolean', 'false'),
232 ('band', 'boolean', 'false'),
233 ('msg22', 'boolean', 'false'),
234 ('raim', 'boolean', 'false'),
235 ('radio', 'uinteger', '0'),
239 "initname" : "json_ais19",
240 "header": "\tAIS_HEADER,",
241 "structname": "ais->type19",
243 # fieldname type default
244 ('reserved', 'uinteger', '0'),
245 ('speed', 'uinteger', 'AIS_SPEED_NOT_AVAILABLE'),
246 ('accuracy', 'boolean', 'false'),
247 ('lon', 'integer', 'AIS_LON_NOT_AVAILABLE'),
248 ('lat', 'integer', 'AIS_LAT_NOT_AVAILABLE'),
249 ('course', 'uinteger', 'AIS_COURSE_NOT_AVAILABLE'),
250 ('heading', 'uinteger', 'AIS_HEADING_NOT_AVAILABLE'),
251 ('second', 'uinteger', 'AIS_SEC_NOT_AVAILABLE'),
252 ('regional', 'uinteger', '0'),
253 ('shipname', 'string', None),
254 ('shiptype', 'uinteger', '0'),
255 ('to_bow', 'uinteger', '0'),
256 ('to_stern', 'uinteger', '0'),
257 ('to_port', 'uinteger', '0'),
258 ('to_starboard', 'uinteger', '0'),
259 ('epfd', 'uinteger', '0'),
260 ('raim', 'boolean', 'false'),
261 ('dte', 'uinteger', '1'),
262 ('assigned', 'boolean', 'false'),
266 "initname" : "json_ais20",
267 "header": "\tAIS_HEADER,",
268 "structname": "ais->type20",
270 # fieldname type default
271 ('offset1', 'uinteger', '0'),
272 ('number1', 'uinteger', '0'),
273 ('timeout1', 'uinteger', '0'),
274 ('increment1', 'uinteger', '0'),
275 ('offset2', 'uinteger', '0'),
276 ('number2', 'uinteger', '0'),
277 ('timeout2', 'uinteger', '0'),
278 ('increment2', 'uinteger', '0'),
279 ('offset3', 'uinteger', '0'),
280 ('number3', 'uinteger', '0'),
281 ('timeout3', 'uinteger', '0'),
282 ('increment3', 'uinteger', '0'),
283 ('offset4', 'uinteger', '0'),
284 ('number4', 'uinteger', '0'),
285 ('timeout4', 'uinteger', '0'),
286 ('increment4', 'uinteger', '0'),
290 "initname" : "json_ais21",
291 "header": "\tAIS_HEADER,",
292 "structname": "ais->type21",
294 # fieldname type default
295 ('aid_type', 'uinteger', '0'),
296 ('name', 'string', None),
297 ('accuracy', 'boolean', 'false'),
298 ('lon', 'integer', 'AIS_LON_NOT_AVAILABLE'),
299 ('lat', 'integer', 'AIS_LAT_NOT_AVAILABLE'),
300 ('to_bow', 'uinteger', '0'),
301 ('to_stern', 'uinteger', '0'),
302 ('to_port', 'uinteger', '0'),
303 ('to_starboard', 'uinteger', '0'),
304 ('epfd', 'uinteger', '0'),
305 ('second', 'uinteger', '0'),
306 ('regional', 'uinteger', '0'),
307 ('off_position', 'boolean', 'false'),
308 ('raim', 'boolean', 'false'),
309 ('virtual_aid', 'boolean', 'false'),
313 "initname" : "json_ais22",
314 "header": "\tAIS_HEADER,",
315 "structname": "ais->type22",
317 # fieldname type default
318 ('channel_a', 'uinteger', '0'),
319 ('channel_b', 'uinteger', '0'),
320 ('txrx', 'uinteger', '0'),
321 ('power', 'boolean', 'false'),
322 ('area.ne_lon', 'integer', 'AIS_GNS_LON_NOT_AVAILABLE'),
323 ('area.ne_lat', 'integer', 'AIS_GNS_LAT_NOT_AVAILABLE'),
324 ('area.sw_lon', 'integer', 'AIS_GNS_LON_NOT_AVAILABLE'),
325 ('area.sw_lat', 'integer', 'AIS_GNS_LAT_NOT_AVAILABLE'),
326 ('mmsi.dest1', 'uinteger', '0'),
327 ('mmsi.dest2', 'uinteger', '0'),
328 ('addressed', 'boolean', 'false'),
329 ('band_a', 'boolean', 'false'),
330 ('band_b', 'boolean', 'false'),
331 ('zonesize', 'uinteger', '0'),
335 "initname" : "json_ais23",
336 "header": "\tAIS_HEADER,",
337 "structname": "ais->type23",
339 # fieldname type default
340 ('ne_lon', 'integer', 'AIS_GNS_LON_NOT_AVAILABLE'),
341 ('ne_lat', 'integer', 'AIS_GNS_LAT_NOT_AVAILABLE'),
342 ('sw_lon', 'integer', 'AIS_GNS_LON_NOT_AVAILABLE'),
343 ('sw_lat', 'integer', 'AIS_GNS_LAT_NOT_AVAILABLE'),
344 ('stationtype', 'uinteger', '0'),
345 ('shiptype', 'uinteger', '0'),
346 ('txrx', 'uinteger', '0'),
347 ('interval', 'uinteger', '0'),
348 ('quiet', 'uinteger', '0'),
352 "initname" : "json_ais24",
353 "header": "\tAIS_HEADER,",
354 "structname": "ais->type24",
356 # fieldname type default
357 ('shipname', 'string', None), # Part A
358 ('shiptype', 'uinteger', '0'), # Part B
359 ('vendorid', 'string', None), # Part B
360 ('callsign', 'string', None), # Part B
361 ('mothership_mmsi', 'uinteger', '0'), # Part B
362 ('dim.to_bow', 'uinteger', '0'), # Part B
363 ('dim.to_stern', 'uinteger', '0'), # Part B
364 ('dim.to_port', 'uinteger', '0'), # Part B
365 ('dim.to_starboard', 'uinteger', '0'), # Part B
369 "initname" : "json_ais25",
370 "header": "\tAIS_HEADER,",
371 "structname": "ais->type25",
373 # fieldname type default
374 ('addressed', 'boolean', 'false'),
375 ('structured', 'boolean', 'false'),
376 ('dest_mmsi', 'uinteger', '0'),
377 ('app_id', 'uinteger', '0'),
378 ('data', 'string', None),
380 "stringbuffered":("data",),
383 "initname" : "json_ais26",
384 "header": "\tAIS_HEADER,",
385 "structname": "ais->type26",
387 # fieldname type default
388 ('addressed', 'boolean', 'false'),
389 ('structured', 'boolean', 'false'),
390 ('dest_mmsi', 'uinteger', '0'),
391 ('app_id', 'uinteger', '0'),
392 ('data', 'string', None),
393 ('radio', 'uinteger', '0'),
395 "stringbuffered":("data",),
400 # Give this global the string spec you need to convert with -g
401 # We do it this mildly odd way only because passing Python multiline
402 # string literals on the command line is inconvenient.
405 # You should not need to modify anything below this line.
410 for (attr, itype, default) in spec["fieldmap"]:
411 if attr in spec.get("stringbuffered", []):
412 if attr not in outboard:
413 report += " char %s[JSON_VAL_MAX+1];\n" % attr
414 outboard.append(attr)
415 report += " const struct json_attr_t %s[] = {\n" % spec["initname"]
417 report += spec["header"] + "\n"
418 for (attr, itype, default) in spec["fieldmap"]:
419 structname = spec["structname"]
420 if itype == "string":
424 if attr in spec.get("stringbuffered", []):
427 target = structname + "." + attr
429 attr = attr[attr.rfind(".")+1:]
430 report += '\t{"%s",%st_%s,%s.addr.%s = %s%s,\n' % \
431 (attr, " "*(14-len(attr)), itype, " "*(10-len(itype)), itype, deref, target)
433 if itype == "string":
434 report += leader + ".len = sizeof(%s)},\n" % target
436 report += leader + ".dflt.%s = %s},\n" % (itype, default)
444 # No code for generating dump functions yet.
445 # When we do this, remembeer that we have to suppress dump function
446 # generation from any spec with a union dot in the field names;
447 # those will have to be coded by hand.
449 def string_to_specifier(strspec):
450 "Compile a Python-style format string to an attribute-type fieldmap."
451 # Map C and Python-type format letters to JSON parser datatypes
456 "s": "boolean", # Only booleans print as unquoted strings
466 strspec = strspec.strip()
467 if strspec[-1] == "}":
468 strspec = strspec[:-1]
470 print "Missing terminating }"
472 print ' "fieldmap":('
473 for item in strspec.split(","):
474 itype = fmtmap[item[-1]]
475 attr = item[:item.find(":")]
483 print " ('%s',%s'%s',%s%s)," % (attr, " "*(14-len(attr)), itype, " "*(14-len(itype)), dflt)
487 if __name__ == '__main__':
489 # The --ais and --target= options are (required) placeho;lders.
490 # In the future, this script will generate more different kinds
492 (options, arguments) = getopt.getopt(sys.argv[1:], "g", ["ais", "target="])
493 except getopt.GetoptError, msg:
494 print "jsongen.py: " + str(msg)
500 for (switch, val) in options:
503 elif switch == '--ais':
505 elif switch == '--target':
508 if not specify and (not target or not spec):
509 print "jsongen.py: must specify type and target."
514 string_to_specifier(stringspec)
517 * This is code generated by jsongen.py. Do not hand-hack it!
520 /*@ -fullinitblock */
524 for description in spec:
525 generate(description)
527 /*@ +fullinitblock */
529 /* Generated code ends. */
531 # The following sets edit modes for GNU EMACS