1: #! /usr/bin/perl
2: #
3: # ----------------------------------------------------------------------
4: # T-Kernel 2.0 Software Package
5: #
6: # Copyright 2011 by Ken Sakamura.
7: # This software is distributed under the latest version of T-License 2.x.
8: # ----------------------------------------------------------------------
9: #
10: # Released by T-Engine Forum(http://www.t-engine.org/) at 2011/05/17.
11: # Modified by T-Engine Forum at 2014/07/14.
12: # Modified by TRON Forum(http://www.tron.org/) at 2015/06/01.
13: #
14: # ----------------------------------------------------------------------
15: #
16:
17: # mkiflib
18: #
19: # Extended SVC
20: # interface library generation script
21: #
22: #
23:
24: $usage = 'usage: mkiflib [-deps] cpu infile';
25:
26: $makedeps = 0;
27: $infile = ""; # input file
28:
29: $copyright_c = <<EndOfCopyright;
30: /*
31: *----------------------------------------------------------------------
32: * T-Kernel 2.0 Software Package
33: *
34: * Copyright 2011 by Ken Sakamura.
35: * This software is distributed under the latest version of T-License 2.x.
36: *----------------------------------------------------------------------
37: *
38: * Released by T-Engine Forum(http://www.t-engine.org/) at 2011/05/17.
39: * Modified by TRON Forum(http://www.tron.org/) at 2015/06/01.
40: *
41: *----------------------------------------------------------------------
42: */
43: EndOfCopyright
44:
45: #
46: # analyze command line parameter
47: #
48: if ( $ARGV[0] eq "-deps" ) {
49: $makedeps = 1;
50: shift(@ARGV);
51: }
52:
53: $cpu = $ARGV[0];
54: $infile = $ARGV[1];
55: if ( $cpu eq "" ) {
56: print STDERR "$usage\n";
57: exit(1);
58: }
59: if ( $infile eq "" ) {
60: print STDERR "Too few arguments\n";
61: exit(1);
62: }
63:
64: chop($infile_base = `basename $infile`);
65: @infile_elem = split(/_|\./, $infile_base);
66: $infile_base = $infile_elem[0];
67:
68: #
69: # parse definition file
70: #
71: open(IN, "$infile") || die "can not open $infile\n";
72:
73: $ignore = 1;
74: $if_h = "if${infile_base}.h";
75: $fn_h = "fn${infile_base}.h";
76: $incfile = "<${infile_base}.h>";
77:
78: while ( <IN> ) {
79:
80: # skip to definition line
81: if ( $ignore != 0 ) {
82: $ignore = 0 if ( /^(#|\/\*\*).*\bDEFINE_IFLIB\b/ );
83: next;
84: }
85:
86: chop;
87: s/^\s//; # trim space code
88:
89: next if ( /^$/ ); # skip empty line
90: next if ( /^#/ ); # skip comment line
91:
92: # input data type
93: if ( /^(\/\*\s+)*\[/ ) {
94: ( $inp ) = /\[(.*)\]/;
95: next;
96: }
97:
98: # clear input data type
99: if ( /^\*\*/ ) {
100: $inp = "";
101: next;
102: }
103:
104: # scan data
105: if ( $inp =~ /^(LIBRARY HEADER FILE)$/i ) {
106: $if_h = $_;
107: }
108: if ( $inp =~ /^(FNUMBER HEADER FILE)$/i ) {
109: $fn_h = $_;
110: }
111: if ( $inp =~ /^(INCLUDE FILE)$/i ) {
112: $incfile = $_;
113: }
114: if ( $inp =~ /^(PREFIX)$/i ) {
115: $prefix = $_;
116: }
117: if ( $inp =~ /^(SVC NO)$/i ) {
118: $svcno = $_;
119: }
120: if ( $inp =~ /^(BEGIN SYSCALLS)$/i ) {
121: s/\s+/ /g; # delete extra space code
122:
123: $syscalls[$#syscalls+1] = $_ if ( /^IMPORT/ );
124:
125: $syscalls[$#syscalls+1] = "" if ( /RESERVE_NO/ );
126:
127: if ( ( $no ) = /ALIGN_NO (0x[0-9a-zA-Z]+|[0-9]+)\b/ ) {
128: $no = oct($no) if ( $no =~ /^0/ );
129: if ( $no > 0 ) {
130: $i = $no - ($#syscalls + 1) % $no;
131: if ( $i > 1 && $i < $no ) {
132: $syscalls[$#syscalls+$i-1] = "";
133: } elsif ( $no > 1 && $#syscalls < 0 ) {
134: $syscalls[$no-2] = "";
135: }
136: }
137: }
138: if ( ( $no ) = /ORIGIN_NO (0x[0-9a-zA-Z]+|[0-9]+)\b/ ) {
139: $no = oct($no) if ( $no =~ /^0/ );
140: if ( $no > $#syscalls + 2 ) {
141: $syscalls[$no-2] = "";
142: }
143: }
144: }
145: }
146:
147: close(IN);
148:
149: if ( $#syscalls < 0 ) {
150: print stderr "There is no definition of a system call.\n";
151: exit(1);
152: }
153:
154: # ----------------------------------------------------------------------------
155: #
156: # dependency (-deps) mode
157: #
158: if ( $makedeps ) {
159: @svcsrc = ();
160:
161: for ( $i = 0; $i <= $#syscalls; $i++ ) {
162: next if ( $syscalls[$i] eq "" );
163:
164: $syscall = $syscalls[$i];
165: ( $Func, $func, $ret, @para ) = &split_func($syscall);
166:
167: $fname = $func;
168: $fname =~ tr/A-Z/a-z/; # to lower case
169:
170: print "\$(IFSRC)/$fname.S: $infile\n";
171: push(@svcsrc, "$fname.S");
172: }
173:
174: print "SRC_SVC += ".join(" ", @svcsrc)."\n" if ( @svcsrc );
175: exit(0);
176: }
177:
178: # ----------------------------------------------------------------------------
179: #
180: # generate function code definition file
181: #
182: open(FN_H, ">$ENV{'BD'}/include/sys/svc/$fn_h") || die "can not open $ENV{'BD'}/include/sys/svc/$fn_h\n";
183:
184: ### create header part ###
185: print FN_H <<EndOfFnHeader;
186: $copyright_c
187: /*
188: * Extended SVC function code
189: *
190: * (generated automatically)
191: */
192:
193: #include <sys/ssid.h>
194:
195: EndOfFnHeader
196:
197: ### generate extended SVC number ###
198: $svc = "${prefix}_SVC";
199: if ( $svcno ne "" ) {
200:
201: print FN_H <<EndOfSVCNo;
202: /*
203: * Extended SVC number
204: */
205: #ifndef ${svc}
206: #define ${svc} $svcno
207: #endif
208:
209: EndOfSVCNo
210: }
211:
212: ### generate function number ###
213: for ( $i = 0; $i <= $#syscalls; $i++ ) {
214: next if ( $syscalls[$i] eq "" );
215:
216: ( $Func, $func, $ret, @para ) = &split_func($syscalls[$i]);
217: $fno = (($i + 1) << 16) + (($#para + 1) << 8);
218: printf FN_H "#define ${prefix}_${Func}_FN\t(0x%08x | ${svc})\n", $fno;
219: }
220: print FN_H "\n";
221:
222: close(FN_H);
223:
224: # ----------------------------------------------------------------------------
225: #
226: # create header file (if*.h)
227: #
228: open(IF_H, ">$ENV{'BD'}/include/sys/svc/$if_h") || die "can not open $ENV{'BD'}/include/sys/svc/$if_h\n";
229:
230: ### generate header part ###
231: print IF_H <<EndOfIfHeader;
232: $copyright_c
233: /*
234: * Extended SVC parameter packet
235: *
236: * (generated automatically)
237: */
238:
239: #include <basic.h>
240: #include ${incfile}
241: #include <sys/str_align.h>
242: #include <sys/svc/${fn_h}>
243:
244: EndOfIfHeader
245:
246: ### generate parameter packet ###
247: for ( $i = 0; $i <= $#syscalls; $i++ ) {
248: next if ( $syscalls[$i] eq "" );
249:
250: ( $Func, $func, $ret, @para ) = &split_func($syscalls[$i]);
251:
252: # expect for void parameter
253: next if ( $#para < 0 );
254:
255: print IF_H "typedef struct {\n";
256: for ( $j = 0; $j <= $#para; $j++ ) {
257: ( $xp, $pad ) = &stack_packet($para[$j]);
258: print IF_H "\t_pad_b($pad)\n" if ( $pad > 0 );
259: print IF_H "\t$xp; _align64\n";
260: print IF_H "\t_pad_l($pad)\n" if ( $pad > 0 );
261: }
262: print IF_H "} ${prefix}_${Func}_PARA;\n\n";
263: }
264:
265: close(IF_H);
266:
267: # ----------------------------------------------------------------------------
268: #
269: # create extended SVC interface function
270: #
271:
272: for ( $i = 0; $i <= $#syscalls; $i++ ) {
273: next if ( $syscalls[$i] eq "" );
274:
275: $syscall = $syscalls[$i];
276: ( $Func, $func, $ret, @para ) = &split_func($syscall);
277:
278: $fname = $func;
279: $fname =~ tr/A-Z/a-z/; # to lower case
280:
281: # open library source file
282: open(LIB, ">sysdepend/$cpu/$fname.S") || die "can not open sysdepend/$cpu/$fname.S\n";
283:
284: print LIB <<EndOfIfLibHeader;
285: $copyright_c
286: /*
287: * T-Kernel extended SVC interface library ($cpu)
288: *
289: * (generated automatically)
290: */
291:
292: EndOfIfLibHeader
293:
294: # system dependencies
295: require("$ENV{'BD'}/etc/sysdepend/cpu/$cpu/makeifex.pl");
296: &makelibex();
297:
298: close(LIB);
299: }
300:
301: exit(0);
302:
303: # ============================================================================
304:
305: #
306: # split definition of function
307: #
308: sub split_func
309: {
310: local($syscall) = @_;
311: local($Func, $func, $ret, @para, $p);
312:
313: ( $ret, $func, $p ) =
314: ( $syscall =~ /IMPORT\s+(\w+)\s+(\w+)\s*\((.*)\)\s*;/ );
315:
316: $p =~ s/^\s*//; # trim space code
317: $p =~ s/\s*$//;
318:
319: @para = split(/\s*,\s*/, $p); # split parameters
320:
321: if ( $#para == 0 && $para[0] =~ /^void$/i ) {
322: # no params (void)
323: @para = ();
324: }
325:
326: if ( $ret =~ /^void$/i ) {
327: # return type is "void"
328: $ret = "";
329: }
330:
331: $Func = $func;
332: $Func =~ s/^b_//; # delete "b_"
333: $Func =~ tr/a-z/A-Z/; # to upper case
334:
335: return ( $Func, $func, $ret, @para );
336: }
337:
338: #
339: # split parameter
340: #
341: sub split_para
342: {
343: local($para) = @_;
344: local($type, $vname, @token);
345:
346: # get variable name
347: $vname = $para;
348: $vname =~ s/\[[^\]]*\]//g;
349: if ( $vname =~ /\(/ ) {
350: $vname =~ s/^[^\(]*\(/\(/;
351: $vname =~ y/()*/ /s;
352: $vname =~ s/^\s*//;
353: @token = split(/ +/, $vname);
354: $vname = $token[0];
355: } else {
356: $vname =~ y/*/ /s;
357: @token = split(/ +/, $vname);
358: $vname = $token[$#token];
359: }
360:
361: # get variable type
362: $type = $para;
363: $type =~ s/\b$vname\b//;
364: $type =~ s/^\s*//;
365: $type =~ s/\s*$//;
366:
367: # convert variable type from array to pointer
368: if ( $para =~ s/\[[^\]]*\]// ) {
369: $para =~ s/\b($vname)\b/(*\1)/;
370: } else {
371: if ( &isMatrix($type) ) {
372: $para =~ s/\b($vname)\b/*\1/;
373: }
374: }
375:
376: return ( $type, $vname, $para );
377: }
378:
379: #
380: # create parameter packet members
381: #
382: sub stack_packet
383: {
384: local($para) = @_;
385: local($type, $vname, $pad);
386:
387: ( $type, $vname, $para ) = &split_para($para);
388:
389: # padding size to INT
390: $pad = &isShort($type);
391:
392: return ( $para, $pad );
393: }
394:
395: #
396: # return TRUE if variable is array
397: #
398: sub isMatrix
399: {
400: local($type) = @_;
401:
402: return ( $type =~ /^(KeyMap)$/ );
403: }
404:
405: #
406: # return sizeof(INT) - sizeof(variable type)
407: #
408: sub isShort
409: {
410: local($type) = @_;
411:
412: return 24 if ( $type =~ /^(B|UB|CHAR)$/ );
413: return 16 if ( $type =~ /^(H|UH|TC|CH|TLANG|SCRIPT)$/ );
414:
415: return 0;
416: }