Commit Graph

26 Commits

Author SHA1 Message Date
Timothy Sample 50328c8c66 Respect the errexit option
* geesh/shell.scm (ignore-errexit?): New parameter.
(without-errexit): New function.
(errexit): New function.
(sh:exec-let, sh:set-redirects, sh:with-redirects, sh:subshell,
sh:substitute-command, sh:pipeline, sh:and, sh:or, sh:not, sh:while,
sh:cond): Use it to exit on nonzero status.
2018-12-05 16:08:09 -05:00
Timothy Sample b4a6350887 Exit subshells with the current status
* geesh/shell.scm (%subshell): Use with-continuation-barrier and
primitive-exit to make sure the child process exits with its status.
2018-12-05 16:08:09 -05:00
Timothy Sample 77f3113fd0 Set status to 0 when all sh-cond tests fail
* geesh/shell.scm (sh:cond): If no body thunk is called, set the
status to 0.
2018-12-05 16:08:09 -05:00
Timothy Sample 8c061471d3 Handle command not found with status 127
* geesh/shell.scm (sh:exec-let): Print a message and set the status to
127 when path search fails.
* tests/shell.scm: Update test.
2018-12-05 16:08:09 -05:00
Timothy Sample 4ef6907851 Globalize the environment module
Instead of passing around references to the environment, just treat it
as a global.  The old way was just the remains of an idea to make the
environment immutable and keep the interpreter from manipulating any
global state.  By making everything global and mutable, we will have
less impedance mismatch with POSIX going forward.

The following changelog is only a sketch, since nearly every function
has changed.

* geesh/environment.scm: Replace this module with one that treats the
environment as a global resource.
* tests/environment.scm: Delete file.
* Makefile.am: Remove it from the list of tests.
* geesh/shell.scm, geesh/eval.scm, geesh/repl.scm, geesh/word.scm,
geesh/built-ins/break.scm, geesh/built-ins/continue.scm,
geesh/built-ins/echo.scm, geesh/built-ins/export.scm,
geesh/built-ins/false.scm, geesh/built-ins/read.scm,
geesh/built-ins/readonly.scm, geesh/built-ins/set.scm,
geesh/built-ins/true.scm, geesh/built-ins/unset.scm: Remove 'env'
parameters and use the new environment module.
* .dir-locals.el: Update indentation of functions that no longer take
an 'env' parameter and add with-arguments, with-environ, and
with-variables from the new environment module.
* tests/shell.scm, tests/word.scm: Update environment creation and
manipulation in tests.
2018-12-05 16:08:09 -05:00
Timothy Sample 3ffcd0c498 Add case and cond semantics
* geesh/shell.scm (sh:case): New public function.
(sh:cond): New public function.
2018-12-05 16:08:09 -05:00
Timothy Sample 2335298226 Add while and until loop semantics
* geesh/shell.scm (sh:while): New public function.
(sh:until): New public function.
2018-12-05 16:08:09 -05:00
Timothy Sample 06db42088a Add 'break' and 'continue'
* geesh/environment.scm (<environment>): Add 'break-prompt' and
'continue-prompt' fields.
(make-environment): Initialize them.
* geesh/shell.scm (sh:for): Setup break and continue prompts.
* geesh/built-ins/break.scm: New file.
* geesh/built-ins/continue.scm: New file.
* Makefile.am: Add them.
* geesh/built-ins.scm (*special-built-ins*): Add break and continue.
2018-12-05 16:08:09 -05:00
Timothy Sample 76bbe01edc Let the 'exec' built-in manipulate files
* geesh/shell.scm (sh:set-redirects): New public function.
* geesh/eval.scm (eval-sh): Use it to handle 'exec' specially when
called with redirects but no arguments.
2018-12-05 16:08:09 -05:00
Timothy Sample 0c0227d523 Add support for file descriptors 3 to 9
* geesh/shell.scm (*fd-count*) Increase to 10.
(current-3-port, current-4-port, current-5-port, current-6-port,
current-7-port, current-8-port, current-9-port): New variables.
(fd->current-port): Handle file descriptors 3 to 9.
2018-12-05 16:08:09 -05:00
Timothy Sample 0ae52599c4 Preserve input and error ports in substitutions
This was simply a mistake.

* geesh/shell.scm (sh:substitute-command): Leave 'current-input-port'
and 'current-error-port' alone.
* tests/shell.scm: Remove tests that check that input and error gets
ignored during substitutions.
2018-12-05 16:08:09 -05:00
Timothy Sample 085c35a833 Use 'parameterize' for redirects
Instead of saving and restoring redirects manually, if we let them all
be parameters (like 'current-input-port'), we can use 'parameterize'
and make Guile take of this for us.  As a side-effect of this change,
redirect errors get handled.

* geesh/shell.scm (save-and-set-redirect): Rename this...
(redir->parameter+port): ...to this and change the return value to be
a pair consisting of a parameter and a port.
(restore-saved-port): Remove function.
(sh:with-redirects): Use 'parameterize' to effect redirects rather
than updating them and restoring them manually.
2018-12-05 16:08:09 -05:00
Timothy Sample b92630b39d Flush ports before forking
There are two issues that arise due to output port buffers and
forking.  If we run Scheme code in a child process, we need to avoid
copying buffered output into the child process.  Otherwise, the
buffered output could be written twice.  If we run non-Scheme
code (i.e., exec), we need to flush the ports to ensure proper
sequencing of writes since the non-Scheme code will not know about the
buffered output and will write its output before the buffer gets
flushed.

