|
|
1.1 root 1: #!/usr/bin/perl
2:
3: if($#ARGV != 2) {
4: print <<ENDOFUSAGE;
5: Usage: $0 infile.h outhead.h outprog.c
6:
7: ENDOFUSAGE
8: exit(1);
9: }
10:
11: my ($infile, $outhead, $outc) = @ARGV;
12: open IN,'<',$infile;
13:
14: while (<IN>) {
15: $header .= $_;
16: }
17: close IN;
18:
19: my $defs='';
20: my $protos='';
21: my $functions='';
22:
23: my $count = 0;
24: my @structs = ();
25: while($header =~ m/struct\s+([^\s\r\n]*)[\s\r\n]+{([^}]*)}/gs) {
26: my($name, $def) = ($1,$2);
27: my ($packcode, $unpackcode, $size, @ints) = parse_defs($name, $def);
28: if(defined $size) {
29: $count++;
30: push @structs,"+ $name";
31: $defs .= $size;
32: $protos .= "int pack_$name\_struct(char *buf, struct $name *data);\n";
33: $protos .= "int unpack_$name\_struct(struct $name *data, char *buf);\n";
34: $functions .= "int pack_$name\_struct(char *buf, struct $name *data)\n";
35: $functions .= "{\n";
36: $functions .= "\tchar\t*p;\n";
37: if($#ints >= 0) {
38: $functions .= "\tint\t\t".join(', ',@ints).";\n";
39: }
40: $functions .="\n\tp = buf;\n";
41: $functions .= $packcode;
42: $functions .="\n\treturn((int)(p-buf));\n}\n\n";
43: $functions .= "int unpack_$name\_struct(struct $name *data, char *buf)\n";
44: $functions .= "{\n";
45: $functions .= "\tchar\t*p;\n";
46: if($#ints >= 0) {
47: $functions .= "\tint\t\t".join(', ',@ints).";\n";
48: }
49: $functions .="\n\tp = buf;\n";
50: $functions .= $unpackcode;
51: $functions .="\n\treturn((int)(p-buf));\n}\n\n";
52: }
53: else {
54: push @structs,"! $name";
55: }
56: }
57:
58: if($count) {
59: open HEAD,'>',$outhead;
60: open C,'>',$outc;
61:
62: print HEAD "/* Generated by genpack.pl from $infile on ".(scalar localtime(time))." */\n\n";
63: my $macro = uc($outhead);
64: $macro=~s/[^A-Z0-9]/_/g;
65: print HEAD '#ifndef _INCLUDED_',$macro,"\n";
66: print HEAD '#define _INCLUDED_',$macro,"\n\n";
67: print HEAD "#include \"$infile\"\n#include \"xpendian.h\"\n\n";
68: print HEAD "/* *_SIZE macros are the packed buffer size requred */\n";
69: print HEAD $defs;
70: print HEAD "\n/* Function prototypes */\n";
71: print HEAD "#if defined(__cplusplus)\nextern \"C\" {\n#endif\n";
72: print HEAD $protos;
73: print HEAD "#if defined(__cplusplus)\n}\n#endif";
74: print HEAD "\n\n";
75: print HEAD "#endif /* Do not add anything after this line! */\n";
76: close HEAD;
77:
78: open C,'>',$outc;
79: print HEAD "/* Generated by genpack.pl from $infile on ".(scalar localtime(time))." */\n\n";
80: print C "#include \"$outhead\"\n\n";
81: print C $functions;
82: print C "\n";
83: close C;
84:
85: print "$count structures read successfully\n+ indicates functions were created\n! indicates a failure\n\n";
86: print join("\n", @structs),"\n";
87: }
88: else {
89: print "No structures imported... files not created.\n";
90: }
91:
92: sub parse_defs
93: {
94: my ($sname, $defs)=@_;
95:
96: my $packcode='';
97: my $unpackcode='';
98: my %vars=();
99: my %sizes=();
100:
101: # Remove comments
102: $defs=~s|/\*.*?\*/||gs;
103: my @lines=split(/[\r\n]+/, $defs);
104: foreach my $line (@lines) {
105: my ($p, $u);
106: my @newvars;
107: my $this_size=0;
108: chomp $line;
109: next if($line =~ /^\s*$/);
110: if($line =~ m/^\s*((?:char)|(?:BYTE)|(?:INT16)|(?:WORD)|(?:INT32)|(?:DWORD)|(?:float))\s+([^\s]+)\s*;\s*$/) {
111: my ($type, $name) = ($1, $2);
112: ($p, $u, @newvars) = parse_line(\%sizes, $type, $name, 0);
113: }
114: elsif($line =~ m/^\s*struct\s+([^\s]+)\s+([^\s]+)\s*;\s*$/) {
115: my ($struct, $name) = ($1, $2);
116: ($p, $u, @newvars) = parse_line(\%sizes, $struct, $name, 1);
117: }
118: else {
119: print "Cannot parse: $line\n";
120: return();
121: }
122: if(!defined $u) {
123: return();
124: }
125: @vars{@newvars}=@newvars;
126: $packcode .= $p;
127: $unpackcode .= $u;
128: }
129: my $sizedef = '#define '.uc($sname)."_SIZE\t(";
130: foreach my $key (keys %sizes) {
131: if(defined $sizes{$key}{count} && !defined $sizes{$key}{multiplier}) {
132: if($sizes{$key}{count} == 1) {
133: $sizedef .= "$key + ";
134: }
135: else {
136: $sizedef .= "($key * $sizes{$key}{count}) + ";
137: }
138: }
139: elsif(!defined $sizes{$key}{count} && defined $sizes{$key}{multiplier}) {
140: $sizes{$key}{multiplier} = substr($sizes{$key}{multiplier}, 0, -3);
141: $sizedef .= "($key * ($sizes{$key}{multiplier})) + ";
142: }
143: elsif(defined $sizes{$key}{count} && defined $sizes{$key}{multiplier}) {
144: $sizes{$key}{multiplier} = substr($sizes{$key}{multiplier}, 0, -3);
145: $sizedef .= "($key * ($sizes{$key}{count} + $sizes{$key}{multiplier})) + ";
146: }
147: }
148: $sizedef = substr($sizedef, 0, -3) . ")\n";
149: return($packcode, $unpackcode, $sizedef, sort keys %vars);
150: }
151:
152: sub parse_line
153: {
154: my ($sizes, $type, $name, $struct) = @_;
155: my $tabs = "\t";
156: my $end = '';
157: my %vars=();
158: my $nextint='i';
159: my ($packcode, $unpackcode);
160: my $sizekey;
161:
162: if($struct) {
163: $sizekey = uc($type).'_SIZE';
164: }
165: else {
166: $sizekey = "sizeof($type)";
167: }
168: if($name =~ /\[/) { # Handle arrays!
169: while($name =~ s/\[([^\]]+)\]/;$nextint;/) {
170: my $size = $1;
171: $packcode .= $tabs."for($nextint = 0; $nextint < $size; $nextint++) {\n";
172: $unpackcode .= $tabs."for($nextint = 0; $nextint < $size; $nextint++) {\n";
173: $sizes->{$sizekey}{multiplier} .= "$size * ";
174: $end = "$tabs}\n$end";
175: $tabs .= "\t";
176: $vars{$nextint}=1;
177: $nextint=chr(ord($nextint)+1);
178: }
179: $sizes->{$sizekey}{multiplier} = substr($sizes->{$sizekey}{multiplier}, 0, -3);
180: $sizes->{$sizekey}{multiplier} .= ' + ';
181: $name =~ s/;(.);/[$1]/g;
182: }
183: else {
184: $sizes->{$sizekey}{count}++;
185: }
186: $name = "data->$name";
187: my ($p, $u) = pack_line($type, $name, $struct, $tabs);
188: $p = "$packcode$p$end";
189: $u = "$unpackcode$u$end";
190: return($p, $u, sort keys %vars);
191: }
192:
193: sub pack_line
194: {
195: my ($type, $name, $struct, $tabs)=@_;
196: my $packcode = '';
197: my $unpackcode = '';
198:
199: # ie: *(INT32)p = LE_LONG($name);
200: if(!$struct) {
201: if($type eq 'char') {
202: $packcode .= $tabs."*p = $name;\n";
203: $packcode .= $tabs."p++;\n";
204: $unpackcode .= $tabs."$name = *p;\n";
205: $unpackcode .= $tabs."p++;\n";
206: }
207: elsif($type eq 'BYTE') {
208: $packcode .= $tabs."*(BYTE *)p = $name;\n";
209: $packcode .= $tabs."p++;\n";
210: $unpackcode .= $tabs."$name = *(BYTE *)p;\n";
211: $unpackcode .= $tabs."p++;\n";
212: }
213: elsif($type eq 'INT16') {
214: $packcode .= $tabs."*(INT16 *)p = LE_SHORT($name);\n";
215: $packcode .= $tabs."p += sizeof(INT16);\n";
216: $unpackcode .= $tabs."$name = LE_SHORT(*(INT16 *)p);\n";
217: $unpackcode .= $tabs."p += sizeof(INT16);\n";
218: }
219: elsif($type eq 'WORD') {
220: $packcode .= $tabs."*(WORD *)p = LE_SHORT($name);\n";
221: $packcode .= $tabs."p += sizeof(WORD);\n";
222: $unpackcode .= $tabs."$name = LE_SHORT(*(WORD *)p);\n";
223: $unpackcode .= $tabs."p += sizeof(WORD);\n";
224: }
225: elsif($type eq 'INT32') {
226: $packcode .= $tabs."*(INT32 *)p = LE_LONG($name);\n";
227: $packcode .= $tabs."p += sizeof(INT32);\n";
228: $unpackcode .= $tabs."$name = LE_LONG(*(INT32 *)p);\n";
229: $unpackcode .= $tabs."p += sizeof(INT32);\n";
230: }
231: elsif($type eq 'DWORD') {
232: $packcode .= $tabs."*(DWORD *)p = LE_LONG($name);\n";
233: $packcode .= $tabs."p += sizeof(DWORD);\n";
234: $unpackcode .= $tabs."$name = LE_LONG(*(DWORD *)p);\n";
235: $unpackcode .= $tabs."p += sizeof(DWORD);\n";
236: }
237: elsif($type eq 'float') {
238: $packcode .= $tabs."*(DWORD *)p = LE_LONG(*((DWORD *)&($name)));\n";
239: $packcode .= $tabs."p += sizeof(float);\n";
240: $unpackcode .= $tabs."*(((DWORD *)&($name))) = LE_LONG(*(DWORD *)p);\n";
241: $unpackcode .= $tabs."p += sizeof(DWORD);\n";
242: }
243: else {
244: print "Unhandled type: $type\n";
245: return(undef, undef);
246: }
247: }
248: else {
249: $packcode .= $tabs."p += pack_$type\_struct(p, &($name));\n";
250: $unpackcode .= $tabs."p += unpack_$type\_struct(&($name), p);\n";
251: }
252:
253: return($packcode, $unpackcode);
254: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.