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: # mktksvc
18: #
19: # T-Kernel system call
20: # interface library generation script
21: #
22: #
23:
24: $usage = 'usage: mktksvc [-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: #
65: # parse definition file
66: #
67: open(IN, "$infile") || die "can not open $infile\n";
68:
69: $ignore = 1;
70: $tb_h = "tksvctbl.h";
71: $fn_h = "tkfncd.h";
72:
73: while ( <IN> ) {
74:
75: # skip to definition line
76: if ( $ignore != 0 ) {
77: $ignore = 0 if ( /^(#|\/\*\*).*\bDEFINE_TKSVC\b/ );
78: next;
79: }
80:
81: chop;
82: s/^\s//; # trim space code
83:
84: next if ( /^$/ ); # skip empty line
85: next if ( /^#/ ); # skip comment line
86:
87: # input data type
88: if ( /^(\/\*\s+)*\[/ ) {
89: ( $inp ) = /\[(.*)\]/;
90: next;
91: }
92:
93: # clear input data type
94: if ( /^\*\*/ ) {
95: $inp = "";
96: next;
97: }
98:
99: # scan data
100: if ( $inp =~ /^(BRANCH TABLE FILE)$/i ) {
101: $tb_h = $_;
102: }
103: if ( $inp =~ /^(FNUMBER HEADER FILE)$/i ) {
104: $fn_h = $_;
105: }
106: if ( $inp =~ /^(BEGIN SYSCALLS)$/i ) {
107: s/\s+/ /g; # delete extra space code
108:
109: $syscalls[$#syscalls+1] = $_ if ( /^IMPORT/ );
110:
111: $syscalls[$#syscalls+1] = "" if ( /RESERVE_NO/ );
112:
113: if ( ( $align ) = /ALIGN_NO (0x[0-9a-zA-Z]+|[0-9]+)\b/ ) {
114: $align = oct($align) if ( $align =~ /^0/ );
115: if ( $align > 0 ) {
116: $i = $align - ($#syscalls + 1) % $align;
117: if ( $i > 1 && $i < $align ) {
118: $syscalls[$#syscalls+$i-1] = "";
119: } elsif ( $align > 1 && $#syscalls < 0 ) {
120: $syscalls[$align-2] = "";
121: }
122: }
123: }
124: }
125: }
126:
127: close(IN);
128:
129: if ( $#syscalls < 0 ) {
130: print stderr "There is no definition of a system call.\n";
131: exit(1);
132: }
133:
134: # ----------------------------------------------------------------------------
135: #
136: # dependency (-deps) mode
137: #
138: if ( $makedeps ) {
139: @svcsrc = ();
140:
141: for ( $i = 0; $i <= $#syscalls; $i++ ) {
142: next if ( $syscalls[$i] eq "" );
143:
144: $syscall = $syscalls[$i];
145: ( $Func, $func, $ret, @para ) = &split_func($syscall);
146:
147: $fname = $func;
148: $fname =~ tr/A-Z/a-z/; # to lower case
149:
150: print "\$(IFSRC)/$fname.S: $infile\n";
151: push(@svcsrc, "$fname.S");
152: }
153:
154: print "SRC_SVC += ".join(" ", @svcsrc)."\n" if ( @svcsrc );
155: exit(0);
156: }
157:
158: # ----------------------------------------------------------------------------
159: #
160: # generate function code definition file
161: #
162: open(FN_H, ">$ENV{'BD'}/include/sys/svc/$fn_h") || die "can not open $ENV{'BD'}/include/sys/svc/$fn_h\n";
163:
164: ### create header part ###
165: print FN_H <<EndOfFnHeader;
166: $copyright_c
167: /*
168: * T-Kernel function code
169: */
170:
171: EndOfFnHeader
172:
173: ### create function code ###
174: for ( $i = 0; $i <= $#syscalls; $i++ ) {
175: next if ( $syscalls[$i] eq "" );
176:
177: ( $Func, $func, $ret, @para ) = &split_func($syscalls[$i]);
178: $psz = ¶_size(@para);
179: $fno = ((($i + 1) << 16) + ($psz << 8)) | 0x80000000;
180: printf FN_H "#define TFN_${Func}\t0x%08x\n", $fno;
181: }
182: print FN_H "\n";
183:
184: close(FN_H);
185:
186: # ----------------------------------------------------------------------------
187: #
188: # generate branch table
189: #
190: open(TB_H, ">$ENV{'BD'}/include/sys/svc/$tb_h") || die "can not open $ENV{'BD'}/include/sys/svc/$tb_h\n";
191:
192: ### create header part ###
193: print TB_H <<EndOfTbHeader;
194: $copyright_c
195: /*
196: * T-Kernel system call branch table
197: *
198: * (generated automatically)
199: */
200:
201: #include <machine.h>
202:
203: #define _SVC_ENTRY(name) .int Csym(_##name)
204:
205: EndOfTbHeader
206:
207: # number of system call
208: printf TB_H "#define N_TFN %d\n", $#syscalls + 1;
209: printf TB_H "\n";
210:
211: ### create branch table ###
212: for ( $i = 0; $i <= $#syscalls; $i++ ) {
213: if ( $syscalls[$i] eq "" ) {
214: printf TB_H "\t_SVC_ENTRY(no_support)\n";
215: } else {
216: ( $Func, $func, $ret, @para ) = &split_func($syscalls[$i]);
217: print TB_H "\t_SVC_ENTRY(${func})\n";
218: }
219: }
220:
221: close(TB_H);
222:
223: # ----------------------------------------------------------------------------
224: #
225: # create SVC interface function
226: #
227:
228: for ( $i = 0; $i <= $#syscalls; $i++ ) {
229: next if ( $syscalls[$i] eq "" );
230:
231: $syscall = $syscalls[$i];
232: ( $Func, $func, $ret, @para ) = &split_func($syscall);
233:
234: $fname = $func;
235: $fname =~ tr/A-Z/a-z/; # to lower case
236:
237: # open library source file
238: open(LIB, ">sysdepend/$cpu/$fname.S") || die "can not open sysdepend/$cpu/$fname.S\n";
239:
240: print LIB <<EndOfIfLibHeader;
241: $copyright_c
242: /*
243: * T-Kernel SVC interface library ($cpu)
244: *
245: * (generated automatically)
246: */
247:
248: EndOfIfLibHeader
249:
250: # system dependencies
251: require("$ENV{'BD'}/etc/sysdepend/cpu/$cpu/makeiftk.pl");
252: &makelib();
253:
254: close(LIB);
255: }
256:
257: exit(0);
258:
259: # ============================================================================
260:
261: #
262: # split definition of function
263: #
264: sub split_func
265: {
266: local($syscall) = @_;
267: local($Func, $func, $ret, @para, $p);
268:
269: ( $ret, $func, $p ) =
270: ( $syscall =~ /IMPORT\s+(\w+)\s+(\w+)\s*\((.*)\)\s*;/ );
271:
272: $p =~ s/^\s*//; # trim space code
273: $p =~ s/\s*$//;
274:
275: @para = split(/\s*,\s*/, $p); # split parameters
276:
277: if ( $#para == 0 && $para[0] =~ /^void$/i ) {
278: # no params (void)
279: @para = ();
280: }
281:
282: if ( $ret =~ /^void$/i ) {
283: # return type is "void"
284: $ret = "";
285: }
286:
287: $Func = $func;
288: $Func =~ s/^tk_//; # delete "tk_"
289: $Func =~ tr/a-z/A-Z/; # to upper case
290:
291: return ( $Func, $func, $ret, @para );
292: }
293:
294: #
295: # Split the argument definition to type and variable name
296: #
297: sub split_para
298: {
299: local($para) = @_;
300: local($type, $vname, $pt, @token);
301:
302: # Obtain variable name
303: $vname = $para;
304: $vname =~ s/\[[^\]]*\]//g;
305: if ( $vname =~ /\(/ ) {
306: $vname =~ s/^[^\(]*\(/\(/;
307: $vname =~ y/()*/ /s;
308: $vname =~ s/^\s*//;
309: @token = split(/ +/, $vname);
310: $vname = $token[0];
311: } else {
312: $vname =~ y/*/ /s;
313: @token = split(/ +/, $vname);
314: $vname = $token[$#token];
315: }
316:
317: # Obtain type
318: $type = $para;
319: $type =~ s/\b$vname\b//;
320: $type =~ s/^\s*//;
321: $type =~ s/\s*$//;
322:
323: return ( $type, $vname );
324: }
325:
326: #
327: # Calculate the total size (in words) of arguments
328: #
329: sub para_size
330: {
331: local(@para) = @_;
332: local($type, $vname, $i, $c);
333:
334: $c = 0;
335: for ( $i = 0; $i <= $#para; $i++ ) {
336: ( $type, $vname ) = &split_para($para[$i]);
337:
338: if ( isLongLong($type) ) {
339: $c += 2;
340: } else {
341: $c++;
342: }
343: }
344:
345: return $c;
346: }
347:
348: #
349: # Return trun if long long
350: #
351: sub isLongLong
352: {
353: local($type) = @_;
354:
355: # except for CONST
356: $type =~ s/\bCONST\b//;
357: $type =~ s/^\s*//;
358: $type =~ s/\s*$//;
359:
360: return 1 if ( $type =~ /^(D|UD|VD|_D|_UD)$/ );
361: return 1 if ( $type =~ /^(TMO_U|RELTIM_U|SYSTIM_U)$/ );
362:
363: return 0;
364: }