--- /dev/null
+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 <evrimulu@gmail.com>
+March 2015
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="src" path="gen"/>
+ <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+ <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
+ <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
+ <classpathentry kind="output" path="bin/classes"/>
+</classpath>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>HelloEclActivity</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.ApkBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>com.android.ide.eclipse.adt.AndroidNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+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
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="org.lisp.ecl"
+ android:versionCode="1"
+ android:versionName="1.0">
+ <uses-sdk android:minSdkVersion="19" />
+ <uses-permission android:name="android.permission.INTERNET" />
+ <application android:label="@string/app_name"
+ android:debuggable="true">
+ <activity android:name="HelloEclActivity"
+ android:label="@string/app_name">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
--- /dev/null
+This project is a base project for ECL Android.
+It is created by Sylvain Ageneau <ageneau@gmail.com>.
+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-lists@sf.net.
+
+evrim ulu <evrimulu@gmail.com>
+March 2015.
\ No newline at end of file
--- /dev/null
+# 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.
+
--- /dev/null
+(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")))
+
--- /dev/null
+Subproject commit 462085f1b7370e67babe9e7d50b37e5043c83fe1
--- /dev/null
+(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)
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="HelloEcl" default="help">
+
+ <!-- The local.properties file is created and updated by the 'android' tool.
+ It contains the path to the SDK. It should *NOT* be checked into
+ Version Control Systems. -->
+ <property file="local.properties" />
+
+ <!-- The ant.properties file can be created by you. It is only edited by the
+ 'android' tool to add properties to it.
+ This is the place to change some Ant specific build properties.
+ Here are some properties you may want to change/update:
+
+ source.dir
+ The name of the source directory. Default is 'src'.
+ out.dir
+ The name of the output directory. Default is 'bin'.
+
+ For other overridable properties, look at the beginning of the rules
+ files in the SDK, at tools/ant/build.xml
+
+ Properties related to the SDK location or the project target should
+ be updated using the 'android' tool with the 'update' action.
+
+ This file is an integral part of the build system for your
+ application and should be checked into Version Control Systems.
+
+ -->
+ <property file="ant.properties" />
+
+ <!-- if sdk.dir was not set from one of the property file, then
+ get it from the ANDROID_HOME env var.
+ This must be done before we load project.properties since
+ the proguard config can use sdk.dir -->
+ <property environment="env" />
+ <condition property="sdk.dir" value="${env.ANDROID_HOME}">
+ <isset property="env.ANDROID_HOME" />
+ </condition>
+
+ <!-- The project.properties file is created and updated by the 'android'
+ tool, as well as ADT.
+
+ This contains project specific properties such as project target, and library
+ dependencies. Lower level build properties are stored in ant.properties
+ (or in .classpath for Eclipse projects).
+
+ This file is an integral part of the build system for your
+ application and should be checked into Version Control Systems. -->
+ <loadproperties srcFile="project.properties" />
+
+ <!-- quick check on sdk.dir -->
+ <fail
+ message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
+ unless="sdk.dir"
+ />
+
+ <!--
+ Import per project custom build rules if present at the root of the project.
+ This is the place to put custom intermediary targets such as:
+ -pre-build
+ -pre-compile
+ -post-compile (This is typically used for code obfuscation.
+ Compiled code location: ${out.classes.absolute.dir}
+ If this is not done in place, override ${out.dex.input.absolute.dir})
+ -post-package
+ -post-build
+ -pre-clean
+ -->
+ <import file="custom_rules.xml" optional="true" />
+
+ <!-- Import the actual build file.
+
+ To customize existing targets, there are two options:
+ - Customize only one target:
+ - copy/paste the target into this file, *before* the
+ <import> task.
+ - customize it to your needs.
+ - Customize the whole content of build.xml
+ - copy/paste the content of the rules files (minus the top node)
+ into this file, replacing the <import> task.
+ - customize to your needs.
+
+ ***********************
+ ****** IMPORTANT ******
+ ***********************
+ In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
+ in order to avoid having your file be overridden by tools such as "android update project"
+ -->
+ <!-- version-tag: 1 -->
+ <import file="${sdk.dir}/tools/ant/build.xml" />
+
+</project>
--- /dev/null
+# 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)
--- /dev/null
+#include <stdlib.h>
+#include <ecl/ecl.h>
+#if ANDROID
+#include <android/log.h>
+#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");
+}
--- /dev/null
+#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
--- /dev/null
+#include <assert.h>
+
+#if ANDROID
+#include <android/log.h>
+#endif
+
+#include <string.h>
+#include <jni.h>
+#include <pthread.h>
+#include <stdio.h>
+
+#include <ecl/ecl.h>
+#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;i<len;i++) {
+ ecl_txt->string.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; i<len; i++) {
+ arr[i] = o->string.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;
+};
--- /dev/null
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* 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
--- /dev/null
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must *NOT* be checked into Version Control Systems,
+# as it contains information specific to your local configuration.
+
+# location of the SDK. This is only used by Ant
+# For customization when using a Version Control System, please read the
+# header note.
+sdk.dir=/home/void/github/android-sdk
--- /dev/null
+# 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 *;
+#}
--- /dev/null
+# 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
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ >
+<TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="Hello World, HelloEclActivity"
+ />
+</LinearLayout>
+
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+ <!-- Single menu item
+ Set id, icon and Title for each menu item
+ -->
+ <item android:id="@+id/menu_uncompress"
+ android:title="Uncompress assets" />
+</menu>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="app_name">HelloEclActivity</string>
+</resources>
--- /dev/null
+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");
+ }
+}
--- /dev/null
+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<files.length; i++)
+ {
+ Log.w(TAG,"Uncompressing: " + files[i]);
+ File fileIn = new File(in,files[i]);
+ File fileOut = new File(out,files[i]);
+
+ try
+ {
+ uncompressFile(fileIn,fileOut);
+ }
+ catch(FileNotFoundException e)
+ {
+ // fileIn is a directory, uncompress the subdir
+ if(!fileOut.isDirectory())
+ {
+ Log.w(TAG,"Creating dir: " + fileOut.getAbsolutePath());
+ fileOut.mkdir();
+ }
+ uncompressDir(fileIn.getPath(), fileOut);
+ }
+ }
+ }
+ catch(IOException e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ // Initiating Menu XML file (menu.xml)
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu)
+ {
+ MenuInflater menuInflater = getMenuInflater();
+ menuInflater.inflate(R.layout.menu, menu);
+ return true;
+ }
+
+ /**
+ * Event Handling for Individual menu item selected
+ * Identify single menu item by it's id
+ * */
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item)
+ {
+ switch (item.getItemId())
+ {
+ case R.id.menu_uncompress:
+ uncompressDir(RESOURCES_DIR,uncompressedFilesDir);
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+ public static String getResourcesPath()
+ {
+ return uncompressedFilesDir.getAbsolutePath();
+ }
+
+ public static void uncompressFile(File fileIn,File fileOut)
+ throws IOException
+ {
+ InputStream in = assetManager.open(fileIn.getPath(),
+ android.content.res.AssetManager.ACCESS_RANDOM);
+ OutputStream out = new FileOutputStream(fileOut);
+
+ byte[] buf = new byte[1024];
+ int len;
+ while ((len = in.read(buf)) > 0)
+ {
+ out.write(buf, 0, len);
+ }
+
+ in.close();
+ out.close();
+ Log.i(TAG,"File copied.");
+ }
+}