From e1f139b841c8f68db758c6a31ec1396f828ce337 Mon Sep 17 00:00:00 2001 From: Timothy Sample Date: Tue, 17 Jul 2018 11:20:06 -0400 Subject: [PATCH] Add support for built-ins, starting with 'echo' * geesh/built-ins/echo.scm: New file. * geesh/built-ins.scm: New file. * Makefile.scm: Add them. * geesh/shell.scm (exec-let): Include built-ins in command search. * tests/shell.scm: Add a test for this. --- Makefile.am | 2 + geesh/built-ins.scm | 80 ++++++++++++++++++++++++++++++++++++++++ geesh/built-ins/echo.scm | 30 +++++++++++++++ geesh/shell.scm | 15 +++++++- tests/shell.scm | 7 ++++ 5 files changed, 133 insertions(+), 1 deletion(-) create mode 100644 geesh/built-ins.scm create mode 100644 geesh/built-ins/echo.scm diff --git a/Makefile.am b/Makefile.am index 83be488..92e53bc 100644 --- a/Makefile.am +++ b/Makefile.am @@ -37,6 +37,8 @@ endif # HAVE_GENHTML test-list: ; @echo $(TESTS) MODULES = \ + geesh/built-ins/echo.scm \ + geesh/built-ins.scm \ geesh/environment.scm \ geesh/lexer.scm \ geesh/parser.scm \ diff --git a/geesh/built-ins.scm b/geesh/built-ins.scm new file mode 100644 index 0000000..a33f951 --- /dev/null +++ b/geesh/built-ins.scm @@ -0,0 +1,80 @@ +;;; The Geesh Shell Interpreter +;;; Copyright 2018 Timothy Sample +;;; +;;; This file is part of Geesh. +;;; +;;; Geesh is free software: you can redistribute it and/or modify +;;; it under the terms of the GNU General Public License as published by +;;; the Free Software Foundation, either version 3 of the License, or +;;; (at your option) any later version. +;;; +;;; Geesh is distributed in the hope that it will be useful, +;;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with Geesh. If not, see . + +(define-module (geesh built-ins) + #:use-module (geesh built-ins echo) + #:export (search-built-ins + search-special-built-ins)) + +;;; Commentary: +;;; +;;; This module provides built-in searching functions. +;;; +;;; Code: + +(define (undefined env . args) + (throw 'undefined-built-in)) + +;; Special built-ins take precedence over any other command. +(define *special-built-ins* + `(("." . ,undefined) + (":" . ,undefined) + ("break" . ,undefined) + ("continue" . ,undefined) + ("eval" . ,undefined) + ("exec" . ,undefined) + ("exit" . ,undefined) + ("export" . ,undefined) + ("readonly" . ,undefined) + ("return" . ,undefined) + ("set" . ,undefined) + ("shift" . ,undefined) + ("times" . ,undefined) + ("trap" . ,undefined) + ("unset" . ,undefined))) + +;; Regular built-ins take precendence over utilities in the search +;; path, but not over functions. +(define *built-ins* + `( ;; POSIX-specified built-ins. + ("alias" . ,undefined) + ("bg" . ,undefined) + ("cd" . ,undefined) + ("command" . ,undefined) + ("false" . ,undefined) + ("fc" . ,undefined) + ("fg" . ,undefined) + ("getopts" . ,undefined) + ("hash" . ,undefined) + ("jobs" . ,undefined) + ("kill" . ,undefined) + ("newgrp" . ,undefined) + ("pwd" . ,undefined) + ("read" . ,undefined) + ("true" . ,undefined) + ("umask" . ,undefined) + ("unalias" . ,undefined) + ("wait" . ,undefined) + ;; Other built-ins. + ("echo" . ,echo))) + +(define (search-special-built-ins name) + (assoc-ref *special-built-ins* name)) + +(define (search-built-ins name) + (assoc-ref *built-ins* name)) diff --git a/geesh/built-ins/echo.scm b/geesh/built-ins/echo.scm new file mode 100644 index 0000000..8e75715 --- /dev/null +++ b/geesh/built-ins/echo.scm @@ -0,0 +1,30 @@ +;;; The Geesh Shell Interpreter +;;; Copyright 2018 Timothy Sample +;;; +;;; This file is part of Geesh. +;;; +;;; Geesh is free software: you can redistribute it and/or modify +;;; it under the terms of the GNU General Public License as published by +;;; the Free Software Foundation, either version 3 of the License, or +;;; (at your option) any later version. +;;; +;;; Geesh is distributed in the hope that it will be useful, +;;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with Geesh. If not, see . + +(define-module (geesh built-ins echo) + #:export (echo)) + +;;; Commentary: +;;; +;;; The 'echo' utility. +;;; +;;; Code: + +(define (echo env . args) + (display (string-join args " ")) + (newline)) diff --git a/geesh/shell.scm b/geesh/shell.scm index 241610d..40d4f3b 100644 --- a/geesh/shell.scm +++ b/geesh/shell.scm @@ -1,4 +1,5 @@ (define-module (geesh shell) + #:use-module (geesh built-ins) #:use-module (geesh environment) #:use-module (ice-9 match) #:export (sh:exec-let @@ -47,7 +48,19 @@ it cannot be found, return @code{#f}." "Find and execute @var{name} with arguments @var{args}, environment @var{env}, and extra environment variable bindings @var{bindings}." (if (slashless? name) - (or (and=> (find-utility env name) + (or (and=> (search-special-built-ins name) + (lambda (proc) + (for-each (match-lambda + ((name . value) + (set-var! env name value))) + bindings) + (apply proc env args))) + ;; TODO: Functions. + (and=> (search-built-ins name) + (lambda (proc) + ;; TODO: Use 'bindings' here. + (apply proc env args))) + (and=> (find-utility env name) (lambda (path) (exec-utility env bindings path name args))) (error "Command not found.")) diff --git a/tests/shell.scm b/tests/shell.scm index 3593084..abfcfc1 100644 --- a/tests/shell.scm +++ b/tests/shell.scm @@ -120,4 +120,11 @@ (('misc-error _ _ ("Command not found.") _) #t) (_ #f)))))))) +(test-equal "Executes regular built-ins" + "foo bar\n" + (let ((env (make-environment '()))) + (with-output-to-string + (lambda () + (sh:exec env "echo" "foo" "bar"))))) + (test-end)