Commit c8a7be53db009fc7ea28fcb7c06c841e9e627776

  • avatar
  • crawley <crawley @407389f7-7c16-0410…ad85acb55d7f.>
  • Sat Aug 22 16:37:39 CEST 2009
Partial implementation of shell functions.  (Arguments, redirections and 
the context / variables are not yet implemented when a function is run.)


git-svn-id: http://jnode.svn.sourceforge.net/svnroot/jnode/trunk@5659 407389f7-7c16-0410-9eee-ad85acb55d7f
  
4848
4949 /**
5050 * Temporary adapter method. Unconverted builtin classes override this.
51 *
52 * @param command
53 * @param interpreter
54 * @param context
55 * @return
56 * @throws ShellException
5751 */
5852 int invoke(CommandLine command, BjorneInterpreter interpreter,
5953 BjorneContext context) throws ShellException {
  
9090 private final BjorneInterpreter interpreter;
9191
9292 private Map<String, VariableSlot> variables;
93
93
9494 private TreeMap<String, String> aliases;
95
96 private TreeMap<String, CommandNode> functions;
9597
9698 private String command = "";
9799
124124 this.holders = holders;
125125 this.variables = new HashMap<String, VariableSlot>();
126126 this.aliases = new TreeMap<String, String>();
127 this.functions = new TreeMap<String, CommandNode>();
127128 initVariables();
128129 }
129130
160160 this.holders = copyStreamHolders(parent.holders);
161161 this.variables = copyVariables(parent.variables);
162162 this.aliases = new TreeMap<String, String>(parent.aliases);
163 this.functions = new TreeMap<String, CommandNode>(parent.functions);
163164 this.globbing = parent.globbing;
164165 this.tildeExpansion = parent.tildeExpansion;
165166 this.echoExpansions = parent.echoExpansions;
410410 * @param tokens the tokens to be expanded and split into words
411411 * @throws ShellException
412412 */
413 public List<BjorneToken> expandAndSplit(BjorneToken ... tokens)
414 throws ShellException {
415 List<BjorneToken> wordTokens = new LinkedList<BjorneToken>();
416 for (BjorneToken token : tokens) {
417 dollarBacktickSplit(token, wordTokens);
418 }
419 wordTokens = fileExpand(wordTokens);
420 wordTokens = dequote(wordTokens);
421 return wordTokens;
413 public List<BjorneToken> expandAndSplit(BjorneToken ... tokens) throws ShellException {
414 return expandAndSplit(Arrays.asList(tokens));
422415 }
423416
424417 /**
10581058 return new BjorneArithmeticEvaluator(this).evaluateExpression(tmp);
10591059 }
10601060
1061 int execute(CommandLine command, CommandIO[] streams, boolean isBuiltin) throws ShellException {
1061 int execute(CommandLine command, CommandIO[] streams) throws ShellException {
10621062 if (isEchoExpansions()) {
10631063 StringBuilder sb = new StringBuilder();
10641064 sb.append(" + ").append(command.getCommandName());
10681068 resolvePrintStream(streams[Command.STD_ERR]).println(sb);
10691069 }
10701070 Map<String, String> env = buildEnvFromExports();
1071 lastReturnCode = interpreter.executeCommand(command, this, streams, null, env, isBuiltin);
1071 lastReturnCode = interpreter.executeCommand(command, this, streams, null, env);
10721072 return lastReturnCode;
10731073 }
10741074
13851385
13861386 public Collection<String> getVariableNames() {
13871387 return variables.keySet();
1388 }
1389
1390 void defineFunction(BjorneToken name, CommandNode body) {
1391 functions.put(name.getText(), body);
1392 }
1393
1394 CommandNode getFunction(String name) {
1395 return functions.get(name);
13881396 }
13891397
13901398}
  
122122 public static final int FLAG_PIPE = 0x0010;
123123
124124 public static final CommandNode EMPTY =
125 new SimpleCommandNode(CMD_EMPTY, new BjorneToken[0], false);
125 new SimpleCommandNode(CMD_EMPTY, new BjorneToken[0]);
126126
127127 static HashMap<String, BjorneBuiltin.Factory> BUILTINS =
128128 new HashMap<String, BjorneBuiltin.Factory>();
313313 }
314314
315315 int executeCommand(CommandLine cmdLine, BjorneContext context, CommandIO[] streams,
316 Properties sysProps, Map<String, String> env, boolean isBuiltin)
316 Properties sysProps, Map<String, String> env)
317317 throws ShellException {
318 if (isBuiltin) {
319 BjorneBuiltinCommandInfo builtin =
320 BUILTINS.get(cmdLine.getCommandName()).buildCommandInfo(context);
318 String commandName = cmdLine.getCommandName();
319 if (isBuiltin(commandName)) {
320 BjorneBuiltinCommandInfo builtin = BUILTINS.get(commandName).buildCommandInfo(context);
321321 cmdLine.setCommandInfo(builtin);
322 }
322 } else {
323 CommandNode body = context.getFunction(commandName);
324 if (body != null) {
325 // FIXME setup a new context, streams and args.
326 return body.execute(context);
327 }
328 }
323329 cmdLine.setStreams(streams);
324330 return shell.invoke(cmdLine, sysProps, env);
325331 }
  
145145 } else {
146146 noLineBreaks();
147147 if (optNext(TOK_END_OF_LINE_BIT) != null) {
148 command = new SimpleCommandNode(CMD_COMMAND, new BjorneToken[0], false);
148 command = new SimpleCommandNode(CMD_COMMAND, new BjorneToken[0]);
149149 }
150150 }
151151 return command;
292292 List<BjorneToken> assignments = new LinkedList<BjorneToken>();
293293 List<RedirectionNode> redirects = new LinkedList<RedirectionNode>();
294294 List<BjorneToken> words = new LinkedList<BjorneToken>();
295 boolean builtin = false;
296295
297296 // Deal with cmd_prefix'es before the command name; i.e. assignments and
298297 // redirections
337337 redirects.add(parseRedirect());
338338 }
339339 }
340 String commandWord = words.get(0).getText();
341 builtin = BjorneInterpreter.isBuiltin(commandWord);
342 // FIXME ... built-in commands should use the Syntax mechanisms so
343 // that completion, help, etc will work as expected.
344340 }
345341 } catch (ShellSyntaxException ex) {
346342 if (completer != null) {
347343 completer.setCommand(words.size() == 0 ? null :
348344 new SimpleCommandNode(CMD_COMMAND,
349 words.toArray(new BjorneToken[words.size()]), builtin));
345 words.toArray(new BjorneToken[words.size()])));
350346 }
351347 throw ex;
352348 }
353349 SimpleCommandNode res = new SimpleCommandNode(CMD_COMMAND,
354 words.toArray(new BjorneToken[words.size()]), builtin);
350 words.toArray(new BjorneToken[words.size()]));
355351 if (completer != null) {
356352 completer.setCommand(words.size() == 0 ? null : res);
357353 }
377377 }
378378
379379 private CommandNode parseFunctionBody() throws ShellSyntaxException {
380 // TODO ... need to set the context to 'rule 9' while parsing the
381 // function body
382380 CommandNode body = parseCompoundCommand();
383381 body.setRedirects(parseOptRedirects());
384382 return body;
  
5656
5757 @Override
5858 public int execute(BjorneContext context) {
59 return -1;
59 context.defineFunction(name, body);
60 return 0;
6061 }
6162
6263 @Override
  
3838
3939 private final BjorneToken[] words;
4040
41 private final boolean builtin;
4241
43 public SimpleCommandNode(int nodeType, BjorneToken[] words, boolean builtin) {
42 public SimpleCommandNode(int nodeType, BjorneToken[] words) {
4443 super(nodeType);
4544 this.words = words;
46 this.builtin = builtin;
4745 }
4846
4947 public void setAssignments(BjorneToken[] assignments) {
5656 return assignments;
5757 }
5858
59 public boolean isBuiltin() {
60 return builtin;
61 }
62
6359 public String toString() {
6460 StringBuilder sb = new StringBuilder();
6561 sb.append("SimpleCommand{").append(super.toString());
6363 sb.append(",assignments=");
6464 appendArray(sb, assignments);
6565 }
66 if (builtin) {
67 sb.append(",builtin=true");
68 }
6966 if (words != null) {
7067 sb.append(",words=");
7168 appendArray(sb, words);
101101 throw new ShellFailureException(
102102 "asynchronous execution (&) not implemented yet");
103103 } else {
104 rc = childContext.execute(command, ios, builtin);
104 rc = childContext.execute(command, ios);
105105 }
106106 }
107107 } catch (BjorneControlException ex) {
144144 throws CompletionException {
145145 try {
146146 CommandLine command = context.buildCommandLine(words);
147 if (builtin) {
147 String commandName = command.getCommandName();
148 if (commandName != null && BjorneInterpreter.isBuiltin(commandName)) {
148149 BjorneBuiltinCommandInfo commandInfo =
149 BjorneInterpreter.BUILTINS.get(command.getCommandName()).buildCommandInfo(context);
150 BjorneInterpreter.BUILTINS.get(commandName).buildCommandInfo(context);
150151 command.setCommandInfo(commandInfo);
151152 }
152153 command.setArgumentAnticipated(argumentAnticipated);
  
7474 <output>fred='ls'
7575</output>
7676 </testSpec>
77 <testSpec title="builtins recognized early" command="test" runMode="AS_SCRIPT" rc="0">
78 <script>#!bjorne
79 alias fred=ls
80 alias
81 unalias -a
82 echo done
83 UNALIAS=unalias
84 alias fred=dir
85 alias
86 $UNALIAS -a
87 echo done
88 </script>
89 <output>fred='ls'
90done
91fred='dir'
92done
93</output>
94 <error>Cannot find an alias or load a command class for 'unalias'
95</error>
96 </testSpec>
9777 <testSpec title="readonly" runMode="AS_SCRIPT" rc="0">
9878 <script>#!bjorne
9979 readonly A
  
969969 <error>Cannot find an alias or load a command class for 'foo'
970970</error>
971971 </testSpec>
972 <testSpec title="shell function" command="test" runMode="AS_SCRIPT" rc="0">
973 <script>#!bjorne
974 foo() {
975 echo hi
976 }
977 foo
978 </script>
979 <output >hi
980</output>
981 </testSpec>
972982</testSet>