Merge commit 'goog/master' into merge_master
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b25c15b
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+*~
diff --git a/adb/adb.c b/adb/adb.c
index 0b5ebac..956df54 100644
--- a/adb/adb.c
+++ b/adb/adb.c
@@ -23,6 +23,7 @@
#include <errno.h>
#include <string.h>
#include <time.h>
+#include <sys/time.h>
#include "sysdeps.h"
#include "adb.h"
@@ -657,10 +658,25 @@
void start_device_log(void)
{
int fd;
- char path[100];
+ char path[PATH_MAX];
+ struct tm now;
+ time_t t;
+ char value[PROPERTY_VALUE_MAX];
- snprintf(path, sizeof path, "/data/adb_%ld.txt", (long)time(NULL));
- fd = unix_open(path, O_WRONLY | O_CREAT | O_APPEND, 0640);
+ // read the trace mask from persistent property persist.adb.trace_mask
+ // give up if the property is not set or cannot be parsed
+ property_get("persist.adb.trace_mask", value, "");
+ if (sscanf(value, "%x", &adb_trace_mask) != 1)
+ return;
+
+ adb_mkdir("/data/adb", 0775);
+ tzset();
+ time(&t);
+ localtime_r(&t, &now);
+ strftime(path, sizeof(path),
+ "/data/adb/adb-%Y-%m-%d-%H-%M-%S.txt",
+ &now);
+ fd = unix_open(path, O_WRONLY | O_CREAT | O_TRUNC, 0640);
if (fd < 0)
return;
@@ -671,11 +687,6 @@
fd = unix_open("/dev/null", O_RDONLY);
dup2(fd, 0);
-
- // log everything
- adb_trace_mask = ~0;
- // except TRACE_RWX is a bit too verbose
- adb_trace_mask &= ~TRACE_RWX;
}
#endif
@@ -875,9 +886,10 @@
** AID_INET to diagnose network issues (netcfg, ping)
** AID_GRAPHICS to access the frame buffer
** AID_NET_BT and AID_NET_BT_ADMIN to diagnose bluetooth (hcidump)
+ ** AID_SDCARD_RW to allow writing to the SD card
*/
gid_t groups[] = { AID_ADB, AID_LOG, AID_INPUT, AID_INET, AID_GRAPHICS,
- AID_NET_BT, AID_NET_BT_ADMIN };
+ AID_NET_BT, AID_NET_BT_ADMIN, AID_SDCARD_RW };
setgroups(sizeof(groups)/sizeof(groups[0]), groups);
/* then switch user and group to "shell" */
@@ -919,9 +931,6 @@
fdevent_loop();
usb_cleanup();
-#if ADB_HOST
- usb_vendors_cleanup();
-#endif
return 0;
}
@@ -1081,9 +1090,8 @@
adb_device_banner = "recovery";
recovery_mode = 1;
}
-#if ADB_DEVICE_LOG
+
start_device_log();
-#endif
return adb_main(0);
#endif
}
diff --git a/adb/adb.h b/adb/adb.h
index 7762e00..b9ed556 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -345,11 +345,6 @@
#endif
-/* set this to log to /data/adb/adb_<time>.txt on the device.
- * has no effect if the /data/adb/ directory does not exist.
- */
-#define ADB_DEVICE_LOG 0
-
#if !TRACE_PACKETS
#define print_packet(tag,p) do {} while (0)
#endif
@@ -357,11 +352,10 @@
#define ADB_PORT 5037
#define ADB_LOCAL_TRANSPORT_PORT 5555
-// Google's USB Vendor ID
-#define VENDOR_ID_GOOGLE 0x18d1
+#define ADB_CLASS 0xff
+#define ADB_SUBCLASS 0x42
+#define ADB_PROTOCOL 0x1
-// HTC's USB Vendor ID
-#define VENDOR_ID_HTC 0x0bb4
void local_init();
int local_connect(int port);
diff --git a/adb/adb_client.c b/adb/adb_client.c
index 5868744..243f0fa 100644
--- a/adb/adb_client.c
+++ b/adb/adb_client.c
@@ -213,7 +213,7 @@
fprintf(stdout,"* daemon started successfully *\n");
}
/* give the server some time to start properly and detect devices */
- adb_sleep_ms(2000);
+ adb_sleep_ms(3000);
// fall through to _adb_connect
} else {
// if server was running, check its version to make sure it is not out of date
diff --git a/adb/transport_usb.c b/adb/transport_usb.c
index 50ebff7..3737c5c 100644
--- a/adb/transport_usb.c
+++ b/adb/transport_usb.c
@@ -135,11 +135,9 @@
unsigned i;
for (i = 0; i < vendorIdCount; i++) {
if (vid == vendorIds[i]) {
- /* class:vendor (0xff) subclass:android (0x42) proto:adb (0x01) */
- if(usb_class == 0xff) {
- if((usb_subclass == 0x42) && (usb_protocol == 0x01)) {
- return 1;
- }
+ if (usb_class == ADB_CLASS && usb_subclass == ADB_SUBCLASS &&
+ usb_protocol == ADB_PROTOCOL) {
+ return 1;
}
return 0;
diff --git a/adb/usb_osx.c b/adb/usb_osx.c
index 171a9fc..4892c38 100644
--- a/adb/usb_osx.c
+++ b/adb/usb_osx.c
@@ -32,9 +32,6 @@
#define DBG D
-#define ADB_SUBCLASS 0x42
-#define ADB_PROTOCOL 0x1
-
static IONotificationPortRef notificationPort = 0;
static io_iterator_t* notificationIterators;
diff --git a/adb/usb_vendors.c b/adb/usb_vendors.c
index f949249..9a15146 100644
--- a/adb/usb_vendors.c
+++ b/adb/usb_vendors.c
@@ -16,25 +16,119 @@
#include "usb_vendors.h"
-#include "sysdeps.h"
#include <stdio.h>
+
+#ifdef _WIN32
+# define WIN32_LEAN_AND_MEAN
+# include "windows.h"
+# include "shlobj.h"
+#else
+# include <unistd.h>
+# include <sys/stat.h>
+#endif
+
+#include "sysdeps.h"
#include "adb.h"
-int* vendorIds = NULL;
+#define ANDROID_PATH ".android"
+#define ANDROID_ADB_INI "adb_usb.ini"
+
+#define TRACE_TAG TRACE_USB
+
+// Google's USB Vendor ID
+#define VENDOR_ID_GOOGLE 0x18d1
+// HTC's USB Vendor ID
+#define VENDOR_ID_HTC 0x0bb4
+
+/** built-in vendor list */
+int builtInVendorIds[] = {
+ VENDOR_ID_GOOGLE,
+ VENDOR_ID_HTC,
+};
+
+#define BUILT_IN_VENDOR_COUNT (sizeof(builtInVendorIds)/sizeof(builtInVendorIds[0]))
+
+/* max number of supported vendor ids (built-in + 3rd party). increase as needed */
+#define VENDOR_COUNT_MAX 128
+
+int vendorIds[VENDOR_COUNT_MAX];
unsigned vendorIdCount = 0;
-void usb_vendors_init(void) {
- /* for now, only put the built-in VENDOR_ID_* */
- vendorIdCount = 2;
- vendorIds = (int*)malloc(vendorIdCount * sizeof(int));
- vendorIds[0] = VENDOR_ID_GOOGLE;
- vendorIds[1] = VENDOR_ID_HTC;
+int get_adb_usb_ini(char* buff, size_t len);
+
+void usb_vendors_init(void)
+{
+ if (VENDOR_COUNT_MAX < BUILT_IN_VENDOR_COUNT) {
+ fprintf(stderr, "VENDOR_COUNT_MAX not big enough for built-in vendor list.\n");
+ exit(2);
+ }
+
+ /* add the built-in vendors at the beginning of the array */
+ memcpy(vendorIds, builtInVendorIds, sizeof(builtInVendorIds));
+
+ /* default array size is the number of built-in vendors */
+ vendorIdCount = BUILT_IN_VENDOR_COUNT;
+
+ if (VENDOR_COUNT_MAX == BUILT_IN_VENDOR_COUNT)
+ return;
+
+ char temp[PATH_MAX];
+ if (get_adb_usb_ini(temp, sizeof(temp)) == 0) {
+ FILE * f = fopen(temp, "rt");
+
+ if (f != NULL) {
+ /* The vendor id file is pretty basic. 1 vendor id per line.
+ Lines starting with # are comments */
+ while (fgets(temp, sizeof(temp), f) != NULL) {
+ if (temp[0] == '#')
+ continue;
+
+ long value = strtol(temp, NULL, 0);
+ if (errno == EINVAL || errno == ERANGE || value > INT_MAX || value < 0) {
+ fprintf(stderr, "Invalid content in %s. Quitting.\n", ANDROID_ADB_INI);
+ exit(2);
+ }
+
+ vendorIds[vendorIdCount++] = (int)value;
+
+ /* make sure we don't go beyond the array */
+ if (vendorIdCount == VENDOR_COUNT_MAX) {
+ break;
+ }
+ }
+ }
+ }
}
-void usb_vendors_cleanup(void) {
- if (vendorIds != NULL) {
- free(vendorIds);
- vendorIds = NULL;
- vendorIdCount = 0;
+/* Utils methods */
+
+/* builds the path to the adb vendor id file. returns 0 if success */
+int build_path(char* buff, size_t len, const char* format, const char* home)
+{
+ if (snprintf(buff, len, format, home, ANDROID_PATH, ANDROID_ADB_INI) >= len) {
+ return 1;
}
+
+ return 0;
+}
+
+/* fills buff with the path to the adb vendor id file. returns 0 if success */
+int get_adb_usb_ini(char* buff, size_t len)
+{
+#ifdef _WIN32
+ const char* home = getenv("ANDROID_SDK_HOME");
+ if (home != NULL) {
+ return build_path(buff, len, "%s\\%s\\%s", home);
+ } else {
+ char path[MAX_PATH];
+ SHGetFolderPath( NULL, CSIDL_PROFILE, NULL, 0, path);
+ return build_path(buff, len, "%s\\%s\\%s", path);
+ }
+#else
+ const char* home = getenv("HOME");
+ if (home == NULL)
+ home = "/tmp";
+
+ return build_path(buff, len, "%s/%s/%s", home);
+#endif
}
diff --git a/adb/usb_vendors.h b/adb/usb_vendors.h
index 43e5f99..43790b9 100644
--- a/adb/usb_vendors.h
+++ b/adb/usb_vendors.h
@@ -17,10 +17,9 @@
#ifndef __USB_VENDORS_H
#define __USB_VENDORS_H
-extern int* vendorIds;
+extern int vendorIds[];
extern unsigned vendorIdCount;
void usb_vendors_init(void);
-void usb_vendors_cleanup(void);
#endif
\ No newline at end of file
diff --git a/include/acc/acc.h b/include/acc/acc.h
new file mode 100644
index 0000000..054d6a0
--- /dev/null
+++ b/include/acc/acc.h
@@ -0,0 +1,78 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_ACC_ACC_H
+#define ANDROID_ACC_ACC_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+typedef char ACCchar;
+typedef int32_t ACCint;
+typedef uint32_t ACCuint;
+typedef ssize_t ACCsizei;
+typedef unsigned int ACCenum;
+typedef void ACCvoid;
+typedef struct ACCscript ACCscript;
+
+#define ACC_NO_ERROR 0x0000
+#define ACC_INVALID_ENUM 0x0500
+#define ACC_INVALID_OPERATION 0x0502
+#define ACC_INVALID_VALUE 0x0501
+#define ACC_OUT_OF_MEMORY 0x0505
+
+#define ACC_COMPILE_STATUS 0x8B81
+#define ACC_INFO_LOG_LENGTH 0x8B84
+
+
+// ----------------------------------------------------------------------------
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ACCscript* accCreateScript();
+
+void accDeleteScript(ACCscript* script);
+
+ACCenum accGetError( ACCscript* script );
+
+void accScriptSource(ACCscript* script,
+ ACCsizei count,
+ const ACCchar** string,
+ const ACCint* length);
+
+void accCompileScript(ACCscript* script);
+
+void accGetScriptiv(ACCscript* script,
+ ACCenum pname,
+ ACCint* params);
+
+void accGetScriptInfoLog(ACCscript* script,
+ ACCsizei maxLength,
+ ACCsizei* length,
+ ACCchar* infoLog);
+
+void accGetScriptLabel(ACCscript* script, const ACCchar * name,
+ ACCvoid** address);
+
+#ifdef __cplusplus
+};
+#endif
+
+// ----------------------------------------------------------------------------
+
+#endif
diff --git a/init/devices.c b/init/devices.c
index 300faab..04ada63 100644
--- a/init/devices.c
+++ b/init/devices.c
@@ -115,6 +115,7 @@
{ "/dev/oncrpc/", 0660, AID_ROOT, AID_SYSTEM, 1 },
{ "/dev/adsp/", 0660, AID_SYSTEM, AID_AUDIO, 1 },
{ "/dev/mt9t013", 0660, AID_SYSTEM, AID_SYSTEM, 0 },
+ { "/dev/msm_camera/", 0660, AID_SYSTEM, AID_SYSTEM, 1 },
{ "/dev/akm8976_daemon",0640, AID_COMPASS, AID_SYSTEM, 0 },
{ "/dev/akm8976_aot", 0640, AID_COMPASS, AID_SYSTEM, 0 },
{ "/dev/akm8976_pffd", 0640, AID_COMPASS, AID_SYSTEM, 0 },
@@ -384,7 +385,10 @@
} else if (!strncmp(uevent->subsystem, "adsp", 4)) {
base = "/dev/adsp/";
mkdir(base, 0755);
- } else if(!strncmp(uevent->subsystem, "input", 5)) {
+ } else if (!strncmp(uevent->subsystem, "msm_camera", 10)) {
+ base = "/dev/msm_camera/";
+ mkdir(base, 0755);
+ } else if(!strncmp(uevent->subsystem, "input", 5)) {
base = "/dev/input/";
mkdir(base, 0755);
} else if(!strncmp(uevent->subsystem, "mtd", 3)) {
diff --git a/libacc/Android.mk b/libacc/Android.mk
index c3207cc..77c71c6 100644
--- a/libacc/Android.mk
+++ b/libacc/Android.mk
@@ -5,8 +5,15 @@
# Shared library
#
-LOCAL_MODULE:= acc
-LOCAL_SRC_FILES := acc.cpp disassem.cpp
-LOCAL_MODULE_TAGS := tests
+LOCAL_MODULE:= libacc
+LOCAL_SRC_FILES := acc.cpp
-include $(BUILD_EXECUTABLE)
+ifeq ($(TARGET_ARCH),arm)
+LOCAL_SRC_FILES += disassem.cpp
+endif
+
+LOCAL_SHARED_LIBRARIES := libdl
+
+include $(BUILD_SHARED_LIBRARY)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
\ No newline at end of file
diff --git a/libacc/LICENSE b/libacc/LICENSE
new file mode 100644
index 0000000..aea41e0
--- /dev/null
+++ b/libacc/LICENSE
@@ -0,0 +1,21 @@
+ Obfuscated Tiny C Compiler
+
+ Copyright (C) 2001-2003 Fabrice Bellard
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product and its documentation
+ *is* required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+
diff --git a/libacc/acc.cpp b/libacc/acc.cpp
index 04d45d5..b7e4594 100644
--- a/libacc/acc.cpp
+++ b/libacc/acc.cpp
@@ -4,33 +4,10 @@
* in scripting environments where speed and memory footprint are important.
*
* This code is based upon the "unobfuscated" version of the
- * Obfuscated Tiny C compiler, and retains the
- * original copyright notice and license from that compiler, see below.
+ * Obfuscated Tiny C compiler, see the file LICENSE for details.
*
*/
-/*
- Obfuscated Tiny C Compiler
-
- Copyright (C) 2001-2003 Fabrice Bellard
-
- This software is provided 'as-is', without any express or implied
- warranty. In no event will the authors be held liable for any damages
- arising from the use of this software.
-
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it
- freely, subject to the following restrictions:
-
- 1. The origin of this software must not be misrepresented; you must not
- claim that you wrote the original software. If you use this software
- in a product, an acknowledgment in the product and its documentation
- *is* required.
- 2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
-
#include <ctype.h>
#include <dlfcn.h>
#include <stdarg.h>
@@ -59,6 +36,13 @@
#include "disassem.h"
#endif
+#include <acc/acc.h>
+
+#define LOG_API(...) do {} while(0)
+// #define LOG_API(...) fprintf (stderr, __VA_ARGS__)
+
+// #define ENABLE_ARM_DISASSEMBLY
+
namespace acc {
class Compiler {
@@ -116,6 +100,27 @@
}
};
+ /**
+ * A code generator creates an in-memory program, generating the code on
+ * the fly. There is one code generator implementation for each supported
+ * architecture.
+ *
+ * The code generator implements the following abstract machine:
+ * R0 - the main accumulator.
+ * R1 - the secondary accumulator.
+ * FP - a frame pointer for accessing function arguments and local
+ * variables.
+ * SP - a stack pointer for storing intermediate results while evaluating
+ * expressions. The stack pointer grows downwards.
+ *
+ * The function calling convention is that all arguments are placed on the
+ * stack such that the first argument has the lowest address.
+ * After the call, the result is in R0. The caller is responsible for
+ * removing the arguments from the stack.
+ * The R0 and R1 registers are not saved across function calls. The
+ * FP and SP registers are saved.
+ */
+
class CodeGenerator {
public:
CodeGenerator() {}
@@ -125,70 +130,170 @@
this->pCodeBuf = pCodeBuf;
}
- /* returns address to patch with local variable size
+ /* Emit a function prolog.
+ * argCount is the number of arguments.
+ * Save the old value of the FP.
+ * Set the new value of the FP.
+ * Convert from the native platform calling convention to
+ * our stack-based calling convention. This may require
+ * pushing arguments from registers to the stack.
+ * Allocate "N" bytes of stack space. N isn't known yet, so
+ * just emit the instructions for adjusting the stack, and return
+ * the address to patch up. The patching will be done in
+ * functionExit().
+ * returns address to patch with local variable size.
*/
virtual int functionEntry(int argCount) = 0;
- virtual void functionExit(int argCount, int localVariableAddress, int localVariableSize) = 0;
+ /* Emit a function epilog.
+ * Restore the old SP and FP register values.
+ * Return to the calling function.
+ * argCount - the number of arguments to the function.
+ * localVariableAddress - returned from functionEntry()
+ * localVariableSize - the size in bytes of the local variables.
+ */
+ virtual void functionExit(int argCount, int localVariableAddress,
+ int localVariableSize) = 0;
- /* load immediate value */
+ /* load immediate value to R0 */
virtual void li(int t) = 0;
+ /* Jump to a target, and return the address of the word that
+ * holds the target data, in case it needs to be fixed up later.
+ */
virtual int gjmp(int t) = 0;
- /* l = 0: je, l == 1: jne */
+ /* Test R0 and jump to a target if the test succeeds.
+ * l = 0: je, l == 1: jne
+ * Return the address of the word that holds the targed data, in
+ * case it needs to be fixed up later.
+ */
virtual int gtst(bool l, int t) = 0;
+ /* Compare R1 against R0, and store the boolean result in R0.
+ * op specifies the comparison.
+ */
virtual void gcmp(int op) = 0;
+ /* Perform the arithmetic op specified by op. R1 is the
+ * left argument, R0 is the right argument.
+ */
virtual void genOp(int op) = 0;
- virtual void clearECX() = 0;
+ /* Set R1 to 0.
+ */
+ virtual void clearR1() = 0;
- virtual void pushEAX() = 0;
+ /* Push R0 onto the stack.
+ */
+ virtual void pushR0() = 0;
- virtual void popECX() = 0;
+ /* Pop R1 off of the stack.
+ */
+ virtual void popR1() = 0;
- virtual void storeEAXToAddressECX(bool isInt) = 0;
+ /* Store R0 to the address stored in R1.
+ * isInt is true if a whole 4-byte integer value
+ * should be stored, otherwise a 1-byte character
+ * value should be stored.
+ */
+ virtual void storeR0ToR1(bool isInt) = 0;
- virtual void loadEAXIndirect(bool isInt) = 0;
+ /* Load R0 from the address stored in R0.
+ * isInt is true if a whole 4-byte integer value
+ * should be loaded, otherwise a 1-byte character
+ * value should be loaded.
+ */
+ virtual void loadR0FromR0(bool isInt) = 0;
- virtual void leaEAX(int ea) = 0;
+ /* Load the absolute address of a variable to R0.
+ * If ea <= LOCAL, then this is a local variable, or an
+ * argument, addressed relative to FP.
+ * else it is an absolute global address.
+ */
+ virtual void leaR0(int ea) = 0;
- virtual void storeEAX(int ea) = 0;
+ /* Store R0 to a variable.
+ * If ea <= LOCAL, then this is a local variable, or an
+ * argument, addressed relative to FP.
+ * else it is an absolute global address.
+ */
+ virtual void storeR0(int ea) = 0;
- virtual void loadEAX(int ea, bool isIncDec, int op) = 0;
+ /* load R0 from a variable.
+ * If ea <= LOCAL, then this is a local variable, or an
+ * argument, addressed relative to FP.
+ * else it is an absolute global address.
+ * If isIncDec is true, then the stored variable's value
+ * should be post-incremented or post-decremented, based
+ * on the value of op.
+ */
+ virtual void loadR0(int ea, bool isIncDec, int op) = 0;
+ /* Emit code to adjust the stack for a function call. Return the
+ * label for the address of the instruction that adjusts the
+ * stack size. This will be passed as argument "a" to
+ * endFunctionCallArguments.
+ */
virtual int beginFunctionCallArguments() = 0;
- virtual void storeEAToArg(int l) = 0;
+ /* Emit code to store R0 to the stack at byte offset l.
+ */
+ virtual void storeR0ToArg(int l) = 0;
+ /* Patch the function call preamble.
+ * a is the address returned from beginFunctionCallArguments
+ * l is the number of bytes the arguments took on the stack.
+ * Typically you would also emit code to convert the argument
+ * list into whatever the native function calling convention is.
+ * On ARM for example you would pop the first 5 arguments into
+ * R0..R4
+ */
virtual void endFunctionCallArguments(int a, int l) = 0;
-
+ /* Emit a call to an unknown function. The argument "symbol" needs to
+ * be stored in the location where the address should go. It forms
+ * a chain. The address will be patched later.
+ * Return the address of the word that has to be patched.
+ */
virtual int callForward(int symbol) = 0;
+ /* Call a function using PC-relative addressing. t is the PC-relative
+ * address of the function. It has already been adjusted for the
+ * architectural jump offset, so just store it as-is.
+ */
virtual void callRelative(int t) = 0;
+ /* Call a function pointer. L is the number of bytes the arguments
+ * take on the stack. The address of the function is stored at
+ * location SP + l.
+ */
virtual void callIndirect(int l) = 0;
+ /* Adjust SP after returning from a function call. l is the
+ * number of bytes of arguments stored on the stack. isIndirect
+ * is true if this was an indirect call. (In which case the
+ * address of the function is stored at location SP + l.)
+ */
virtual void adjustStackAfterCall(int l, bool isIndirect) = 0;
+ /* Print a disassembly of the assembled code to out. Return
+ * non-zero if there is an error.
+ */
virtual int disassemble(FILE* out) = 0;
- /* output a symbol and patch all calls to it */
+ /* Generate a symbol at the current PC. t is the head of a
+ * linked list of addresses to patch.
+ */
virtual void gsym(int t) = 0;
- virtual int finishCompile() {
-#if defined(__arm__)
- const long base = long(pCodeBuf->getBase());
- const long curr = base + long(pCodeBuf->getSize());
- int err = cacheflush(base, curr, 0);
- return err;
-#else
- return 0;
-#endif
- }
+ /*
+ * Do any cleanup work required at the end of a compile.
+ * For example, an instruction cache might need to be
+ * invalidated.
+ * Return non-zero if there is an error.
+ */
+ virtual int finishCompile() = 0;
/**
* Adjust relative branches by this amount.
@@ -214,6 +319,10 @@
intptr_t getPC() {
return pCodeBuf->getPC();
}
+
+ intptr_t getSize() {
+ return pCodeBuf->getSize();
+ }
private:
CodeBuf* pCodeBuf;
};
@@ -228,7 +337,7 @@
/* returns address to patch with local variable size
*/
virtual int functionEntry(int argCount) {
- fprintf(stderr, "functionEntry(%d);\n", argCount);
+ LOG_API(stderr, "functionEntry(%d);\n", argCount);
// sp -> arg4 arg5 ...
// Push our register-based arguments back on the stack
if (argCount > 0) {
@@ -243,7 +352,7 @@
}
virtual void functionExit(int argCount, int localVariableAddress, int localVariableSize) {
- fprintf(stderr, "functionExit(%d, %d, %d);\n", argCount, localVariableAddress, localVariableSize);
+ LOG_API("functionExit(%d, %d, %d);\n", argCount, localVariableAddress, localVariableSize);
// Patch local variable allocation code:
if (localVariableSize < 0 || localVariableSize > 255) {
error("localVariables out of range: %d", localVariableSize);
@@ -270,7 +379,7 @@
/* load immediate value */
virtual void li(int t) {
- fprintf(stderr, "li(%d);\n", t);
+ LOG_API("li(%d);\n", t);
if (t >= 0 && t < 255) {
o4(0xE3A00000 + t); // mov r0, #0
} else if (t >= -256 && t < 0) {
@@ -285,20 +394,20 @@
}
virtual int gjmp(int t) {
- fprintf(stderr, "gjmp(%d);\n", t);
+ LOG_API("gjmp(%d);\n", t);
return o4(0xEA000000 | encodeAddress(t)); // b .L33
}
/* l = 0: je, l == 1: jne */
virtual int gtst(bool l, int t) {
- fprintf(stderr, "gtst(%d, %d);\n", l, t);
+ LOG_API("gtst(%d, %d);\n", l, t);
o4(0xE3500000); // cmp r0,#0
int branch = l ? 0x1A000000 : 0x0A000000; // bne : beq
return o4(branch | encodeAddress(t));
}
virtual void gcmp(int op) {
- fprintf(stderr, "gcmp(%d);\n", op);
+ LOG_API("gcmp(%d);\n", op);
o4(0xE1510000); // cmp r1, r1
switch(op) {
case OP_EQUALS:
@@ -332,7 +441,7 @@
}
virtual void genOp(int op) {
- fprintf(stderr, "genOp(%d);\n", op);
+ LOG_API("genOp(%d);\n", op);
switch(op) {
case OP_MUL:
o4(0x0E0000091); // mul r0,r1,r0
@@ -378,23 +487,23 @@
#endif
}
- virtual void clearECX() {
- fprintf(stderr, "clearECX();\n");
+ virtual void clearR1() {
+ LOG_API("clearR1();\n");
o4(0xE3A01000); // mov r1, #0
}
- virtual void pushEAX() {
- fprintf(stderr, "pushEAX();\n");
+ virtual void pushR0() {
+ LOG_API("pushR0();\n");
o4(0xE92D0001); // stmfd sp!,{r0}
}
- virtual void popECX() {
- fprintf(stderr, "popECX();\n");
+ virtual void popR1() {
+ LOG_API("popR1();\n");
o4(0xE8BD0002); // ldmfd sp!,{r1}
}
- virtual void storeEAXToAddressECX(bool isInt) {
- fprintf(stderr, "storeEAXToAddressECX(%d);\n", isInt);
+ virtual void storeR0ToR1(bool isInt) {
+ LOG_API("storeR0ToR1(%d);\n", isInt);
if (isInt) {
o4(0xE5810000); // str r0, [r1]
} else {
@@ -402,16 +511,16 @@
}
}
- virtual void loadEAXIndirect(bool isInt) {
- fprintf(stderr, "loadEAXIndirect(%d);\n", isInt);
+ virtual void loadR0FromR0(bool isInt) {
+ LOG_API("loadR0FromR0(%d);\n", isInt);
if (isInt)
o4(0xE5900000); // ldr r0, [r0]
else
o4(0xE5D00000); // ldrb r0, [r0]
}
- virtual void leaEAX(int ea) {
- fprintf(stderr, "leaEAX(%d);\n", ea);
+ virtual void leaR0(int ea) {
+ LOG_API("leaR0(%d);\n", ea);
if (ea < LOCAL) {
// Local, fp relative
if (ea < -1023 || ea > 1023 || ((ea & 3) != 0)) {
@@ -431,8 +540,8 @@
}
}
- virtual void storeEAX(int ea) {
- fprintf(stderr, "storeEAX(%d);\n", ea);
+ virtual void storeR0(int ea) {
+ LOG_API("storeR0(%d);\n", ea);
if (ea < LOCAL) {
// Local, fp relative
if (ea < -4095 || ea > 4095) {
@@ -452,8 +561,8 @@
}
}
- virtual void loadEAX(int ea, bool isIncDec, int op) {
- fprintf(stderr, "loadEAX(%d, %d, %d);\n", ea, isIncDec, op);
+ virtual void loadR0(int ea, bool isIncDec, int op) {
+ LOG_API("loadR0(%d, %d, %d);\n", ea, isIncDec, op);
if (ea < LOCAL) {
// Local, fp relative
if (ea < -4095 || ea > 4095) {
@@ -500,12 +609,12 @@
}
virtual int beginFunctionCallArguments() {
- fprintf(stderr, "beginFunctionCallArguments();\n");
+ LOG_API("beginFunctionCallArguments();\n");
return o4(0xE24DDF00); // Placeholder
}
- virtual void storeEAToArg(int l) {
- fprintf(stderr, "storeEAToArg(%d);\n", l);
+ virtual void storeR0ToArg(int l) {
+ LOG_API("storeR0ToArg(%d);\n", l);
if (l < 0 || l > 4096-4) {
error("l out of range for stack offset: 0x%08x", l);
}
@@ -513,7 +622,7 @@
}
virtual void endFunctionCallArguments(int a, int l) {
- fprintf(stderr, "endFunctionCallArguments(0x%08x, %d);\n", a, l);
+ LOG_API("endFunctionCallArguments(0x%08x, %d);\n", a, l);
if (l < 0 || l > 0x3FC) {
error("L out of range for stack adjustment: 0x%08x", l);
}
@@ -526,13 +635,13 @@
}
virtual int callForward(int symbol) {
- fprintf(stderr, "callForward(%d);\n", symbol);
+ LOG_API("callForward(%d);\n", symbol);
// Forward calls are always short (local)
return o4(0xEB000000 | encodeAddress(symbol));
}
virtual void callRelative(int t) {
- fprintf(stderr, "callRelative(%d);\n", t);
+ LOG_API("callRelative(%d);\n", t);
int abs = t + getPC() + jumpOffset();
fprintf(stderr, "abs=%d (0x%08x)\n", abs, abs);
if (t >= - (1 << 25) && t < (1 << 25)) {
@@ -548,7 +657,7 @@
}
virtual void callIndirect(int l) {
- fprintf(stderr, "callIndirect(%d);\n", l);
+ LOG_API("callIndirect(%d);\n", l);
int argCount = l >> 2;
int poppedArgs = argCount > 4 ? 4 : argCount;
int adjustedL = l - (poppedArgs << 2);
@@ -560,7 +669,7 @@
}
virtual void adjustStackAfterCall(int l, bool isIndirect) {
- fprintf(stderr, "adjustStackAfterCall(%d, %d);\n", l, isIndirect);
+ LOG_API("adjustStackAfterCall(%d, %d);\n", l, isIndirect);
int argCount = l >> 2;
int stackArgs = argCount > 4 ? argCount - 4 : 0;
int stackUse = stackArgs + (isIndirect ? 1 : 0);
@@ -578,11 +687,11 @@
/* output a symbol and patch all calls to it */
virtual void gsym(int t) {
- fprintf(stderr, "gsym(0x%x)\n", t);
+ LOG_API("gsym(0x%x)\n", t);
int n;
int base = getBase();
int pc = getPC();
- fprintf(stderr, "pc = 0x%x\n", pc);
+ LOG_API("pc = 0x%x\n", pc);
while (t) {
int data = * (int*) t;
int decodedOffset = ((BRANCH_REL_ADDRESS_MASK & data) << 2);
@@ -597,8 +706,20 @@
}
}
+ virtual int finishCompile() {
+#if defined(__arm__)
+ const long base = long(getBase());
+ const long curr = long(getPC());
+ int err = cacheflush(base, curr, 0);
+ return err;
+#else
+ return 0;
+#endif
+ }
+
virtual int disassemble(FILE* out) {
- disasmOut = out;
+#ifdef ENABLE_ARM_DISASSEMBLY
+ disasmOut = out;
disasm_interface_t di;
di.di_readword = disassemble_readword;
di.di_printaddr = disassemble_printaddr;
@@ -610,6 +731,7 @@
fprintf(out, "%08x: %08x ", i, *(int*) i);
::disasm(&di, i, 0);
}
+#endif
return 0;
}
@@ -679,7 +801,7 @@
}
};
-#endif // PROVIDE_X86_CODEGEN
+#endif // PROVIDE_ARM_CODEGEN
#ifdef PROVIDE_X86_CODEGEN
@@ -730,23 +852,23 @@
o(0x92); /* xchg %edx, %eax */
}
- virtual void clearECX() {
+ virtual void clearR1() {
oad(0xb9, 0); /* movl $0, %ecx */
}
- virtual void pushEAX() {
+ virtual void pushR0() {
o(0x50); /* push %eax */
}
- virtual void popECX() {
+ virtual void popR1() {
o(0x59); /* pop %ecx */
}
- virtual void storeEAXToAddressECX(bool isInt) {
+ virtual void storeR0ToR1(bool isInt) {
o(0x0188 + isInt); /* movl %eax/%al, (%ecx) */
}
- virtual void loadEAXIndirect(bool isInt) {
+ virtual void loadR0FromR0(bool isInt) {
if (isInt)
o(0x8b); /* mov (%eax), %eax */
else
@@ -754,15 +876,15 @@
ob(0); /* add zero in code */
}
- virtual void leaEAX(int ea) {
+ virtual void leaR0(int ea) {
gmov(10, ea); /* leal EA, %eax */
}
- virtual void storeEAX(int ea) {
+ virtual void storeR0(int ea) {
gmov(6, ea); /* mov %eax, EA */
}
- virtual void loadEAX(int ea, bool isIncDec, int op) {
+ virtual void loadR0(int ea, bool isIncDec, int op) {
gmov(8, ea); /* mov EA, %eax */
if (isIncDec) {
/* Implement post-increment or post decrement.
@@ -776,7 +898,7 @@
return oad(0xec81, 0); /* sub $xxx, %esp */
}
- virtual void storeEAToArg(int l) {
+ virtual void storeR0ToArg(int l) {
oad(0x248489, l); /* movl %eax, xxx(%esp) */
}
@@ -808,7 +930,7 @@
}
virtual int disassemble(FILE* out) {
- return 1;
+ return 0;
}
/* output a symbol and patch all calls to it */
@@ -822,6 +944,10 @@
}
}
+ virtual int finishCompile() {
+ return 0;
+ }
+
private:
/** Output 1 to 4 bytes.
@@ -868,6 +994,39 @@
#endif // PROVIDE_X86_CODEGEN
+ class InputStream {
+ public:
+ virtual int get() = 0;
+ virtual long tell() = 0;
+ };
+
+ class FileInputStream : public InputStream {
+ public:
+ FileInputStream(FILE* in) : f(in) {}
+ virtual int get() { return fgetc(f); }
+ virtual long tell() { return ftell(f); }
+ private:
+ FILE* f;
+ };
+
+ class TextInputStream : public InputStream {
+ public:
+ TextInputStream(const char* text, size_t textLength)
+ : pText(text), mTextLength(textLength), mPosition(0) {
+ }
+ virtual int get() {
+ return mPosition < mTextLength ? pText[mPosition++] : EOF;
+ }
+ virtual long tell() {
+ return mPosition;
+ }
+
+ private:
+ const char* pText;
+ size_t mTextLength;
+ size_t mPosition;
+ };
+
/* vars: value of variables
loc : local variable index
glo : global variable index
@@ -882,7 +1041,8 @@
void* pSymbolBase;
void* pGlobalBase;
void* pVarsBase;
- FILE* file;
+
+ InputStream* file;
CodeBuf codeBuf;
CodeGenerator* pGen;
@@ -957,7 +1117,7 @@
ch = dch;
}
} else
- ch = fgetc(file);
+ ch = file->get();
/* printf("ch=%c 0x%x\n", ch, ch); */
}
@@ -1108,7 +1268,7 @@
va_list ap;
va_start(ap, fmt);
- fprintf(stderr, "%ld: ", ftell((FILE *) file));
+ fprintf(stderr, "%ld: ", file->tell());
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
va_end(ap);
@@ -1149,7 +1309,7 @@
} else if (c == 2) {
/* -, +, !, ~ */
unary(0);
- pGen->clearECX();
+ pGen->clearR1();
if (t == '!')
pGen->gcmp(a);
else
@@ -1175,15 +1335,15 @@
unary(0);
if (tok == '=') {
next();
- pGen->pushEAX();
+ pGen->pushR0();
expr();
- pGen->popECX();
- pGen->storeEAXToAddressECX(t == TOK_INT);
+ pGen->popR1();
+ pGen->storeR0ToR1(t == TOK_INT);
} else if (t) {
- pGen->loadEAXIndirect(t == TOK_INT);
+ pGen->loadR0FromR0(t == TOK_INT);
}
} else if (t == '&') {
- pGen->leaEAX(*(int *) tok);
+ pGen->leaR0(*(int *) tok);
next();
} else {
n = *(int *) t;
@@ -1195,10 +1355,10 @@
/* assignment */
next();
expr();
- pGen->storeEAX(n);
+ pGen->storeR0(n);
} else if (tok != '(') {
/* variable */
- pGen->loadEAX(n, tokl == 11, tokc);
+ pGen->loadR0(n, tokl == 11, tokc);
if (tokl == 11) {
next();
}
@@ -1209,7 +1369,7 @@
/* function call */
if (tok == '(') {
if (n == 1)
- pGen->pushEAX();
+ pGen->pushR0();
/* push args and invert order */
a = pGen->beginFunctionCallArguments();
@@ -1217,7 +1377,7 @@
l = 0;
while (tok != ')') {
expr();
- pGen->storeEAToArg(l);
+ pGen->storeR0ToArg(l);
if (tok == ',')
next();
l = l + 4;
@@ -1255,9 +1415,9 @@
a = pGen->gtst(t == OP_LOGICAL_OR, a); /* && and || output code generation */
sum(l);
} else {
- pGen->pushEAX();
+ pGen->pushR0();
sum(l);
- pGen->popECX();
+ pGen->popR1();
if ((l == 4) | (l == 5)) {
pGen->gcmp(t);
@@ -1420,6 +1580,10 @@
delete pGen;
pGen = 0;
}
+ if (file) {
+ delete file;
+ file = 0;
+ }
}
void clear() {
@@ -1470,7 +1634,7 @@
#endif
}
if (pGen == NULL) {
- fprintf(stderr, "No code generator defined.");
+ fprintf(stderr, "No code generator defined.\n");
}
}
@@ -1490,16 +1654,16 @@
cleanup();
}
- int compile(FILE* in, args& args) {
+ int compile(const char* text, size_t textLength) {
cleanup();
clear();
codeBuf.init(ALLOC_SIZE);
- setArchitecture(args.architecture);
+ setArchitecture(NULL);
if (!pGen) {
return -1;
}
pGen->init(&codeBuf);
- file = in;
+ file = new TextInputStream(text, textLength);
sym_stk = (intptr_t) calloc(1, ALLOC_SIZE);
dstk = (intptr_t) strcpy((char*) sym_stk,
" int if else while break return for define main ")
@@ -1534,6 +1698,38 @@
return pGen->disassemble(out);
}
+ /* Look through the symbol table to find a symbol.
+ * If found, return its value.
+ */
+ void* lookup(const char* name) {
+ if (!sym_stk) {
+ return NULL;
+ }
+ size_t nameLen = strlen(name);
+ char* pSym = (char*) sym_stk;
+ char c;
+ for(;;) {
+ c = *pSym++;
+ if (c == 0) {
+ break;
+ }
+ if (c == TAG_TOK) {
+ if (memcmp(pSym, name, nameLen) == 0
+ && pSym[nameLen] == TAG_TOK) {
+ int tok = pSym - 1 - (char*) sym_stk;
+ tok = tok * 8 + TOK_IDENT;
+ if (tok <= TOK_DEFINE) {
+ return 0;
+ } else {
+ tok = vars + tok;
+ return * (void**) tok;
+ }
+ }
+ }
+ }
+ return NULL;
+ }
+
};
const char* Compiler::operatorChars =
@@ -1578,96 +1774,130 @@
};
#endif
-} // namespace acc
+struct ACCscript {
+ ACCscript() {
+ text = 0;
+ textLength = 0;
+ accError = ACC_NO_ERROR;
+ }
-// This is a separate function so it can easily be set by breakpoint in gdb.
-int run(acc::Compiler& c, int argc, char** argv) {
- return c.run(argc, argv);
-}
+ ~ACCscript() {
+ delete text;
+ }
-int main(int argc, char** argv) {
- bool doDump = false;
- bool doDisassemble = false;
- const char* inFile = NULL;
- const char* outFile = NULL;
- const char* architecture = NULL;
- int i;
- for (i = 1; i < argc; i++) {
- char* arg = argv[i];
- if (arg[0] == '-') {
- switch (arg[1]) {
- case 'a':
- if (i + 1 >= argc) {
- fprintf(stderr, "Expected architecture after -a\n");
- return 2;
- }
- architecture = argv[i+1];
- i += 1;
- break;
- case 'd':
- if (i + 1 >= argc) {
- fprintf(stderr, "Expected filename after -d\n");
- return 2;
- }
- doDump = true;
- outFile = argv[i + 1];
- i += 1;
- break;
- case 'S':
- doDisassemble = true;
- break;
- default:
- fprintf(stderr, "Unrecognized flag %s\n", arg);
- return 3;
- }
- } else if (inFile == NULL) {
- inFile = arg;
- } else {
- break;
+ void setError(ACCenum error) {
+ if (accError == ACC_NO_ERROR && error != ACC_NO_ERROR) {
+ accError = error;
}
}
- FILE* in = stdin;
- if (inFile) {
- in = fopen(inFile, "r");
- if (!in) {
- fprintf(stderr, "Could not open input file %s\n", inFile);
- return 1;
- }
- }
- acc::Compiler compiler;
- acc::Compiler::args args;
- if (architecture != NULL) {
- args.architecture = architecture;
- }
- int compileResult = compiler.compile(in, args);
- if (in != stdin) {
- fclose(in);
- }
- if (compileResult) {
- fprintf(stderr, "Compile failed: %d\n", compileResult);
- return 6;
- }
- if (doDisassemble) {
- compiler.disassemble(stderr);
- }
- if (doDump) {
- FILE* save = fopen(outFile, "w");
- if (!save) {
- fprintf(stderr, "Could not open output file %s\n", outFile);
- return 5;
- }
- compiler.dump(save);
- fclose(save);
- } else {
- fprintf(stderr, "Executing compiled code:\n");
- int codeArgc = argc - i + 1;
- char** codeArgv = argv + i - 1;
- codeArgv[0] = (char*) (inFile ? inFile : "stdin");
- int result = run(compiler, codeArgc, codeArgv);
- fprintf(stderr, "result: %d\n", result);
+ ACCenum getError() {
+ ACCenum result = accError;
+ accError = ACC_NO_ERROR;
return result;
}
- return 0;
+ Compiler compiler;
+ char* text;
+ int textLength;
+ ACCenum accError;
+};
+
+
+extern "C"
+ACCscript* accCreateScript() {
+ return new ACCscript();
}
+
+extern "C"
+ACCenum accGetError( ACCscript* script ) {
+ return script->getError();
+}
+
+extern "C"
+void accDeleteScript(ACCscript* script) {
+ delete script;
+}
+
+extern "C"
+void accScriptSource(ACCscript* script,
+ ACCsizei count,
+ const ACCchar ** string,
+ const ACCint * length) {
+ int totalLength = 0;
+ for(int i = 0; i < count; i++) {
+ int len = -1;
+ const ACCchar* s = string[i];
+ if (length) {
+ len = length[i];
+ }
+ if (len < 0) {
+ len = strlen(s);
+ }
+ totalLength += len;
+ }
+ delete script->text;
+ char* text = new char[totalLength + 1];
+ script->text = text;
+ script->textLength = totalLength;
+ char* dest = text;
+ for(int i = 0; i < count; i++) {
+ int len = -1;
+ const ACCchar* s = string[i];
+ if (length) {
+ len = length[i];
+ }
+ if (len < 0) {
+ len = strlen(s);
+ }
+ memcpy(dest, s, len);
+ dest += len;
+ }
+ text[totalLength] = '\0';
+}
+
+extern "C"
+void accCompileScript(ACCscript* script) {
+ int result = script->compiler.compile(script->text, script->textLength);
+ if (result) {
+ script->setError(ACC_INVALID_OPERATION);
+ }
+}
+
+extern "C"
+void accGetScriptiv(ACCscript* script,
+ ACCenum pname,
+ ACCint * params) {
+ switch (pname) {
+ case ACC_INFO_LOG_LENGTH:
+ *params = 0;
+ break;
+ }
+}
+
+extern "C"
+void accGetScriptInfoLog(ACCscript* script,
+ ACCsizei maxLength,
+ ACCsizei * length,
+ ACCchar * infoLog) {
+ if (length) {
+ *length = 0;
+ }
+ if (maxLength > 0 && infoLog) {
+ *infoLog = 0;
+ }
+}
+
+extern "C"
+void accGetScriptLabel(ACCscript* script, const ACCchar * name,
+ ACCvoid ** address) {
+ void* value = script->compiler.lookup(name);
+ if (value) {
+ *address = value;
+ } else {
+ script->setError(ACC_INVALID_VALUE);
+ }
+}
+
+} // namespace acc
+
diff --git a/libacc/test b/libacc/test
deleted file mode 100755
index 28b7655..0000000
--- a/libacc/test
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/bin/sh
-rm -f tests/acc
-g++ acc.cpp disassem.cpp -g -ldl -o tests/acc && tests/acc tests/otcc.c -a x86 -d tests/otcc.out && diff tests/otcc.out tests/otcc.out-orig
-if [ -x "tests/acc" ]; then
- tests/acc -S tests/returnval.c
-
- if [ "$(uname)" = "Linux" ]; then
- if [ "$(uname -m)" = "i686" ]; then
- echo "Linux i686. Testing otcc.c"
- tests/acc tests/otcc.c tests/otcc.c tests/returnval.c
- fi
- fi
-fi
diff --git a/libacc/testarm b/libacc/testarm
deleted file mode 100755
index d1a442e..0000000
--- a/libacc/testarm
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/sh
-adb remount
-adb push tests/returnval.c /system/bin/returnval.c
-mm -j8 && adb sync && adb shell /system/bin/acc -S /system/bin/returnval.c
diff --git a/libacc/tests/.gitignore b/libacc/tests/.gitignore
index 9974532..a26b298 100644
--- a/libacc/tests/.gitignore
+++ b/libacc/tests/.gitignore
@@ -1,2 +1,2 @@
-acc
+test-acc
*.out
diff --git a/libacc/tests/Android.mk b/libacc/tests/Android.mk
new file mode 100644
index 0000000..2cff9d3
--- /dev/null
+++ b/libacc/tests/Android.mk
@@ -0,0 +1,15 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ main.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+ libacc
+
+LOCAL_MODULE:= acc
+
+LOCAL_MODULE_TAGS := tests
+
+include $(BUILD_EXECUTABLE)
+
diff --git a/libacc/tests/bellard.otccex.c b/libacc/tests/data/bellard.otccex.c
similarity index 100%
rename from libacc/tests/bellard.otccex.c
rename to libacc/tests/data/bellard.otccex.c
diff --git a/libacc/tests/expr.c b/libacc/tests/data/expr.c
similarity index 100%
rename from libacc/tests/expr.c
rename to libacc/tests/data/expr.c
diff --git a/libacc/tests/hello.c b/libacc/tests/data/hello.c
similarity index 100%
rename from libacc/tests/hello.c
rename to libacc/tests/data/hello.c
diff --git a/libacc/tests/missing-main.c b/libacc/tests/data/missing-main.c
similarity index 100%
rename from libacc/tests/missing-main.c
rename to libacc/tests/data/missing-main.c
diff --git a/libacc/tests/otcc.c b/libacc/tests/data/otcc.c
similarity index 100%
rename from libacc/tests/otcc.c
rename to libacc/tests/data/otcc.c
diff --git a/libacc/tests/returnval.c b/libacc/tests/data/returnval.c
similarity index 100%
rename from libacc/tests/returnval.c
rename to libacc/tests/data/returnval.c
diff --git a/libacc/tests/simplest.c b/libacc/tests/data/simplest.c
similarity index 100%
rename from libacc/tests/simplest.c
rename to libacc/tests/data/simplest.c
diff --git a/libacc/tests/hello.out-orig b/libacc/tests/hello.out-orig
deleted file mode 100644
index 1fb7bf5..0000000
--- a/libacc/tests/hello.out-orig
+++ /dev/null
Binary files differ
diff --git a/libacc/tests/main.cpp b/libacc/tests/main.cpp
new file mode 100644
index 0000000..8cfc196
--- /dev/null
+++ b/libacc/tests/main.cpp
@@ -0,0 +1,102 @@
+/*
+ * Android "Almost" C Compiler.
+ * This is a compiler for a small subset of the C language, intended for use
+ * in scripting environments where speed and memory footprint are important.
+ *
+ * This code is based upon the "unobfuscated" version of the
+ * Obfuscated Tiny C compiler, see the file LICENSE for details.
+ *
+ */
+
+#include <ctype.h>
+#include <dlfcn.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if defined(__arm__)
+#include <unistd.h>
+#endif
+
+#include <acc/acc.h>
+
+
+typedef int (*MainPtr)(int, char**);
+// This is a separate function so it can easily be set by breakpoint in gdb.
+int run(MainPtr mainFunc, int argc, char** argv) {
+ return mainFunc(argc, argv);
+}
+
+int main(int argc, char** argv) {
+ const char* inFile = NULL;
+ bool printListing;
+ FILE* in = stdin;
+ int i;
+ for (i = 1; i < argc; i++) {
+ char* arg = argv[i];
+ if (arg[0] == '-') {
+ switch (arg[1]) {
+ case 'S':
+ printListing = true;
+ break;
+ default:
+ fprintf(stderr, "Unrecognized flag %s\n", arg);
+ return 3;
+ }
+ } else if (inFile == NULL) {
+ inFile = arg;
+ } else {
+ break;
+ }
+ }
+
+ if (! inFile) {
+ fprintf(stderr, "input file required\n");
+ return 2;
+ }
+
+ if (inFile) {
+ in = fopen(inFile, "r");
+ if (!in) {
+ fprintf(stderr, "Could not open input file %s\n", inFile);
+ return 1;
+ }
+ }
+
+ fseek(in, 0, SEEK_END);
+ size_t fileSize = (size_t) ftell(in);
+ rewind(in);
+ ACCchar* text = new ACCchar[fileSize];
+ size_t bytesRead = fread(text, 1, fileSize, in);
+ if (bytesRead != fileSize) {
+ fprintf(stderr, "Could not read all of file %s\n", inFile);
+ }
+
+ ACCscript* script = accCreateScript();
+
+ const ACCchar* scriptSource[] = {text};
+ accScriptSource(script, 1, scriptSource, NULL);
+ delete[] text;
+
+ accCompileScript(script);
+
+ MainPtr mainPointer = 0;
+
+ accGetScriptLabel(script, "main", (ACCvoid**) & mainPointer);
+
+ int result = accGetError(script);
+ if (result == ACC_NO_ERROR) {
+ fprintf(stderr, "Executing compiled code:\n");
+ int codeArgc = argc - i + 1;
+ char** codeArgv = argv + i - 1;
+ codeArgv[0] = (char*) (inFile ? inFile : "stdin");
+ result = run(mainPointer, codeArgc, codeArgv);
+ fprintf(stderr, "result: %d\n", result);
+ }
+
+ accDeleteScript(script);
+
+ return result;
+}
diff --git a/libacc/tests/otcc.out-orig b/libacc/tests/otcc.out-orig
deleted file mode 100644
index fa14c72..0000000
--- a/libacc/tests/otcc.out-orig
+++ /dev/null
Binary files differ
diff --git a/libacc/tests/testarm b/libacc/tests/testarm
new file mode 100755
index 0000000..db7ebe5
--- /dev/null
+++ b/libacc/tests/testarm
@@ -0,0 +1,9 @@
+#!/bin/sh
+adb remount
+adb shell rm /system/bin/acc
+adb push data/returnval.c /system/bin/returnval.c
+cd ..
+mm -j8
+cd tests
+adb sync
+adb shell /system/bin/acc -S /system/bin/returnval.c
diff --git a/libacc/tests/testlocal b/libacc/tests/testlocal
new file mode 100755
index 0000000..a76322b
--- /dev/null
+++ b/libacc/tests/testlocal
@@ -0,0 +1,15 @@
+#!/bin/sh
+rm -f test-acc
+cd ..
+g++ -I../include acc.cpp disassem.cpp tests/main.cpp -g -ldl -o tests/test-acc
+cd tests
+if [ -x "test-acc" ]; then
+ ./test-acc -S data/returnval.c
+
+ if [ "$(uname)" = "Linux" ]; then
+ if [ "$(uname -m)" = "i686" ]; then
+ echo "Linux i686. Testing otcc.c"
+ ./test-acc data/otcc.c data/otcc.c data/returnval.c
+ fi
+ fi
+fi
diff --git a/libcutils/Android.mk b/libcutils/Android.mk
index aaee8bf..087d652 100644
--- a/libcutils/Android.mk
+++ b/libcutils/Android.mk
@@ -17,7 +17,6 @@
include $(CLEAR_VARS)
commonSources := \
- abort_socket.c \
array.c \
hashmap.c \
atomic.c \
@@ -45,22 +44,23 @@
# some files must not be compiled when building against Mingw
# they correspond to features not used by our host development tools
# which are also hard or even impossible to port to native Win32
-WITH_MINGW :=
+WINDOWS_HOST_ONLY :=
ifeq ($(HOST_OS),windows)
ifeq ($(strip $(USE_CYGWIN)),)
- WITH_MINGW := 1
+ WINDOWS_HOST_ONLY := 1
endif
endif
# USE_MINGW is defined when we build against Mingw on Linux
ifneq ($(strip $(USE_MINGW)),)
- WITH_MINGW := 1
+ WINDOWS_HOST_ONLY := 1
endif
-ifeq ($(WITH_MINGW),1)
+ifeq ($(WINDOWS_HOST_ONLY),1)
commonSources += \
uio.c
else
commonSources += \
+ abort_socket.c \
mspace.c \
selector.c \
tztime.c \
diff --git a/libcutils/abort_socket.c b/libcutils/abort_socket.c
index d732142..6a5e5e4 100644
--- a/libcutils/abort_socket.c
+++ b/libcutils/abort_socket.c
@@ -239,7 +239,7 @@
}
if (pfd[0].revents) {
- if (pfd[0].revents & POLLIN) {
+ if (pfd[0].revents & POLLOUT) {
/* ready to write() without blocking */
do {
ret = write(s->fd, buf, count);
diff --git a/nexus/CommandListener.cpp b/nexus/CommandListener.cpp
index fdf3fed..5b03357 100644
--- a/nexus/CommandListener.cpp
+++ b/nexus/CommandListener.cpp
@@ -33,54 +33,19 @@
CommandListener::CommandListener() :
FrameworkListener("nexus") {
- registerCmd(new WifiEnableCmd());
- registerCmd(new WifiDisableCmd());
- registerCmd(new WifiScanCmd());
registerCmd(new WifiScanResultsCmd());
registerCmd(new WifiListNetworksCmd());
registerCmd(new WifiAddNetworkCmd());
registerCmd(new WifiRemoveNetworkCmd());
- registerCmd(new WifiSetVarCmd());
- registerCmd(new WifiGetVarCmd());
- registerCmd(new VpnEnableCmd());
- registerCmd(new VpnSetVarCmd());
- registerCmd(new VpnGetVarCmd());
- registerCmd(new VpnDisableCmd());
+ registerCmd(new GetCmd());
+ registerCmd(new SetCmd());
}
/* -------------
* Wifi Commands
* ------------ */
-CommandListener::WifiEnableCmd::WifiEnableCmd() :
- NexusCommand("wifi_enable") {
-}
-
-int CommandListener::WifiEnableCmd::runCommand(SocketClient *cli, char *data) {
- Controller *c = NetworkManager::Instance()->findController("WIFI");
-
- if (c->enable())
- cli->sendMsg(ErrorCode::OperationFailed, "Failed to enable wifi", true);
- else
- cli->sendMsg(ErrorCode::CommandOkay, "Wifi Enabled", false);
- return 0;
-}
-
-CommandListener::WifiDisableCmd::WifiDisableCmd() :
- NexusCommand("wifi_disable") {
-}
-
-int CommandListener::WifiDisableCmd::runCommand(SocketClient *cli, char *data) {
- Controller *c = NetworkManager::Instance()->findController("WIFI");
-
- if (c->disable())
- cli->sendMsg(ErrorCode::OperationFailed, "Failed to disable wifi", true);
- else
- cli->sendMsg(ErrorCode::CommandOkay, "Wifi Disabled", false);
- return 0;
-}
-
CommandListener::WifiAddNetworkCmd::WifiAddNetworkCmd() :
NexusCommand("wifi_add_network") {
}
@@ -116,21 +81,6 @@
return 0;
}
-CommandListener::WifiScanCmd::WifiScanCmd() :
- NexusCommand("wifi_scan") {
-}
-
-int CommandListener::WifiScanCmd::runCommand(SocketClient *cli, char *data) {
- WifiController *wc = (WifiController *) NetworkManager::Instance()->findController("WIFI");
-
- if (wc->setScanMode(atoi(data)))
- cli->sendMsg(ErrorCode::OperationFailed, "Failed to set scan mode", true);
- else
- cli->sendMsg(ErrorCode::CommandOkay, "Scan mode set", false);
-
- return 0;
-}
-
CommandListener::WifiScanResultsCmd::WifiScanResultsCmd() :
NexusCommand("wifi_scan_results") {
}
@@ -181,158 +131,39 @@
return 0;
}
-CommandListener::WifiSetVarCmd::WifiSetVarCmd() :
- NexusCommand("wifi_setvar") {
-}
-
-int CommandListener::WifiSetVarCmd::runCommand(SocketClient *cli, char *data) {
- WifiController *wc = (WifiController *) NetworkManager::Instance()->findController("WIFI");
-
- char *bword;
- char *last;
- char varname[32];
- char val[250];
- int networkId;
-
- if (!(bword = strtok_r(data, ":", &last)))
- goto out_inval;
-
- networkId = atoi(bword);
-
- if (!(bword = strtok_r(NULL, ":", &last)))
- goto out_inval;
-
- strncpy(varname, bword, sizeof(varname));
-
- if (!(bword = strtok_r(NULL, ":", &last)))
- goto out_inval;
-
- strncpy(val, bword, sizeof(val));
-
- LOGD("Network id %d, varname '%s', value '%s'", networkId, varname, val);
-
- return 0;
-
-out_inval:
- errno = EINVAL;
- cli->sendMsg(ErrorCode::CommandParameterError, "Failed to set variable.", true);
- return 0;
-}
-
-CommandListener::WifiGetVarCmd::WifiGetVarCmd() :
- NexusCommand("wifi_getvar") {
-}
-
-int CommandListener::WifiGetVarCmd::runCommand(SocketClient *cli, char *data) {
- WifiController *wc = (WifiController *) NetworkManager::Instance()->findController("WIFI");
-
- char *bword;
- char *last;
- char varname[32];
- int networkId;
-
- if (!(bword = strtok_r(data, ":", &last)))
- goto out_inval;
-
- networkId = atoi(bword);
-
- if (!(bword = strtok_r(NULL, ":", &last)))
- goto out_inval;
-
- strncpy(varname, bword, sizeof(varname));
-
- LOGD("networkId = %d, varname '%s'", networkId, varname);
-
- return 0;
-out_inval:
- errno = EINVAL;
- cli->sendMsg(ErrorCode::CommandParameterError, "Failed to get variable.", true);
- return 0;
-}
-
/* ------------
* Vpn Commands
* ------------ */
-CommandListener::VpnEnableCmd::VpnEnableCmd() :
- NexusCommand("vpn_enable") {
-}
-
-int CommandListener::VpnEnableCmd::runCommand(SocketClient *cli, char *data) {
- Controller *c = NetworkManager::Instance()->findController("VPN");
- if (c->enable())
- cli->sendMsg(ErrorCode::OperationFailed, "Failed to enable VPN", true);
- else
- cli->sendMsg(ErrorCode::CommandOkay, "VPN enabled", false);
- return 0;
-}
-
-CommandListener::VpnSetVarCmd::VpnSetVarCmd() :
- NexusCommand("vpn_setvar") {
+/* ----------------
+ * Generic Commands
+ * ---------------- */
+CommandListener::GetCmd::GetCmd() :
+ NexusCommand("get") {
}
-int CommandListener::VpnSetVarCmd::runCommand(SocketClient *cli, char *data) {
- VpnController *vc = (VpnController *) NetworkManager::Instance()->findController("VPN");
-
+int CommandListener::GetCmd::runCommand(SocketClient *cli, char *data) {
char *bword;
char *last;
- char varname[32];
- char val[250];
-
- if (!(bword = strtok_r(data, ":", &last)))
- goto out_inval;
-
- strncpy(varname, bword, sizeof(varname));
-
- if (!(bword = strtok_r(NULL, ":", &last)))
- goto out_inval;
-
- strncpy(val, bword, sizeof(val));
-
- if (!strcasecmp(varname, "vpn_gateway")) {
- if (vc->setVpnGateway(val))
- goto out_inval;
- } else {
- cli->sendMsg(ErrorCode::CommandParameterError, "Variable not found.", true);
- return 0;
- }
-
- cli->sendMsg(ErrorCode::CommandOkay, "Variable written.", false);
- return 0;
-
-out_inval:
- errno = EINVAL;
- cli->sendMsg(ErrorCode::CommandParameterError, "Failed to set variable.", true);
- return 0;
-}
-
-CommandListener::VpnGetVarCmd::VpnGetVarCmd() :
- NexusCommand("vpn_getvar") {
-}
-
-int CommandListener::VpnGetVarCmd::runCommand(SocketClient *cli, char *data) {
- VpnController *vc = (VpnController *) NetworkManager::Instance()->findController("VPN");
-
- char *bword;
- char *last;
- char varname[32];
+ char propname[32];
if (!(bword = strtok_r(data, ":", &last)))
goto out_inval;
- strncpy(varname, bword, sizeof(varname));
+ strncpy(propname, bword, sizeof(propname));
- if (!strcasecmp(varname, "vpn_gateway")) {
- char buffer[255];
+ char pb[255];
+ snprintf(pb, sizeof(pb), "%s:", propname);
- sprintf(buffer, "%s:%s", varname, inet_ntoa(vc->getVpnGateway()));
- cli->sendMsg(ErrorCode::VariableRead, buffer, false);
- } else {
- cli->sendMsg(ErrorCode::CommandParameterError, "Variable not found.", true);
- return 0;
+ if (!NetworkManager::Instance()->getProperty(propname,
+ &pb[strlen(pb)],
+ sizeof(pb) - strlen(pb))) {
+ goto out_inval;
}
- cli->sendMsg(ErrorCode::CommandOkay, "Variable read.", false);
+ cli->sendMsg(ErrorCode::VariableRead, pb, false);
+
+ cli->sendMsg(ErrorCode::CommandOkay, "Property read.", false);
return 0;
out_inval:
errno = EINVAL;
@@ -340,16 +171,34 @@
return 0;
}
-CommandListener::VpnDisableCmd::VpnDisableCmd() :
- NexusCommand("vpn_disable") {
-}
-
-int CommandListener::VpnDisableCmd::runCommand(SocketClient *cli, char *data) {
- Controller *c = NetworkManager::Instance()->findController("VPN");
+CommandListener::SetCmd::SetCmd() :
+ NexusCommand("set") {
+}
- if (c->disable())
- cli->sendMsg(ErrorCode::OperationFailed, "Failed to disable VPN", true);
- else
- cli->sendMsg(ErrorCode::CommandOkay, "VPN disabled", false);
+int CommandListener::SetCmd::runCommand(SocketClient *cli, char *data) {
+ char *bword;
+ char *last;
+ char propname[32];
+ char propval[250];
+
+ if (!(bword = strtok_r(data, ":", &last)))
+ goto out_inval;
+
+ strncpy(propname, bword, sizeof(propname));
+
+ if (!(bword = strtok_r(NULL, ":", &last)))
+ goto out_inval;
+
+ strncpy(propval, bword, sizeof(propval));
+
+ if (NetworkManager::Instance()->setProperty(propname, propval))
+ goto out_inval;
+
+ cli->sendMsg(ErrorCode::CommandOkay, "Property set.", false);
+ return 0;
+
+out_inval:
+ errno = EINVAL;
+ cli->sendMsg(ErrorCode::CommandParameterError, "Failed to set property.", true);
return 0;
}
diff --git a/nexus/CommandListener.h b/nexus/CommandListener.h
index a44aa29..6973aaa 100644
--- a/nexus/CommandListener.h
+++ b/nexus/CommandListener.h
@@ -25,19 +25,6 @@
virtual ~CommandListener() {}
private:
- class WifiEnableCmd : public NexusCommand {
- public:
- WifiEnableCmd();
- virtual ~WifiEnableCmd() {}
- int runCommand(SocketClient *c, char *data);
- };
-
- class WifiDisableCmd : public NexusCommand {
- public:
- WifiDisableCmd();
- virtual ~WifiDisableCmd() {}
- int runCommand(SocketClient *c, char *data);
- };
class WifiScanCmd : public NexusCommand {
public:
@@ -74,48 +61,19 @@
int runCommand(SocketClient *c, char *data);
};
- class WifiSetVarCmd : public NexusCommand {
+ class SetCmd : public NexusCommand {
public:
- WifiSetVarCmd();
- virtual ~WifiSetVarCmd() {}
+ SetCmd();
+ virtual ~SetCmd() {}
int runCommand(SocketClient *c, char *data);
};
- class WifiGetVarCmd : public NexusCommand {
+ class GetCmd : public NexusCommand {
public:
- WifiGetVarCmd();
- virtual ~WifiGetVarCmd() {}
+ GetCmd();
+ virtual ~GetCmd() {}
int runCommand(SocketClient *c, char *data);
};
-
- class VpnEnableCmd : public NexusCommand {
- public:
- VpnEnableCmd();
- virtual ~VpnEnableCmd() {}
- int runCommand(SocketClient *c, char *data);
- };
-
- class VpnSetVarCmd : public NexusCommand {
- public:
- VpnSetVarCmd();
- virtual ~VpnSetVarCmd() {}
- int runCommand(SocketClient *c, char *data);
- };
-
- class VpnGetVarCmd : public NexusCommand {
- public:
- VpnGetVarCmd();
- virtual ~VpnGetVarCmd() {}
- int runCommand(SocketClient *c, char *data);
- };
-
- class VpnDisableCmd : public NexusCommand {
- public:
- VpnDisableCmd();
- virtual ~VpnDisableCmd() {}
- int runCommand(SocketClient *c, char *data);
- };
-
};
#endif
diff --git a/nexus/Controller.cpp b/nexus/Controller.cpp
index cc1a187..133e796 100644
--- a/nexus/Controller.cpp
+++ b/nexus/Controller.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
@@ -32,8 +33,13 @@
extern "C" int init_module(void *, unsigned int, const char *);
extern "C" int delete_module(const char *, unsigned int);
-Controller::Controller(const char *name) {
+Controller::Controller(const char *name, const char *prefix) {
mName = name;
+ mPropertyPrefix = prefix;
+ mProperties = new PropertyCollection();
+
+ mEnabled = false;
+ registerProperty("enable");
}
int Controller::start() {
@@ -44,12 +50,69 @@
return 0;
}
+const PropertyCollection & Controller::getProperties() {
+ return *mProperties;
+}
+
+int Controller::setProperty(const char *name, char *value) {
+ if (!strcmp(name, "enable")) {
+ int en = atoi(value);
+ int rc;
+
+ rc = (en ? enable() : disable());
+
+ if (!rc)
+ mEnabled = en;
+
+ return rc;
+ }
+
+ errno = ENOENT;
+ return -1;
+}
+
+const char *Controller::getProperty(const char *name, char *buffer, size_t maxsize) {
+ if (!strcmp(name, "enable")) {
+ snprintf(buffer, maxsize, "%d", mEnabled);
+ return buffer;
+ }
+
+ errno = ENOENT;
+ return NULL;
+}
+
+int Controller::registerProperty(const char *name) {
+ PropertyCollection::iterator it;
+
+ for (it = mProperties->begin(); it != mProperties->end(); ++it) {
+ if (!strcmp(name, (*it))) {
+ errno = EADDRINUSE;
+ LOGE("Failed to register property (%s)", strerror(errno));
+ return -1;
+ }
+ }
+
+ mProperties->push_back(name);
+ return 0;
+}
+
+int Controller::unregisterProperty(const char *name) {
+ PropertyCollection::iterator it;
+
+ for (it = mProperties->begin(); it != mProperties->end(); ++it) {
+ if (!strcmp(name, (*it))) {
+ mProperties->erase(it);
+ return 0;
+ }
+ }
+ errno = ENOENT;
+ return -1;
+}
+
int Controller::loadKernelModule(char *modpath, const char *args) {
void *module;
unsigned int size;
- LOGD("loadKernelModule(%s, %s)", modpath, args);
-
module = loadFile(modpath, &size);
if (!module) {
errno = -EIO;
@@ -65,7 +128,6 @@
int rc = -1;
int retries = 10;
- LOGD("unloadKernelModule(%s)", modtag);
while (retries--) {
rc = delete_module(modtag, O_NONBLOCK | O_EXCL);
if (rc < 0 && errno == EAGAIN)
@@ -107,7 +169,6 @@
return false;
}
-
void *Controller::loadFile(char *filename, unsigned int *_size)
{
int ret, fd;
diff --git a/nexus/Controller.h b/nexus/Controller.h
index 8e69978..ae37426 100644
--- a/nexus/Controller.h
+++ b/nexus/Controller.h
@@ -16,31 +16,48 @@
#ifndef _CONTROLLER_H
#define _CONTROLLER_H
+#include <unistd.h>
+#include <sys/types.h>
+
#include "../../../frameworks/base/include/utils/List.h"
+#include "PropertyCollection.h"
+
class Controller {
private:
const char *mName;
+ const char *mPropertyPrefix;
+ PropertyCollection *mProperties;
+ bool mEnabled;
public:
- Controller(const char *name);
+ Controller(const char *name, const char *prefix);
virtual ~Controller() {}
virtual int start();
virtual int stop();
- virtual int enable() = 0;
- virtual int disable() = 0;
+ virtual const PropertyCollection &getProperties();
+ virtual int setProperty(const char *name, char *value);
+ virtual const char *getProperty(const char *name, char *buffer, size_t maxsize);
- virtual const char *getName() { return mName; }
+ const char *getName() { return mName; }
+ const char *getPropertyPrefix() { return mPropertyPrefix; }
protected:
int loadKernelModule(char *modpath, const char *args);
bool isKernelModuleLoaded(const char *modtag);
int unloadKernelModule(const char *modtag);
+ int registerProperty(const char *name);
+ int unregisterProperty(const char *name);
+
private:
void *loadFile(char *filename, unsigned int *_size);
+
+ virtual int enable() = 0;
+ virtual int disable() = 0;
+
};
typedef android::List<Controller *> ControllerCollection;
diff --git a/nexus/LoopController.cpp b/nexus/LoopController.cpp
index 38037ac..400d279 100644
--- a/nexus/LoopController.cpp
+++ b/nexus/LoopController.cpp
@@ -18,7 +18,7 @@
#include "LoopController.h"
LoopController::LoopController() :
- Controller("LOOP") {
+ Controller("LOOP", "loop") {
}
int LoopController::enable() {
diff --git a/nexus/LoopController.h b/nexus/LoopController.h
index 8b89977..d047f87 100644
--- a/nexus/LoopController.h
+++ b/nexus/LoopController.h
@@ -23,6 +23,7 @@
LoopController();
virtual ~LoopController() {}
+private:
int enable();
int disable();
};
diff --git a/nexus/NetworkManager.cpp b/nexus/NetworkManager.cpp
index 3b823d1..022d7f8 100644
--- a/nexus/NetworkManager.cpp
+++ b/nexus/NetworkManager.cpp
@@ -83,6 +83,73 @@
return NULL;
}
+int NetworkManager::setProperty(const char *name, char *value) {
+ char *tmp = strdup(name);
+ char *next = tmp;
+ char *prefix;
+ char *rest;
+ ControllerCollection::iterator it;
+
+ if (!(prefix = strsep(&next, ".")))
+ goto out_inval;
+
+ rest = next;
+
+ if (!strncasecmp(prefix, "netman", 6)) {
+ errno = ENOSYS;
+ return -1;
+ }
+
+ for (it = mControllers->begin(); it != mControllers->end(); ++it) {
+ if (!strcasecmp(prefix, (*it)->getPropertyPrefix())) {
+ return (*it)->setProperty(rest, value);
+ }
+ }
+
+ errno = ENOENT;
+ return -1;
+
+out_inval:
+ errno = EINVAL;
+ return -1;
+}
+
+const char *NetworkManager::getProperty(const char *name, char *buffer,
+ size_t maxsize) {
+ char *tmp = strdup(name);
+ char *next = tmp;
+ char *prefix;
+ char *rest;
+ ControllerCollection::iterator it;
+
+ if (!(prefix = strsep(&next, ".")))
+ goto out_inval;
+
+ rest = next;
+
+ if (!strncasecmp(prefix, "netman", 6)) {
+ errno = ENOSYS;
+ return NULL;
+ }
+
+ for (it = mControllers->begin(); it != mControllers->end(); ++it) {
+ if (!strcasecmp(prefix, (*it)->getPropertyPrefix())) {
+ return (*it)->getProperty(rest, buffer, maxsize);
+ }
+ }
+
+ errno = ENOENT;
+ return NULL;
+
+out_inval:
+ errno = EINVAL;
+ return NULL;
+}
+
+const PropertyCollection &NetworkManager::getProperties() {
+ return *mProperties;
+}
+
int NetworkManager::onInterfaceCreated(Controller *c, char *name) {
LOGD("Interface %s created by controller %s", name, c->getName());
return 0;
diff --git a/nexus/NetworkManager.h b/nexus/NetworkManager.h
index 0ac4a4d..bd00849 100644
--- a/nexus/NetworkManager.h
+++ b/nexus/NetworkManager.h
@@ -19,6 +19,7 @@
#include <sysutils/SocketListener.h>
#include "Controller.h"
+#include "PropertyCollection.h"
class NetworkManager {
private:
@@ -27,6 +28,7 @@
private:
ControllerCollection *mControllers;
SocketListener *mBroadcaster;
+ PropertyCollection *mProperties;
public:
virtual ~NetworkManager() {}
@@ -37,6 +39,10 @@
Controller *findController(const char *name);
+ const PropertyCollection &getProperties();
+ int setProperty(const char *name, char *value);
+ const char *getProperty(const char *name, char *buffer, size_t maxsize);
+
void setBroadcaster(SocketListener *sl) { mBroadcaster = sl; }
SocketListener *getBroadcaster() { return mBroadcaster; }
@@ -45,6 +51,9 @@
private:
int startControllers();
int stopControllers();
+ int registerProperty(const char *name);
+ int unregisterProperty(const char *name);
+
NetworkManager();
public:
diff --git a/nexus/OpenVpnController.cpp b/nexus/OpenVpnController.cpp
index 411a0c7..1934024 100644
--- a/nexus/OpenVpnController.cpp
+++ b/nexus/OpenVpnController.cpp
@@ -63,7 +63,6 @@
}
int OpenVpnController::disable() {
-
if (mServiceManager->stop("openvpn"))
return -1;
return 0;
diff --git a/nexus/OpenVpnController.h b/nexus/OpenVpnController.h
index b321029..439e18a 100644
--- a/nexus/OpenVpnController.h
+++ b/nexus/OpenVpnController.h
@@ -31,6 +31,8 @@
int start();
int stop();
+
+private:
int enable();
int disable();
};
diff --git a/nexus/PropertyCollection.h b/nexus/PropertyCollection.h
new file mode 100644
index 0000000..4be1cf0
--- /dev/null
+++ b/nexus/PropertyCollection.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2008 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.
+ */
+
+#ifndef _PROPERTY_COLLECTION_H
+#define _PROPERTY_COLLECTION_H
+
+#include "../../../frameworks/base/include/utils/List.h"
+
+typedef android::List<const char *> PropertyCollection;
+
+#endif
+
diff --git a/nexus/VpnController.cpp b/nexus/VpnController.cpp
index cd24c19..d3bc216 100644
--- a/nexus/VpnController.cpp
+++ b/nexus/VpnController.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
@@ -23,7 +24,8 @@
#include "VpnController.h"
VpnController::VpnController() :
- Controller("VPN") {
+ Controller("VPN", "vpn") {
+ registerProperty("gateway");
}
int VpnController::start() {
@@ -46,15 +48,23 @@
return -1;
}
-int VpnController::setVpnGateway(const char *vpnGw) {
- if (!inet_aton(vpnGw, &mVpnGateway)) {
- errno = EINVAL;
- return -1;
- }
- return 0;
+int VpnController::setProperty(const char *name, char *value) {
+ if (!strcmp(name, "gateway")) {
+ if (!inet_aton(value, &mVpnGateway)) {
+ errno = EINVAL;
+ return -1;
+ }
+ return 0;
+ }
+
+ return Controller::setProperty(name, value);
}
-int VpnController::setVpnGateway(struct in_addr *vpnGw) {
- memcpy(&mVpnGateway, vpnGw, sizeof(struct in_addr));
- return 0;
+const char *VpnController::getProperty(const char *name, char *buffer, size_t maxsize) {
+ if (!strcmp(name, "gateway")) {
+ snprintf(buffer, maxsize, "%s", inet_ntoa(mVpnGateway));
+ return buffer;
+ }
+
+ return Controller::getProperty(name, buffer, maxsize);
}
diff --git a/nexus/VpnController.h b/nexus/VpnController.h
index 4088e6a..0a93990 100644
--- a/nexus/VpnController.h
+++ b/nexus/VpnController.h
@@ -33,14 +33,14 @@
virtual int start();
virtual int stop();
+ virtual int setProperty(const char *name, char *value);
+ virtual const char *getProperty(const char *name, char *buffer,
+ size_t maxlen);
+
+private:
virtual int enable();
virtual int disable();
- struct in_addr &getVpnGateway() { return mVpnGateway; }
- int setVpnGateway(const char *vpnGw);
- int setVpnGateway(struct in_addr *vpnGw);
-
-protected:
};
#endif
diff --git a/nexus/WifiController.cpp b/nexus/WifiController.cpp
index 126db69..72207ce 100644
--- a/nexus/WifiController.cpp
+++ b/nexus/WifiController.cpp
@@ -13,6 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
+#include <stdlib.h>
#include <string.h>
#include <errno.h>
@@ -26,7 +28,7 @@
#include "ErrorCode.h"
WifiController::WifiController(char *modpath, char *modname, char *modargs) :
- Controller("WIFI") {
+ Controller("WIFI", "wifi") {
strncpy(mModulePath, modpath, sizeof(mModulePath));
strncpy(mModuleName, modname, sizeof(mModuleName));
strncpy(mModuleArgs, modargs, sizeof(mModuleArgs));
@@ -34,6 +36,8 @@
mSupplicant = new Supplicant();
mScanner = new WifiScanner(mSupplicant, 10);
mCurrentScanMode = 0;
+
+ registerProperty("scanmode");
}
int WifiController::start() {
@@ -94,7 +98,7 @@
return -1;
}
-void WifiController::sendStatusBroadcast(char *msg) {
+void WifiController::sendStatusBroadcast(const char *msg) {
NetworkManager::Instance()->
getBroadcaster()->
sendBroadcast(ErrorCode::UnsolicitedInformational, msg, false);
@@ -167,3 +171,20 @@
WifiNetworkCollection *WifiController::createNetworkList() {
return mSupplicant->createNetworkList();
}
+
+int WifiController::setProperty(const char *name, char *value) {
+ if (!strcmp(name, "scanmode"))
+ return setScanMode((uint32_t) strtoul(value, NULL, 0));
+
+ return Controller::setProperty(name, value);
+}
+
+const char *WifiController::getProperty(const char *name, char *buffer, size_t maxsize) {
+ if (!strcmp(name, "scanmode")) {
+ snprintf(buffer, maxsize, "0x%.8x", mCurrentScanMode);
+ return buffer;
+ }
+
+ return Controller::getProperty(name, buffer, maxsize);
+}
+
diff --git a/nexus/WifiController.h b/nexus/WifiController.h
index b9c981c..a70fb5b 100644
--- a/nexus/WifiController.h
+++ b/nexus/WifiController.h
@@ -54,15 +54,14 @@
int start();
int stop();
- int enable();
- int disable();
-
int addNetwork();
int removeNetwork(int networkId);
WifiNetworkCollection *createNetworkList();
- int getScanMode() { return mCurrentScanMode; }
- int setScanMode(uint32_t mode);
+ virtual int setProperty(const char *name, char *value);
+ virtual const char *getProperty(const char *name, char *buffer,
+ size_t maxlen);
+
ScanResultCollection *createScanResults();
char *getModulePath() { return mModulePath; }
@@ -79,7 +78,13 @@
virtual bool isFirmwareLoaded() = 0;
virtual bool isPoweredUp() = 0;
- void sendStatusBroadcast(char *msg);
+ void sendStatusBroadcast(const char *msg);
+
+private:
+ int setScanMode(uint32_t mode);
+ int enable();
+ int disable();
+
};
#endif
diff --git a/nexus/WifiScanner.cpp b/nexus/WifiScanner.cpp
index 1bc9722..048e784 100644
--- a/nexus/WifiScanner.cpp
+++ b/nexus/WifiScanner.cpp
@@ -65,7 +65,7 @@
struct timeval to;
int rc = 0;
- to.tv_sec = 0;
+ to.tv_usec = 0;
to.tv_sec = mPeriod;
FD_ZERO(&read_fds);
@@ -83,4 +83,5 @@
} else if (FD_ISSET(mCtrlPipe[0], &read_fds))
break;
} // while
+ LOGD("Stopping wifi scanner");
}
diff --git a/rootdir/etc/init.goldfish.sh b/rootdir/etc/init.goldfish.sh
index 0eb0154..f1b801d 100755
--- a/rootdir/etc/init.goldfish.sh
+++ b/rootdir/etc/init.goldfish.sh
@@ -34,6 +34,10 @@
;;
esac
+# call 'qemu-props' to set system properties from the emulator.
+#
+/system/bin/qemu-props
+
# this line doesn't really do anything useful. however without it the
# previous setprop doesn't seem to apply for some really odd reason
setprop ro.qemu.init.completed 1