Lightweight bytecode interpreter
Go to file
Rick Hanson 6bc3fe5f11 get_exename() for OpenBSD. (#17)
get_exename() for OpenBSD.

Issue

`get_exename()` gets the pathname of the current process.  In
femtolisp, this is used to set the top-level `*install-dir*` which in
turn is used as the location of the system image, `flisp.boot`.

There is only a trivial implementation of `get_exename()` for OpenBSD
that simply returns `NULL`.  A minor consequence is that the unit test
will fail for the default build (make) because the system image cannot
be found.

Fix

This commit provides an implementation of `get_exename()` for OpenBSD,
so that the system image can be found.

Unlike, say, Linux or FreeBSD, OpenBSD doesn't have a system call to
get the path of the current (or any, for that matter) process.  The
present code contains some logic that was put together to emulate the
behavior of the Linux and FreeBSD variants of `get_exename()` as best
as possible.  It works as described by the following.

(1) Call `sysctl(3)` (with `CTL_KERN` -> `KERN_PROC_ARGS` ->
    `KERN_PROC_ARGV`) to get the "`argv[0]`" of the current process.
    If the program (flisp) was called in "`basename` form" (i.e. as
    "flisp"), then go to (2).  Otherwise, return the value from
    `sysctl(3)` which will be an absolute or relative pathname,
    e.g. "/usr/local/bin/flisp" or  "../flisp".

    The code for (1) was adapted from old OpenBSD-specific `tmux` code
    that has since been abandoned by the author only because he deemed
    it "too expensive".  For that code, see

    8c259f562b/tree/osdep-openbsd.c

(2) Since we now only have "flisp", we need to find out where it is
    located on the system.  We assume that a program like the shell
    had to crawl `PATH` to find "flisp"; hence we do the same.

    The code for (2) was adapted from the `which` utility in OpenBSD.
    See

    http://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/usr.bin/which/which.c?rev=1.20&content-type=text/plain

Finally, any error condition returns `NULL`, which is the same
behavior of the other `get_exename()` variants.

* Resolve relative pathnames to absolute, for OpenBSD get_exename().
2016-11-15 15:12:14 -05:00
attic remove and clean up some old files 2013-06-11 17:31:51 -04:00
examples remove and clean up some old files 2013-06-11 17:31:51 -04:00
lib a rename 2012-02-17 18:36:19 -05:00
llt get_exename() for OpenBSD. (#17) 2016-11-15 15:12:14 -05:00
tests fix #24, make `<=` and `>=` work on strings 2016-09-17 14:30:05 -04:00
tiny Make FreeBSD a "first class citizen" among femtolisp's build OSes. 2015-04-11 15:21:02 -04:00
.gitignore gitignore flisp.boot.bak 2013-06-11 17:40:46 -04:00
LICENSE moving stuff around some more 2012-02-17 17:53:34 -05:00
Makefile Make FreeBSD a "first class citizen" among femtolisp's build OSes. 2015-04-11 15:21:02 -04:00
Makefile.macosx Updated carbon path and pointer size check 2013-05-08 19:41:21 -04:00
README.md update README: `map` is now built in. fixes #26 2016-09-23 16:06:44 -04:00
aliases.scm fix #24, make `<=` and `>=` work on strings 2016-09-17 14:30:05 -04:00
ascii-mona-lisa moving stuff around some more 2012-02-17 17:53:34 -05:00
ascii-mona-lisa-2 moving stuff around some more 2012-02-17 17:53:34 -05:00
bootstrap.sh moving stuff around some more 2012-02-17 17:53:34 -05:00
builtins.c several minor changes and additions: 2013-06-08 19:29:15 -04:00
compiler.lsp fix lack of error when calling builtins with the wrong number of args 2013-08-26 16:55:17 -04:00
cvalues.c several minor changes and additions: 2013-06-08 19:29:15 -04:00
equal.c several minor changes and additions: 2013-06-08 19:29:15 -04:00
equalhash.c moving stuff around some more 2012-02-17 17:53:34 -05:00
equalhash.h removing leading/trailing underscores from preprocessor symbols 2012-02-20 17:43:53 -05:00
flisp.boot fix #24, make `<=` and `>=` work on strings 2016-09-17 14:30:05 -04:00
flisp.c fix #22 2016-08-09 22:58:44 -04:00
flisp.h several minor changes and additions: 2013-06-08 19:29:15 -04:00
flmain.c Merge branch 'master' of github.com:JeffBezanson/femtolisp 2013-06-08 19:29:46 -04:00
iostream.c fix bug in file-not-found due to incomplete init of the ios_t 2014-05-22 18:09:49 -04:00
mkboot0.lsp moving stuff around some more 2012-02-17 17:53:34 -05:00
mkboot1.lsp moving stuff around some more 2012-02-17 17:53:34 -05:00
opaque_type_template.c moving stuff around some more 2012-02-17 17:53:34 -05:00
opcodes.h removing leading/trailing underscores from preprocessor symbols 2012-02-20 17:43:53 -05:00
operators.c fixing large int64 comparison bug 2012-03-15 00:21:39 -04:00
print.c several minor changes and additions: 2013-06-08 19:29:15 -04:00
read.c several minor changes and additions: 2013-06-08 19:29:15 -04:00
string.c several minor changes and additions: 2013-06-08 19:29:15 -04:00
system.lsp fix #24, make `<=` and `>=` work on strings 2016-09-17 14:30:05 -04:00
table.c several minor changes and additions: 2013-06-08 19:29:15 -04:00
todo moving stuff around some more 2012-02-17 17:53:34 -05:00
todo-scrap moving stuff around some more 2012-02-17 17:53:34 -05:00
types.c several minor changes and additions: 2013-06-08 19:29:15 -04:00

README.md

...a purely symbolic gesture...

This project began with an attempt to write the fastest lisp interpreter I could in under 1000 lines of C. It snowballed from there as I kept trying to see if I could add powerful features with minimal code. At the same time I assembled a library of some of my favorite C code (by myself and others) to use as a base for a standard library. This includes ios, a replacement for parts of C's stdio that adds more flexible features.

Before you say "oh no, another lisp", consider the following: femtolisp is about 150kb, is very self-contained, and has the following features:

  • vectors, strings, gensyms
  • backquote
  • exceptions
  • printing and reading circular/shared structure
  • all values can be printed readably
  • prettyprinting
  • hash tables
  • support for directly using C data types ala Python's ctypes
  • equal and ordered comparison predicates that work on circular structure
  • proper tail recursion
  • io and memory streams with utf8 support
  • highly compatible with Scheme, including some R6RS features
  • simple, well-organized, powerful API with as few functions as possible
  • compacting GC
  • and...

...it is fast, ranking among the fastest non-native-compiled Scheme implementations. It achieves this level of speed even though many primitives (e.g. filter and for-each) are written in the language instead of C. femtolisp uses a bytecode compiler and VM, with the compiler written in femtolisp. Bytecode is first-class, can be printed and read, and is "human readable" (the representation is a string of normal low-ASCII characters).

femtolisp is a simple, elegant Scheme dialect. It is a lisp-1 with lexical scope. The core is 12 builtin special forms and 33 builtin functions.

A primary design goal is to keep the code concise and interesting. I strive to have each concept implemented in just one place, so the system is easy to understand and modify. The result is high reliability, because there are fewer places for bugs to hide. You want a small core of generically useful features that work really well (for example, see torture.scm).

Almost everybody has their own lisp implementation. Some programmers' dogs and cats probably have their own lisp implementations as well. This is great, but too often I see people omit some of the obscure but critical features that make lisp uniquely wonderful. These include read macros like #. and backreferences, gensyms, and properly escaped symbol names. If you're going to waste everybody's time with yet another lisp, at least do it right damnit.

Another design goal is to avoid spurious novelties. Many others offering their own "shiny new" lisp dialects get carried away and change anything that strikes their fancy. These changes have no effect except incompatibility, and often make the language worse because the new design was not as carefully thought out and has not stood the test of time. For example, how does it help to remove backquote? One design changes the syntax of quote. Some systems disallow dotted lists. (I've seen all three of these.) What's the point? Implementers wave the banner of "simplicity", yet wedge in all kinds of weird implicit behaviors and extra evaluation rules.

Lately a surprising amount of FUD has been spread about tail call optimization. I agree that not every language needs it, but I would like to refute the idea that it makes interpreters slow. Look at the "tiny" subdirectory or the "interpreter" branch to see a pure s-expr interpreter with efficient TCO. All you have to do is keep track of whether you're in tail position, which can be done very cheaply. These interpreters are difficult to beat for speed, yet they have lexical scope and TCO.

This project is mostly a matter of style. Look at the code and you'll understand.

This is what I do for fun, because it is the exact opposite of the kind of thing people will pay for: an obscure implementation of a programming language everybody hates.