diff --git a/README.android b/README.android new file mode 100644 index 000000000..83f284757 --- /dev/null +++ b/README.android @@ -0,0 +1,12 @@ +To build: + +$ export ANDROID_NDK_ROOT=Path to NDK +$ ./configure.android + +This will create a 32-bit version of ECL to cross-compile. +Then it will compile an ARM 32-bit ECL into android/install/android. +Please see the sample application in contrib/android. + + +evrim ulu +March 2015 \ No newline at end of file diff --git a/examples/android/.classpath b/examples/android/.classpath new file mode 100644 index 000000000..7bc01d9a9 --- /dev/null +++ b/examples/android/.classpath @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/examples/android/.project b/examples/android/.project new file mode 100644 index 000000000..508d720fb --- /dev/null +++ b/examples/android/.project @@ -0,0 +1,33 @@ + + + HelloEclActivity + + + + + + com.android.ide.eclipse.adt.ResourceManagerBuilder + + + + + com.android.ide.eclipse.adt.PreCompilerBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + com.android.ide.eclipse.adt.ApkBuilder + + + + + + com.android.ide.eclipse.adt.AndroidNature + org.eclipse.jdt.core.javanature + + diff --git a/examples/android/.settings/org.eclipse.jdt.core.prefs b/examples/android/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..b080d2ddc --- /dev/null +++ b/examples/android/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,4 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/examples/android/AndroidManifest.xml b/examples/android/AndroidManifest.xml new file mode 100644 index 000000000..1a92913c1 --- /dev/null +++ b/examples/android/AndroidManifest.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + diff --git a/examples/android/README b/examples/android/README new file mode 100644 index 000000000..58c493664 --- /dev/null +++ b/examples/android/README @@ -0,0 +1,14 @@ +This project is a base project for ECL Android. +It is created by Sylvain Ageneau . +Original location of this project is: +http://github.com/ageneau/ecl-android + +Instructions: +$ android update project -t android-19 -p . +$ ndk-build +$ ant debug install + +Please direct further questions to ecl-devel@common-lisp.net + +evrim ulu +March 2015. diff --git a/examples/android/ant.properties b/examples/android/ant.properties new file mode 100644 index 000000000..b0971e891 --- /dev/null +++ b/examples/android/ant.properties @@ -0,0 +1,17 @@ +# This file is used to override default values used by the Ant build system. +# +# This file must be checked into Version Control Systems, as it is +# integral to the build system of your project. + +# This file is only used by the Ant script. + +# You can use this to override default values such as +# 'source.dir' for the location of your java source folder and +# 'out.dir' for the location of your output folder. + +# You can also use it define how the release builds are signed by declaring +# the following properties: +# 'key.store' for the location of your keystore and +# 'key.alias' for the name of the key to use. +# The password will be asked during the build when you use the 'release' target. + diff --git a/examples/android/assets/lisp/init.lisp b/examples/android/assets/lisp/init.lisp new file mode 100644 index 000000000..a96aaadc8 --- /dev/null +++ b/examples/android/assets/lisp/init.lisp @@ -0,0 +1,57 @@ +(in-package :cl-user) +(format t "ECL (Embeddable Common-Lisp) ~A (git:~D)~%" + (lisp-implementation-version) + (ext:lisp-implementation-vcs-id)) + +(require :SOCKETS) +(require :ASDF) +(setq *default-directory* + *default-pathname-defaults*) +(defvar *ecl-home* *default-directory*) +(ext:setenv "HOME" (namestring *ecl-home*)) +(pushnew (namestring *default-pathname-defaults*) + asdf:*central-registry*) +(asdf:oos 'asdf:load-op :swank) +(swank-loader:init :load-contribs t + :setup t + :delete t + :quiet nil) + +;; The following "patches" swank to work correctly on android/iOS +(in-package :swank/backend) +(defimplementation lisp-implementation-program () + "Return the argv[0] of the running Lisp process, or NIL." + ;; (lisp-implementation-type) + nil) + +(in-package :swank) +(defun repl-input-stream-read (connection stdin) + (loop + (let* ((socket (connection.socket-io connection)) + (inputs (list socket #+nil stdin)) + (ready (wait-for-input inputs))) + (describe (list 'hobaa connection stdin socket inputs ready)) + (cond ((eq ready :interrupt) + (check-slime-interrupts)) + ((member socket ready) + ;; A Slime request from Emacs is pending; make sure to + ;; redirect IO to the REPL buffer. + (with-simple-restart (process-input "Continue reading input.") + (let ((*sldb-quit-restart* (find-restart 'process-input))) + (with-io-redirection (connection) + (handle-requests connection t))))) + ((member stdin ready) + ;; User typed something into the *inferior-lisp* buffer, + ;; so do not redirect. + (return (read-non-blocking stdin))) + (t (assert (null ready))))))) + +(mp:process-run-function + "SLIME-listener" + (lambda () + (swank:create-server :port 4005 + :dont-close t))) + +(cond ((probe-file #P"user.lisp") + (load "user"))) + diff --git a/examples/android/assets/lisp/user.lisp b/examples/android/assets/lisp/user.lisp new file mode 100644 index 000000000..c0e9f28d7 --- /dev/null +++ b/examples/android/assets/lisp/user.lisp @@ -0,0 +1,51 @@ +(in-package :cl-user) +(require 'bytecmp) +(setq *default-directory* + *default-pathname-defaults*) + +(defun sysinfo (&optional (out *standard-output*)) + "Print the current environment to a stream." + (declare (stream out)) + (format out "~&~%~75~~%~75,,,'-:@<<{[ The current environment ]}>~>~%~ +Implementation:~20t~a~%~7tversion:~20t~a~%Machine: type:~20t~a +~7tversion:~20t~a~%~6tinstance:~20t~a~%Opeating System:~19t" + (lisp-implementation-type) (lisp-implementation-version) + (machine-type) (machine-version) (machine-instance)) + #+darwin (princ " Darwin") + #+unix (princ " Unix") + (format out "~%Software: type:~20t~a~%~7tversion:~20t~a~%Site:~20t~a (~a) +User home:~20t~a~%Current directory:~20t~a~%Default pathname:~20t~a~%" + (software-type) (software-version) (long-site-name) + (short-site-name) (user-homedir-pathname) *default-directory* + *default-pathname-defaults*) + (format out "Features: ~s. +Modules:~s.~% +Current package:~s~%" + *features* *modules* *package*) + (flet ((exdi (fl) (integer-length (nth-value 1 (decode-float fl))))) + (format out "Fixnum length:~25t~3d bits +Short Floats:~25t~3d bits exponent, ~3d bits significand (mantissa) +Single Floats:~25t~3d bits exponent, ~3d bits significand (mantissa) +Double Floats:~25t~3d bits exponent, ~3d bits significand (mantissa) +Long Floats:~25t~3d bits exponent, ~3d bits significand (mantissa)~%" + (integer-length most-positive-fixnum) + (exdi most-positive-short-float) + (float-digits most-positive-short-float) + (exdi most-positive-single-float) + (float-digits most-positive-single-float) + (exdi most-positive-double-float) + (float-digits most-positive-double-float) + (exdi most-positive-long-float) + (float-digits most-positive-long-float))) + (dolist (sy '(array-total-size-limit array-rank-limit array-dimension-limit + lambda-parameters-limit call-arguments-limit + multiple-values-limit char-code-limit)) + (format out " ~a:~30t~15:d~%" sy (symbol-value sy))) + (format out "lambda-list-keywords:~s~%" + lambda-list-keywords) + (format out "Internal time unit:~25t~f sec~%*gensym-counter*:~25t~:d +Current time:~25t" (/ internal-time-units-per-second) *gensym-counter*) + (format out "~a" (get-universal-time)) + (format out "~%~75~~%") (room) (values)) + +(sysinfo) diff --git a/examples/android/jni/Android.mk b/examples/android/jni/Android.mk new file mode 100644 index 000000000..1784f06ec --- /dev/null +++ b/examples/android/jni/Android.mk @@ -0,0 +1,39 @@ +# Copyright (C) 2009 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +BASE_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +ifeq ($(TARGET_ARCH),x86) +PLATFORM := androidx86 +else +PLATFORM := android +endif + +ECL_HOME := ../../android/install/$(PLATFORM) +ECL_VER := $(shell basename $(ECL_HOME)/lib/ecl-* |cut -d "-" -f2) + +LOCAL_MODULE := ecl_android +LOCAL_PATH := $(BASE_PATH) +LOCAL_SRC_FILES := org_lisp_ecl_EmbeddedCommonLisp.c ecl_boot.c +LOCAL_CFLAGS += -I$(ECL_HOME)/include +LOCAL_CFLAGS += -g -Wall -DANDROID +LOCAL_LDLIBS := -L$(ECL_HOME)/lib +LOCAL_LDLIBS += -L$(ECL_HOME)/lib/ecl-$(ECL_VER) +LOCAL_LDLIBS += -lecl -lasdf -leclgmp -lsockets -llog +LOCAL_LDLIBS += -lsb-bsd-sockets -lserve-event -lecl-help +LOCAL_LDLIBS += -lecl-cdb -leclgc -leclatomic + +include $(BUILD_SHARED_LIBRARY) diff --git a/examples/android/jni/ecl_boot.c b/examples/android/jni/ecl_boot.c new file mode 100644 index 000000000..f6fcce73f --- /dev/null +++ b/examples/android/jni/ecl_boot.c @@ -0,0 +1,88 @@ +#include +#include +#if ANDROID +#include +#endif + +#if ANDROID +#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "native-activity", __VA_ARGS__)) +#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "native-activity", __VA_ARGS__)) +#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, "native-activity", __VA_ARGS__)) +#define LOGV(...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, "native-activity", __VA_ARGS__)) +#else +#define LOGI(...) +#define LOGW(...) +#define LOGE(...) +#endif + +#include "ecl_boot.h" + +#ifdef __cplusplus +#define ECL_CPP_TAG "C" +#else +#define ECL_CPP_TAG +#endif + +extern ECL_CPP_TAG void main_lib_ASDF(); +extern ECL_CPP_TAG void main_lib_SOCKETS(); +extern ECL_CPP_TAG void main_lib_SB_BSD_SOCKETS(); +extern ECL_CPP_TAG void main_lib_SERVE_EVENT(); +extern ECL_CPP_TAG void main_lib_ECL_CDB(); +extern ECL_CPP_TAG void main_lib_ECL_HELP(); + + +extern void loadLispFromAssets(char* fn); + + +int ecl_boot(const char *root_dir) +{ + char *ecl = "ecl"; + char tmp[2048]; + + sprintf(tmp, "%s/", root_dir); + setenv("ECLDIR", tmp, 1); + + // ecl_set_option(ECL_OPT_TRAP_SIGFPE, 0); + // ecl_set_option(ECL_OPT_TRAP_SIGSEGV, 0); + // ecl_set_option(ECL_OPT_TRAP_SIGINT, 0); + // ecl_set_option(ECL_OPT_TRAP_SIGILL, 0); + // ecl_set_option(ECL_OPT_TRAP_SIGBUS, 0); + // ecl_set_option(ECL_OPT_TRAP_INTERRUPT_SIGNAL, 0); + // ecl_set_option(ECL_OPT_SIGNAL_HANDLING_THREAD, 0); + // ecl_set_option(ECL_OPT_INCREMENTAL_GC, 0); + + cl_boot(1, &ecl); + + main_lib_ECL_HELP(); + main_lib_ASDF(); + main_lib_SOCKETS(); + + si_safe_eval(3, c_string_to_object("(format t \"ECL_BOOT, features = ~A ~%\" *features*)"), Cnil, OBJNULL); + si_safe_eval(3, c_string_to_object("(format t \"(truename SYS:): ~A)\" (truename \"SYS:\"))"), Cnil, OBJNULL); + + LOGI("ALL LOADED\n"); + + ecl_toplevel(root_dir); + + return 0; +} + +void ecl_toplevel(const char *home) +{ + char tmp[2048]; + + LOGI("START TOP LEVEL\n"); + + CL_CATCH_ALL_BEGIN(ecl_process_env()) + { + sprintf(tmp, "(setq *default-pathname-defaults* #p\"%s/\")", home); + si_safe_eval(3, c_string_to_object(tmp), Cnil, OBJNULL); + + si_select_package(ecl_make_simple_base_string("CL-USER", 7)); + + si_safe_eval(3, c_string_to_object("(load \"init\")"), Cnil, OBJNULL); + + } CL_CATCH_ALL_END; + + LOGI("EXIT TOP LEVEL\n"); +} diff --git a/examples/android/jni/ecl_boot.h b/examples/android/jni/ecl_boot.h new file mode 100644 index 000000000..45284079d --- /dev/null +++ b/examples/android/jni/ecl_boot.h @@ -0,0 +1,8 @@ +#ifndef _ECL_BOOT_H_ +#define _ECL_BOOT_H_ + +int ecl_boot(const char *root_dir); +void ecl_toplevel(const char *home); +void eclshell_show(char *message); + +#endif \ No newline at end of file diff --git a/examples/android/jni/org_lisp_ecl_EmbeddedCommonLisp.c b/examples/android/jni/org_lisp_ecl_EmbeddedCommonLisp.c new file mode 100644 index 000000000..2e6f85cef --- /dev/null +++ b/examples/android/jni/org_lisp_ecl_EmbeddedCommonLisp.c @@ -0,0 +1,134 @@ +#include + +#if ANDROID +#include +#endif + +#include +#include +#include +#include + +#include +#include "ecl_boot.h" + +#if ANDROID +#define ECL_TAG "ecl-native" +#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, ECL_TAG, __VA_ARGS__)) +#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, ECL_TAG, __VA_ARGS__)) +#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, ECL_TAG, __VA_ARGS__)) +#define LOGV(...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, ECL_TAG, __VA_ARGS__)) +#else +#define LOGI(...) +#define LOGW(...) +#define LOGE(...) +#endif + +#define jni_ecl_read_from_string(x) si_string_to_object(1, x) + +/* + * Class: org_lisp_ecl_EmbeddedCommonLisp + * Method: start + * Signature: ()V + */ +JNIEXPORT void JNICALL +Java_org_lisp_ecl_EmbeddedCommonLisp_start(JNIEnv *env, jobject this, + jstring path) { + + const char *lisp_dir = (*env)->GetStringUTFChars(env, path, NULL); + LOGI("ECL starting: *default-pathname-defaults* to: %s\n", lisp_dir); + ecl_boot(lisp_dir); + LOGI("ECL started."); +}; + +/* This was fun to make UTF8 work across Java-C-Lisp boundaries. + -evrim, 2014. */ +cl_object java_string_to_ecl_string(JNIEnv *env, jstring str) { + const jchar *txt = (*env)->GetStringChars(env, str, NULL); + jsize len = (*env)->GetStringLength(env, str); + cl_object ecl_txt = ecl_alloc_simple_extended_string(len); + cl_index i; + + for (i=0;istring.self[i] = txt[i]; + }; + + (*env)->ReleaseStringChars(env, str, txt); + + return ecl_txt; +} + + +jstring ecl_object_to_java_string(JNIEnv *env, cl_object o) { + jstring ret; + if (ECL_EXTENDED_STRING_P(o)) { + LOGI("ecl->java extended string of fillp: %d, dim: %d", + o->string.fillp, + o->string.dim); + + jsize len = o->string.fillp; + jchar *arr = malloc(sizeof(jchar)*(len+1)); + cl_index i; + for (i=0; istring.self[i]; + } + arr[len] = 0; + ret = (*env)->NewString(env, arr, len); + free(arr); + } else if (ECL_STRINGP(o)) { + LOGI("ecl->java base string of len %d: %s", + o->base_string.dim, + o->base_string.self); + + ret = (*env)->NewStringUTF(env, + (const char*)o->base_string.self); + } else { + LOGI("ecl->java not a string, coercing"); + return ecl_object_to_java_string(env, cl_princ_to_string(o)); + } + + return ret; +} + +/* + * Class: org_lisp_ecl_EmbeddedCommonLisp + * Method: exec + * Signature: (Ljava/lang/String;)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL +Java_org_lisp_ecl_EmbeddedCommonLisp_exec(JNIEnv *env, jobject this, jstring str) { + jstring ret; + cl_object txt = java_string_to_ecl_string(env, str); + cl_object result = si_safe_eval(3, jni_ecl_read_from_string(txt), Cnil, OBJNULL); + + if (result) { + ret = ecl_object_to_java_string(env, result); + } else { + ret = (*env)->NewStringUTF(env, "ERROR in eval"); + } + + return ret; +}; + +#undef jni_ecl_read_from_string + +/* + * Class: org_lisp_ecl_EmbeddedCommonLisp + * Method: exec_ + * Signature: (Ljava/lang/String;)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL +Java_org_lisp_ecl_EmbeddedCommonLisp_exec_(JNIEnv *env, jobject this, jstring str) { + jstring ret; + const char *cmd = (*env)->GetStringUTFChars(env, str, NULL); + cl_object result = si_safe_eval(3, c_string_to_object(cmd), + Cnil, OBJNULL); + + if (result) { + cl_object out = si_coerce_to_base_string(cl_princ_to_string(result)); + ret = (*env)->NewStringUTF(env, (const char*) out->base_string.self); + } else { + ret = (*env)->NewStringUTF(env, "ERROR in eval"); + } + return ret; +}; diff --git a/examples/android/jni/org_lisp_ecl_EmbeddedCommonLisp.h b/examples/android/jni/org_lisp_ecl_EmbeddedCommonLisp.h new file mode 100644 index 000000000..9de49b39b --- /dev/null +++ b/examples/android/jni/org_lisp_ecl_EmbeddedCommonLisp.h @@ -0,0 +1,37 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class org_lisp_ecl_EmbeddedCommonLisp */ + +#ifndef _Included_org_lisp_ecl_EmbeddedCommonLisp +#define _Included_org_lisp_ecl_EmbeddedCommonLisp +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: org_lisp_ecl_EmbeddedCommonLisp + * Method: start + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_org_lisp_ecl_EmbeddedCommonLisp_start +(JNIEnv *, jobject, jstring); + +/* + * Class: org_lisp_ecl_EmbeddedCommonLisp + * Method: exec + * Signature: (Ljava/lang/String;)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_org_lisp_ecl_EmbeddedCommonLisp_exec +(JNIEnv *, jobject, jstring); + +/* /\* */ +/* * Class: org_lisp_ecl_EmbeddedCommonLisp */ +/* * Method: botExec */ +/* * Signature: (Ljava/lang/String;)Ljava/lang/String; */ +/* *\/ */ +/* JNIEXPORT jstring JNICALL Java_org_lisp_ecl_EmbeddedCommonLisp_exec_ */ +/* (JNIEnv *, jobject, jstring); */ + +#ifdef __cplusplus +} +#endif +#endif diff --git a/examples/android/proguard-project.txt b/examples/android/proguard-project.txt new file mode 100644 index 000000000..f2fe1559a --- /dev/null +++ b/examples/android/proguard-project.txt @@ -0,0 +1,20 @@ +# To enable ProGuard in your project, edit project.properties +# to define the proguard.config property as described in that file. +# +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in ${sdk.dir}/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the ProGuard +# include property in project.properties. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} diff --git a/examples/android/project.properties b/examples/android/project.properties new file mode 100644 index 000000000..4ab125693 --- /dev/null +++ b/examples/android/project.properties @@ -0,0 +1,14 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system edit +# "ant.properties", and override values to adapt the script to your +# project structure. +# +# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): +#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt + +# Project target. +target=android-19 diff --git a/examples/android/res/layout/main.xml b/examples/android/res/layout/main.xml new file mode 100644 index 000000000..a065c8384 --- /dev/null +++ b/examples/android/res/layout/main.xml @@ -0,0 +1,13 @@ + + + + + diff --git a/examples/android/res/layout/menu.xml b/examples/android/res/layout/menu.xml new file mode 100644 index 000000000..65b3bd681 --- /dev/null +++ b/examples/android/res/layout/menu.xml @@ -0,0 +1,8 @@ + + + + + diff --git a/examples/android/res/values/strings.xml b/examples/android/res/values/strings.xml new file mode 100644 index 000000000..f846038c2 --- /dev/null +++ b/examples/android/res/values/strings.xml @@ -0,0 +1,4 @@ + + + HelloEclActivity + diff --git a/examples/android/src/org/lisp/ecl/EmbeddedCommonLisp.java b/examples/android/src/org/lisp/ecl/EmbeddedCommonLisp.java new file mode 100644 index 000000000..b9b1ce31c --- /dev/null +++ b/examples/android/src/org/lisp/ecl/EmbeddedCommonLisp.java @@ -0,0 +1,19 @@ +package org.lisp.ecl; + +import android.util.Log; + +public class EmbeddedCommonLisp { + private static String TAG = "EmbeddedCommonLisp"; + + public void start() { + start(System.getenv("user.dir")); + } + public native void start(String path); + public native String exec(String string); + // public native String botExec(String string); + + static { + System.loadLibrary("ecl_android"); + Log.w(TAG,"Done loading library"); + } +} diff --git a/examples/android/src/org/lisp/ecl/HelloEclActivity.java b/examples/android/src/org/lisp/ecl/HelloEclActivity.java new file mode 100644 index 000000000..efd745489 --- /dev/null +++ b/examples/android/src/org/lisp/ecl/HelloEclActivity.java @@ -0,0 +1,154 @@ +package org.lisp.ecl; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import android.app.Activity; +import android.content.Context; +import android.content.SharedPreferences; +import android.content.res.AssetManager; +import android.os.Bundle; +import android.util.Log; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.widget.Toast; + + +public class HelloEclActivity extends Activity +{ + private static String TAG = "HelloEcl"; + private static String RESOURCES_DIR = "lisp"; + private static String APP_RESOURCES_DIR = "resources"; + private EmbeddedCommonLisp ecl = new EmbeddedCommonLisp(); + + private static boolean DEBUG = false; + + static AssetManager assetManager; + static File uncompressedFilesDir; + + /** Called when the activity is first created. */ + @Override + public void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + assetManager = getAssets(); + + SharedPreferences settings = getPreferences(MODE_PRIVATE); + boolean assetsUncompressed = settings.getBoolean("assetsUncompressed", false); + uncompressedFilesDir = getDir(APP_RESOURCES_DIR,MODE_PRIVATE); + + if(!assetsUncompressed) + { + uncompressDir(RESOURCES_DIR,uncompressedFilesDir); + SharedPreferences.Editor editor = settings.edit(); + editor.putBoolean("assetsUncompressed", true); + editor.commit(); + } + + Log.w(TAG,"ECL starting."); + + + ecl.start(getResourcesPath()); + Log.w(TAG,"ECL Started"); + + setContentView(R.layout.main); + + String result = ecl.exec("(format nil \"Hello from lisp\")"); + System.out.println("Result: " + result); + + Context context = getApplicationContext(); + int duration = Toast.LENGTH_LONG; + + Toast toast = Toast.makeText(context, result, duration); + toast.show(); + } + + public void uncompressDir(String in, File out) + { + try + { + String[] files = assetManager.list(in); + Log.w(TAG,"Uncompressing: " + files.length + " files"); + for(int i=0; i 0) + { + out.write(buf, 0, len); + } + + in.close(); + out.close(); + Log.i(TAG,"File copied."); + } +}