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