1#!/usr/local/bin/perl
2
3sub maxprefix {
4	my $p = shift(@_);
5	for (@_) {
6		chop $p until /^\Q$p/;
7	}
8	$p =~ s/_[^_]*$/_/;
9	$p = "CEC_OP_CEC_" if ($p =~ /CEC_OP_CEC_VERSION_/);
10	return $p;
11}
12
13my $cur_msg;
14
15sub process_func
16{
17	my $feature = shift;
18	my $func = shift;
19	my $func_args = $func;
20	$func =~ s/\(.*//;
21	my $msg = $func;
22	$msg =~ s/([a-z])/\U\1/g;
23	$func =~ s/cec_msg//;
24	my $opt = $func;
25	$opt =~ s/_([a-z])/\U\1/g;
26	$func_args =~ s/.*\((.*)\).*/\1/;
27	my $has_reply = $func_args =~ /^int reply/;
28	$func_args =~ s/^int reply,? ?//;
29	my $arg_names;
30	my $arg_ptrs;
31	my $name, $type, $size;
32	my $msg_dash_name, $msg_lc_name;
33	my @enum, $val;
34	my $usage;
35	my $has_digital = $func_args =~ /cec_op_digital_service_id/;
36	my $has_ui_command = $func_args =~ /cec_op_ui_command/;
37	my $has_short_aud_descr = $func_args =~ /num_descriptors/;
38
39	my @ops_args = split(/, */, $func_args);
40	if ($has_digital) {
41		$func_args =~ s/const struct cec_op_digital_service_id \*digital/uint8_t service_id_method, uint8_t dig_bcast_system, uint16_t transport_id, uint16_t service_id, uint16_t orig_network_id, uint16_t program_number, uint8_t channel_number_fmt, uint16_t major, uint16_t minor/;
42	}
43	if ($has_ui_command) {
44		$func_args =~ s/const struct cec_op_ui_command \*ui_cmd/uint8_t ui_cmd, uint8_t has_opt_arg, uint8_t play_mode, uint8_t ui_function_media, uint8_t ui_function_select_av_input, uint8_t ui_function_select_audio_input, uint8_t ui_bcast_type, uint8_t ui_snd_pres_ctl, uint8_t channel_number_fmt, uint16_t major, uint16_t minor/;
45	}
46	if ($has_short_aud_descr) {
47		$func_args =~ s/const uint32_t \*descriptors/uint8_t descriptor1, uint8_t descriptor2, uint8_t descriptor3, uint8_t descriptor4/;
48		$func_args =~ s/const uint8_t \*audio_format_id, const uint8_t \*audio_format_code/uint8_t audio_format_id1, uint8_t audio_format_code1, uint8_t audio_format_id2, uint8_t audio_format_code2, uint8_t audio_format_id3, uint8_t audio_format_code3, uint8_t audio_format_id4, uint8_t audio_format_code4/;
49	}
50	my @args = split(/, */, $func_args);
51	my $has_struct = $func_args =~ /struct/;
52	return if ($func_args =~ /__u\d+\s*\*/ || $func_args =~ /uint\d+_t\s*\*/);
53
54	my $cec_msg = $msg;
55	while ($cec_msg =~ /_/ && !exists($msgs{$cec_msg})) {
56		$cec_msg =~ s/_[^_]*$//;
57	}
58	return unless ($cec_msg =~ /_/);
59
60	my $msg_name = $cec_msg;
61	$msg_name =~ s/CEC_MSG_//;
62	$msg_dash_name = $msg;
63	$msg_dash_name =~ s/CEC_MSG_//;
64	$msg_dash_name =~ s/([A-Z])/\l\1/g;
65	$msg_dash_name =~ s/_/-/g;
66	$msg_lc_name = $msg;
67	$msg_lc_name =~ s/([A-Z])/\l\1/g;
68	$cur_msg = $msg;
69
70	if ($cec_msg eq $msg) {
71		if ($cec_msg =~ /_CDC_/ && !$cdc_case) {
72			$cdc_case = 1;
73			$logswitch .= "\tcase CEC_MSG_CDC_MESSAGE:\n";
74			$logswitch .= "\tswitch (msg->msg[4]) {\n";
75		}
76		if ($cec_msg =~ /_HTNG_/ && !$htng_case) {
77			$htng_case = 1;
78			$cdc_case = 0;
79			$std_logswitch = $logswitch;
80			$logswitch = "";
81		}
82		if ($cdc_case) {
83			$cdcmsgtable .= "\t{ $cec_msg, \"$msg_name\" },\n";
84		} elsif ($htng_case) {
85			$htngmsgtable .= "\t{ $cec_msg, \"$msg_name\" },\n";
86		} else {
87			$msgtable .= "\t{ $cec_msg, \"$msg_name\" },\n";
88		}
89		if (@args == 0) {
90			$logswitch .= "\tcase $cec_msg:\n";
91			$logswitch .= "\t\tprintf(\"$msg_name (0x%02x)\\n\", $cec_msg);\n";
92			$logswitch .= "\t\tbreak;\n\n";
93		} else {
94			$logswitch .= "\tcase $cec_msg: {\n";
95			foreach (@ops_args) {
96				($type, $name) = /(.*?) ?([a-zA-Z_]\w+)$/;
97				if ($type =~ /struct .*\*/) {
98					$type =~ s/ \*//;
99					$type =~ s/const //;
100				}
101				if ($name eq "rc_profile" || $name eq "dev_features") {
102					$logswitch .= "\t\tconst uint8_t *$name = NULL;\n";
103				} elsif ($type eq "const char *") {
104					$logswitch .= "\t\tchar $name\[16\];\n";
105				} elsif ($type eq "const uint32_t *") {
106					$logswitch .= "\t\tuint32_t $name\[4\];\n";
107				} elsif ($type eq "const uint8_t *") {
108					$logswitch .= "\t\tuint8_t $name\[4\];\n";
109				} elsif ($type =~ /struct/) {
110					$logswitch .= "\t\t$type $name = {};\n";
111				} else {
112					$logswitch .= "\t\t$type $name;\n";
113				}
114			}
115			if ($cdc_case) {
116				$logswitch .= "\t\tuint16_t phys_addr;\n";
117			}
118			my $ops_lc_name = $msg_lc_name;
119			$ops_lc_name =~ s/^cec_msg/cec_ops/;
120			$logswitch .= "\n\t\t$ops_lc_name(msg";
121			if ($cdc_case) {
122				$logswitch .= ", &phys_addr";
123			}
124			foreach (@ops_args) {
125				($type, $name) = /(.*?) ?([a-zA-Z_]\w+)$/;
126				if ($type eq "const char *" ||
127				    $type eq "const uint8_t *" ||
128				    $type eq "const uint32_t *") {
129					$logswitch .= ", $name";
130				} else {
131					$logswitch .= ", &$name";
132				}
133			}
134			$logswitch .= ");\n";
135			$logswitch .= "\t\tprintf(\"$msg_name (0x%02x):\\n\", $cec_msg);\n";
136			if ($cdc_case) {
137				$logswitch .= "\t\tlog_arg(&arg_phys_addr, \"phys-addr\", phys_addr);\n";
138			}
139			foreach (@ops_args) {
140				($type, $name) = /(.*?) ?([a-zA-Z_]\w+)$/;
141				my $dash_name = $name;
142				$dash_name =~ s/_/-/g;
143				if ($name eq "rc_profile" || $name eq "dev_features") {
144					$logswitch .= "\t\tlog_features(&arg_$name, \"$dash_name\", $name);\n";
145				} elsif ($name eq "digital") {
146					$logswitch .= "\t\tlog_digital(\"$dash_name\", &$name);\n";
147				} elsif ($name eq "ui_cmd") {
148					$logswitch .= "\t\tlog_ui_command(\"$dash_name\", &$name);\n";
149				} elsif ($name eq "rec_src") {
150					$logswitch .= "\t\tlog_rec_src(\"$dash_name\", &$name);\n";
151				} elsif ($name eq "tuner_dev_info") {
152					$logswitch .= "\t\tlog_tuner_dev_info(\"$dash_name\", &$name);\n";
153				} elsif ($name eq "descriptors") {
154					$logswitch .= "\t\tlog_descriptors(\"$dash_name\", num_descriptors, $name);\n";
155				} elsif ($name eq "audio_format_id" || $name eq "audio_format_code") {
156					$logswitch .= "\t\tlog_u8_array(\"$dash_name\", num_descriptors, $name);\n";
157				} else {
158					$logswitch .= "\t\tlog_arg(&arg_$name, \"$dash_name\", $name);\n";
159				}
160			}
161			$logswitch .= "\t\tbreak;\n\t}\n";
162		}
163	}
164	return if $has_struct;
165
166	$options .= "\tOpt$opt,\n";
167	$messages .= "\t\t$cec_msg,\n";
168	if (@args == 0) {
169		$messages .= "\t\t0, { }, { },\n";
170		$long_opts .= "\t{ \"$msg_dash_name\", no_argument, 0, Opt$opt }, \\\n";
171		$usage .= "\t\"  --" . sprintf("%-30s", $msg_dash_name) . "Send $msg_name message (\" xstr($cec_msg) \")\\n\"\n";
172		$usage_msg{$msg} = $usage;
173		$switch .= "\tcase Opt$opt: {\n";
174		$switch .= "\t\t$msg_lc_name(&msg";
175		$switch .= ", reply" if $has_reply;
176		$switch .= ");\n\t\tbreak;\n\t}\n\n";
177	} else {
178		$long_opts .= "\t{ \"$msg_dash_name\", required_argument, 0, Opt$opt }, \\\n";
179		$usage .= "\t\"  --$msg_dash_name";
180		my $prefix = "\t\"    " . sprintf("%-30s", " ");
181		my $sep = " ";
182		foreach (@args) {
183			($type, $name) = /(.*?) ?([a-zA-Z_]\w+)$/;
184			$name =~ s/_/-/g;
185			$usage .= "$sep$name=<val>";
186			$sep = ",";
187		}
188		$usage .= "\\n\"\n";
189		foreach (@args) {
190			($type, $name) = /(.*?) ?([a-zA-Z_]\w+)$/;
191			@enum = @{$types{$name}};
192			next if !scalar(@enum);
193			$name =~ s/_/-/g;
194			$usage .= $prefix . "'$name' can have these values:\\n\"\n";
195			my $common_prefix = maxprefix(@enum);
196			foreach (@enum) {
197				my $e = $_;
198				s/^$common_prefix//;
199				s/([A-Z])/\l\1/g;
200				s/_/-/g;
201				$usage .= $prefix . "    $_ (\" xstr($e) \")\\n\"\n";
202			}
203		}
204		$usage .= $prefix . "Send $msg_name message (\" xstr($cec_msg) \")\\n\"\n";
205		$usage_msg{$msg} = $usage;
206		$switch .= "\tcase Opt$opt: {\n";
207		foreach (@args) {
208			($type, $name) = /(.*?) ?([a-zA-Z_]\w+)$/;
209			if ($type =~ /char/) {
210				$switch .= "\t\tconst char *$name = \"\";\n";
211			} else {
212				$switch .= "\t\t$type $name = 0;\n";
213			}
214		}
215		$switch .= "\n\t\twhile (*subs != '\\0') {\n";
216		$switch .= "\t\t\tswitch (cec_parse_subopt(&subs, opt->arg_names, &value)) {\n";
217		my $cnt = 0;
218		foreach (@args) {
219			($type, $name) = /(.*?) ?([a-zA-Z_]\w+)$/;
220			@enum = @{$types{$name}};
221			$switch .= "\t\t\tcase $cnt:\n";
222			if ($type =~ /char/) {
223				$switch .= "\t\t\t\t$name = value;\n";
224			} elsif (scalar(@enum) || $name eq "ui_cmd") {
225				$switch .= "\t\t\t\t$name = parse_enum(value, opt->args\[$cnt\]);\n";
226			} elsif ($name =~ /audio_out_delay/ || $name =~ /video_latency/) {
227				$switch .= "\t\t\t\t$name = parse_latency(value);\n";
228			} elsif ($name =~ /phys_addr/) {
229				$switch .= "\t\t\t\t$name = cec_parse_phys_addr(value);\n";
230			} else {
231				$switch .= "\t\t\t\t$name = strtol(value, 0L, 0);\n";
232			}
233			$switch .= "\t\t\t\tbreak;\n";
234			$cnt++;
235		}
236		$switch .= "\t\t\tdefault:\n";
237		$switch .= "\t\t\t\texit(1);\n";
238		$switch .= "\t\t\t}\n\t\t}\n";
239		$switch .= "\t\t$msg_lc_name(&msg";
240		$switch .= ", reply" if $has_reply;
241		foreach (@args) {
242			($type, $name) = /(.*?) ?([a-zA-Z_]\w+)$/;
243			$switch .= ", $name";
244		}
245		$switch .= ");\n\t\tbreak;\n\t}\n\n";
246
247		foreach (@args) {
248			($type, $name) = /(.*?) ?([a-zA-Z_]\w+)$/;
249			if ($arg_names ne "") {
250				$arg_names .= ", ";
251				$arg_ptrs .= ", ";
252			}
253			$arg_ptrs .= "&arg_$name";
254			$name =~ s/_/-/g;
255			$arg_names .= '"' . $name . '"';
256		}
257		$size = $#args + 1;
258		$messages .= "\t\t$size, { $arg_names },\n";
259		$messages .= "\t\t{ $arg_ptrs },\n";
260		foreach (@args) {
261			($type, $name) = /(.*?) ?([a-zA-Z_]\w+)$/;
262			@enum = @{$types{$name}};
263			$size = scalar(@enum);
264
265			if ($size && !defined($created_enum{$name})) {
266				$created_enum{$name} = 1;
267				$enums .= "static const struct cec_arg_enum_values type_$name\[\] = {\n";
268				my $common_prefix = maxprefix(@enum);
269				foreach (@enum) {
270					$val = $_;
271					s/^$common_prefix//;
272					s/([A-Z])/\l\1/g;
273					s/_/-/g;
274					$enums .= "\t{ \"$_\", $val },\n";
275				}
276				$enums .= "};\n\n";
277			}
278			if (!defined($created_arg{$name})) {
279				$created_arg{$name} = 1;
280				if ($type eq "uint8_t" && $size) {
281					$arg_structs .= "static const struct cec_arg arg_$name = {\n";
282					$arg_structs .= "\tCEC_ARG_TYPE_ENUM, $size, type_$name\n};\n\n";
283				} elsif ($type eq "uint8_t") {
284					$arg_structs .= "#define arg_$name arg_u8\n";
285				} elsif ($type eq "uint16_t") {
286					$arg_structs .= "#define arg_$name arg_u16\n";
287				} elsif ($type eq "uint32_t") {
288					$arg_structs .= "#define arg_$name arg_u32\n";
289				} elsif ($type eq "const char *") {
290					$arg_structs .= "#define arg_$name arg_string\n";
291				}
292			}
293		}
294	}
295	$messages .= "\t\t\"$msg_name\"\n";
296	$messages .= "\t}, {\n";
297	push @{$feature_usage{$feature}}, $msg;
298}
299
300while (<>) {
301	last if /\/\* Messages \*\//;
302}
303
304$comment = 0;
305$has_also = 0;
306$operand_name = "";
307$feature = "";
308
309while (<>) {
310	chomp;
311	last if /_CEC_UAPI_FUNCS_H/;
312	if (/^\/\*.*Feature \*\/$/) {
313		($feature) = /^\/\* (.*) Feature/;
314	}
315	elsif (/^\/\*.*General Protocol Messages \*\/$/) {
316		$feature = "Abort";
317	}
318	if ($operand_name ne "" && !/^#define/) {
319		@{$types{$operand_name}} = @ops;
320		undef @ops;
321		$operand_name = "";
322	}
323	if (/\/\*.*Operand \((.*)\)/) {
324		$operand_name = $1;
325		next;
326	}
327	s/\/\*.*\*\///;
328	if ($comment) {
329		if ($has_also) {
330			if (/CEC_MSG/) {
331				($also_msg) = /(CEC_MSG\S+)/;
332				push @{$feature_also{$feature}}, $also_msg;
333				if (!exists($feature_usage{$feature})) {
334					push @{$feature_usage{$feature}}, "";
335				}
336			}
337		} elsif (/^ \* Has also:$/) {
338			$has_also = 1;
339		}
340		$has_also = 0 if (/\*\//);
341		next unless /\*\//;
342		$comment = 0;
343		s/^.*\*\///;
344	}
345	if (/\/\*/) {
346		$comment = 1;
347		$has_also = 0;
348		next;
349	}
350	next if /^\s*$/;
351	if (/^\#define/) {
352		($name, $val) = /define (\S+)\s+(\S+)/;
353		if ($name =~ /^CEC_MSG/) {
354			$msgs{$name} = 1;
355		} elsif ($operand_name ne "" && $name =~ /^CEC_OP/) {
356			push @ops, $name;
357		}
358		next;
359	}
360}
361
362while (<>) {
363	chomp;
364	if (/^\/\*.*Feature \*\/$/) {
365		($feature) = /^\/\* (.*) Feature/;
366	}
367	elsif (/^\/\*.*General Protocol Messages \*\/$/) {
368		$feature = "Abort";
369	}
370	if (/\/\* broadcast \*\//) {
371		$usage_msg{$cur_msg} =~ s/"\)\\n"$/", bcast)\\n"/;
372	}
373	s/\/\*.*\*\///;
374	if ($comment) {
375		next unless /\*\//;
376		$comment = 0;
377		s/^.*\*\///;
378	}
379	if (/\/\*/) {
380		$comment = 1;
381		next;
382	}
383	next if /^\s*$/;
384	next if /cec_msg_reply_feature_abort/;
385	next if /cec_msg_htng_init/;
386	if (/^static (__)?inline(__)? void cec_msg.*\(.*\)/) {
387		s/static\s(__)?inline(__)?\svoid\s//;
388		s/struct cec_msg \*msg, //;
389		s/struct cec_msg \*msg//;
390		process_func($feature, $_);
391		next;
392	}
393	if (/^static (__)?inline(__)? void cec_msg/) {
394		$func = $_;
395		next;
396	}
397	if ($func ne "") {
398		$func .= $_;
399		next unless /\)$/;
400		$func =~ s/\s+/ /g;
401		$func =~ s/static\s(__)?inline(__)?\svoid\s//;
402		$func =~ s/struct cec_msg \*msg, //;
403		$func =~ s/struct cec_msg \*msg//;
404		process_func($feature, $func);
405		$func = "";
406	}
407}
408
409$options .= "\tOptHelpAll,\n";
410
411open(my $fh, '>', 'cec-parse-src-gen.h') or die "Could not open cec-parse-src-gen.h for writing";
412
413print $fh "\n\n";
414foreach (sort keys %feature_usage) {
415	$name = $_;
416	s/ /_/g;
417	s/([A-Z])/\l\1/g;
418	$usage_var = $_ . "_usage";
419	printf $fh "static const char *$usage_var =\n";
420	$usage = "";
421	foreach (@{$feature_usage{$name}}) {
422		$usage .= $usage_msg{$_};
423	}
424	foreach (@{$feature_also{$name}}) {
425		$usage .= $usage_msg{$_};
426	}
427	chop $usage;
428	$usage =~ s/"  --vendor-remote-button-up/VENDOR_EXTRA\n\t"  --vendor-remote-button-up/;
429	printf $fh "%s;\n\n", $usage;
430	s/_/-/g;
431	$opt = "OptHelp" . $name;
432	$opt =~ s/ //g;
433	$help .= "\tif (options[OptHelpAll] || options\[$opt\]) {\n";
434	$help .= "\t\tprintf(\"$name Feature:\\n\\n\");\n";
435	$help .= "\t\tprintf(\"\%s\\n\", $usage_var);\n\t}\n";
436}
437
438printf $fh "void cec_parse_usage_options(const char *options)\n{\n";
439printf $fh "%s}\n\n", $help;
440printf $fh "void cec_parse_msg_args(struct cec_msg &msg, int reply, const cec_msg_args *opt, int ch)\n{\n";
441printf $fh "\tchar *value, *subs = optarg;\n\n";
442printf $fh "\tswitch (ch) {\n";
443$switch =~ s/(service_id_method, dig_bcast_system, transport_id, service_id, orig_network_id, program_number, channel_number_fmt, major, minor)/args2digital_service_id(\1)/g;
444$switch =~ s/(ui_cmd, has_opt_arg, play_mode, ui_function_media, ui_function_select_av_input, ui_function_select_audio_input, ui_bcast_type, ui_snd_pres_ctl, channel_number_fmt, major, minor)/args2ui_command(\1)/g;
445$switch =~ s/(descriptor1, descriptor2, descriptor3, descriptor4)/args2short_descrs(\1)/g;
446$switch =~ s/(audio_format_id1, audio_format_code1, audio_format_id2, audio_format_code2, audio_format_id3, audio_format_code3, audio_format_id4, audio_format_code4)/args2short_aud_fmt_ids(audio_format_id1, audio_format_id2, audio_format_id3, audio_format_id4), args2short_aud_fmt_codes(audio_format_code1, audio_format_code2, audio_format_code3, audio_format_code4)/g;
447printf $fh "%s", $switch;
448printf $fh "\t}\n};\n\n";
449close $fh;
450
451open(my $fh, '>', 'cec-parse-gen.h') or die "Could not open cec-parse-gen.h for writing";
452foreach (sort keys %feature_usage) {
453	$name = $_;
454	s/ /-/g;
455	s/([A-Z])/\l\1/g;
456	$help_features .= sprintf("\t\"  --help-%-28s Show help for the $name feature\\n\" \\\n", $_);
457	$opt = "OptHelp" . $name;
458	$opt =~ s/ //g;
459	$options .= "\t$opt,\n";
460	$long_opts .= "\t{ \"help-$_\", no_argument, 0, $opt }, \\\n";
461}
462print $fh "enum cec_parse_options {\n\tOptMessages = 255,\n";
463printf $fh "%s\n\tOptLast = 512\n};\n\n", $options;
464
465printf $fh "#define CEC_PARSE_LONG_OPTS \\\n%s\n\n", $long_opts;
466printf $fh "#define CEC_PARSE_USAGE \\\n%s\n\n", $help_features;
467close $fh;
468
469open(my $fh, '>', 'cec-log-gen.h') or die "Could not open cec-log-gen.h for writing";
470printf $fh "%s%s\n", $enums, $arg_structs;
471printf $fh "static const struct cec_msg_args messages[] = {\n\t{\n";
472printf $fh "%s\t}\n};\n\n", $messages;
473
474print $fh <<'EOF';
475void cec_log_msg(const struct cec_msg *msg)
476{
477	if (msg->len == 1) {
478		printf("POLL\n");
479		goto status;
480	}
481
482	switch (msg->msg[1]) {
483EOF
484printf $fh "%s", $std_logswitch;
485print $fh <<'EOF';
486	default:
487		log_unknown_msg(msg);
488		break;
489	}
490	break;
491
492	default:
493		log_unknown_msg(msg);
494		break;
495	}
496
497status:
498	if ((msg->tx_status && !(msg->tx_status & CEC_TX_STATUS_OK)) ||
499	    (msg->rx_status && !(msg->rx_status & (CEC_RX_STATUS_OK | CEC_RX_STATUS_FEATURE_ABORT))))
500		printf("\t%s\n", cec_status2s(*msg).c_str());
501}
502
503void log_htng_msg(const struct cec_msg *msg)
504{
505	if ((msg->tx_status && !(msg->tx_status & CEC_TX_STATUS_OK)) ||
506	    (msg->rx_status && !(msg->rx_status & (CEC_RX_STATUS_OK | CEC_RX_STATUS_FEATURE_ABORT))))
507		printf("\t%s\n", cec_status2s(*msg).c_str());
508
509	if (msg->len < 6)
510		return;
511
512	switch (msg->msg[5]) {
513EOF
514printf $fh "%s", $logswitch;
515print $fh <<'EOF';
516	default:
517		log_htng_unknown_msg(msg);
518		break;
519	}
520}
521EOF
522close $fh;
523
524open(my $fh, '>', 'cec-msgs-gen.h') or die "Could not open cec-msgs-gen.h for writing";
525printf $fh "struct msgtable {\n";
526printf $fh "\tuint8_t opcode;\n";
527printf $fh "\tconst char *name;\n";
528printf $fh "};\n\n";
529printf $fh "static const struct msgtable msgtable[] = {\n";
530printf $fh "%s", $msgtable;
531printf $fh "\t{ CEC_MSG_VENDOR_COMMAND, \"VENDOR_COMMAND\" },\n";
532printf $fh "\t{ CEC_MSG_VENDOR_COMMAND_WITH_ID, \"VENDOR_COMMAND_WITH_ID\" },\n";
533printf $fh "\t{ CEC_MSG_VENDOR_REMOTE_BUTTON_DOWN, \"VENDOR_REMOTE_BUTTON_DOWN\" },\n";
534printf $fh "\t{ CEC_MSG_CDC_MESSAGE, \"CDC_MESSAGE\" },\n";
535printf $fh "};\n\n";
536printf $fh "static const struct msgtable cdcmsgtable[] = {\n";
537printf $fh "%s", $cdcmsgtable;
538printf $fh "};\n\n";
539printf $fh "static const struct msgtable htngmsgtable[] = {\n";
540printf $fh "%s", $htngmsgtable;
541printf $fh "};\n";
542close $fh;
543