* geesh/shell.scm (exec-utility): Flush all ports before forking.
(%subshell): Ditto.
2018-12-05 16:08:09 -05:00
Timothy Sample 93a5cba568 Add function call semantics
* geesh/shell.scm (exec-let): Find and use functions when appropriate.
2018-12-03 20:19:39 -05:00
Timothy Sample e43e6a88c4 Add 'status' field to environment
Instead of using an environment variable named '?', we will use a
special environment field called 'status'.  This lets us get rid of a
lot of number-string conversions (since an environment variable has to
have a string value).

* geesh/environment.scm (<environment>): Add a 'status' field.
(make-environment): Set it to 0 by default.
* geesh/repl.scm (run-repl): Use new field in place of '?' variable.
* geesh/shell.scm (exec-utility, sh:and, sh:exec-let, sh:for, sh:not,
sh:or, sh:pipeline, sh:subshell, sh:substitute-command): Ditto.
* geesh/word.scm (parameter-ref): New function that handles both
special parameters (e.g., '?') and variables.
(parameter-ref*): Like 'var-ref*', but for 'parameter-ref'.
(word->qword): Replace 'var-ref' and 'var-ref*' with 'parameter-ref'
and 'parameter-ref*' respectively.
2018-12-03 20:17:56 -05:00
Timothy Sample fb493cc5f4 Process the return value of built-ins
* geesh/shell.scm (sh:exec-let): Set the '$?' variable to the return
value of built-in utilities.
2018-12-03 20:15:40 -05:00
Timothy Sample db56b1cc0a Add for-loop semantics
* geesh/shell.scm (sh:for): New public function.
* .dir-locals.el: Indent it nicely.
2018-12-03 20:12:51 -05:00
Timothy Sample 240ca130e8 Add boolean semantics
* geesh/shell.scm (sh:and, sh:not, sh:or): New public functions.
2018-12-03 20:12:02 -05:00
Timothy Sample 37f4ce6ea8 Add pipeline semantics
* geesh/shell.scm (swap-and-shift-pairs): New function.
(make-pipes): New function.
(plumb): New function.
(sh:pipeline): New public function.
* tests/shell.scm: Test it.
2018-12-03 20:09:55 -05:00
Timothy Sample 553b8f2b96 Use ports for redirects
Before, we were using raw file descriptors.  This worked okay, but
there was interference caused by port buffering.  Doing everything at
the port level avoids this problem, and has the added benefit of
allowing one to use the 'current-*-port' parameters with the shell
module (in a limited way, but there is room for improvement).

* geesh/shell.scm (*fd-count*): New variable.
(fd->current-port): New function.
(install-current-ports!): New function.
(exec-utility): Use it to set up file descriptors.
(save-and-install-redirect!): Rename this...
(save-and-set-redirect): ...to this and modify the current port
parameters instead of raw file descriptors.
(restore-saved-fdes!): Rename this...
(restore-saved-port): ...to this.
(sh:with-redirects): Adjust to use the renamed functions.
(sh:substitute-command): Parameterize the current ports directly
instead of using redirects.
* tests/shell.scm: Add tests to check if port buffers cause problems.
2018-12-03 20:07:53 -05:00
Timothy Sample 6b6ca11bce Add command substitution semantics
* geesh/shell.scm (%subshell): New function factored out from 'subshell'.
(subshell): Use it.
(substitute-command): New public function.
* tests/shell.scm: Test it.
* .dir-locals.el: Indent it nicely.
2018-12-03 20:06:47 -05:00
Timothy Sample 8739cafad9 Add subshell semantics
* geesh/shell.scm (subshell): New public function.
* tests/shell.scm: Test it.
* .dir-locals.el: Indent it nicely.
2018-11-28 23:07:03 -05:00
Timothy Sample e6f732ada9 Add redirect semantics
* geesh/shell.scm (save-and-install-redirect!): New function.
(restore-saved-fdes!): New function.
(with-redirects): New public function.
* tests/shell.scm: Test it.
* .dir-locals.el: Indent it nicely.
2018-11-28 23:07:03 -05:00
Timothy Sample e1f139b841 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.
2018-11-28 23:07:03 -05:00
Timothy Sample 7cc94e88e1 Add PATH searching
* geesh/shell.scm (slashless?) New function.
(split-search-path): New function.
(find-utility): New function.
(exec-let): Use them to search PATH for a utility when appropriate.
(exec): Update doc string.
* tests/shell.scm: Test it.
2018-11-28 23:07:03 -05:00
Timothy Sample b9ec924bbe Add shell module
* geesh/shell.scm: New file.
* tests/shell.scm: New file.
* Makefile.am: Add them.
* tests/config.scm.in: New file.
* configure.ac: Add it.
* .gitignore: Add its generated form.
* .dir-locals.el: Add indentation rule for 'make-script'.
2018-11-28 23:07:03 -05:00