• R/O
  • HTTP
  • SSH
  • HTTPS

コミット

タグ
未設定

よく使われているワード(クリックで追加)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

system/corennnnn


コミットメタ情報

リビジョン1edfd382ba69ff96ebd0220b05b134a90b910ea7 (tree)
日時2009-05-28 06:25:54
作者Mathias Agopian <mathias@goog...>
コミッターMathias Agopian

ログメッセージ

Merge commit 'goog/master' into merge_master

変更サマリ

差分

--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
1+*~
--- a/adb/adb.c
+++ b/adb/adb.c
@@ -23,6 +23,7 @@
2323 #include <errno.h>
2424 #include <string.h>
2525 #include <time.h>
26+#include <sys/time.h>
2627
2728 #include "sysdeps.h"
2829 #include "adb.h"
@@ -657,10 +658,25 @@ void start_logging(void)
657658 void start_device_log(void)
658659 {
659660 int fd;
660- char path[100];
661+ char path[PATH_MAX];
662+ struct tm now;
663+ time_t t;
664+ char value[PROPERTY_VALUE_MAX];
661665
662- snprintf(path, sizeof path, "/data/adb_%ld.txt", (long)time(NULL));
663- fd = unix_open(path, O_WRONLY | O_CREAT | O_APPEND, 0640);
666+ // read the trace mask from persistent property persist.adb.trace_mask
667+ // give up if the property is not set or cannot be parsed
668+ property_get("persist.adb.trace_mask", value, "");
669+ if (sscanf(value, "%x", &adb_trace_mask) != 1)
670+ return;
671+
672+ adb_mkdir("/data/adb", 0775);
673+ tzset();
674+ time(&t);
675+ localtime_r(&t, &now);
676+ strftime(path, sizeof(path),
677+ "/data/adb/adb-%Y-%m-%d-%H-%M-%S.txt",
678+ &now);
679+ fd = unix_open(path, O_WRONLY | O_CREAT | O_TRUNC, 0640);
664680 if (fd < 0)
665681 return;
666682
@@ -671,11 +687,6 @@ void start_device_log(void)
671687
672688 fd = unix_open("/dev/null", O_RDONLY);
673689 dup2(fd, 0);
674-
675- // log everything
676- adb_trace_mask = ~0;
677- // except TRACE_RWX is a bit too verbose
678- adb_trace_mask &= ~TRACE_RWX;
679690 }
680691 #endif
681692
@@ -875,9 +886,10 @@ int adb_main(int is_daemon)
875886 ** AID_INET to diagnose network issues (netcfg, ping)
876887 ** AID_GRAPHICS to access the frame buffer
877888 ** AID_NET_BT and AID_NET_BT_ADMIN to diagnose bluetooth (hcidump)
889+ ** AID_SDCARD_RW to allow writing to the SD card
878890 */
879891 gid_t groups[] = { AID_ADB, AID_LOG, AID_INPUT, AID_INET, AID_GRAPHICS,
880- AID_NET_BT, AID_NET_BT_ADMIN };
892+ AID_NET_BT, AID_NET_BT_ADMIN, AID_SDCARD_RW };
881893 setgroups(sizeof(groups)/sizeof(groups[0]), groups);
882894
883895 /* then switch user and group to "shell" */
@@ -919,9 +931,6 @@ int adb_main(int is_daemon)
919931 fdevent_loop();
920932
921933 usb_cleanup();
922-#if ADB_HOST
923- usb_vendors_cleanup();
924-#endif
925934
926935 return 0;
927936 }
@@ -1081,9 +1090,8 @@ int main(int argc, char **argv)
10811090 adb_device_banner = "recovery";
10821091 recovery_mode = 1;
10831092 }
1084-#if ADB_DEVICE_LOG
1093+
10851094 start_device_log();
1086-#endif
10871095 return adb_main(0);
10881096 #endif
10891097 }
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -345,11 +345,6 @@ typedef enum {
345345 #endif
346346
347347
348-/* set this to log to /data/adb/adb_<time>.txt on the device.
349- * has no effect if the /data/adb/ directory does not exist.
350- */
351-#define ADB_DEVICE_LOG 0
352-
353348 #if !TRACE_PACKETS
354349 #define print_packet(tag,p) do {} while (0)
355350 #endif
@@ -357,11 +352,10 @@ typedef enum {
357352 #define ADB_PORT 5037
358353 #define ADB_LOCAL_TRANSPORT_PORT 5555
359354
360-// Google's USB Vendor ID
361-#define VENDOR_ID_GOOGLE 0x18d1
355+#define ADB_CLASS 0xff
356+#define ADB_SUBCLASS 0x42
357+#define ADB_PROTOCOL 0x1
362358
363-// HTC's USB Vendor ID
364-#define VENDOR_ID_HTC 0x0bb4
365359
366360 void local_init();
367361 int local_connect(int port);
--- a/adb/adb_client.c
+++ b/adb/adb_client.c
@@ -213,7 +213,7 @@ int adb_connect(const char *service)
213213 fprintf(stdout,"* daemon started successfully *\n");
214214 }
215215 /* give the server some time to start properly and detect devices */
216- adb_sleep_ms(2000);
216+ adb_sleep_ms(3000);
217217 // fall through to _adb_connect
218218 } else {
219219 // if server was running, check its version to make sure it is not out of date
--- a/adb/transport_usb.c
+++ b/adb/transport_usb.c
@@ -135,11 +135,9 @@ int is_adb_interface(int vid, int pid, int usb_class, int usb_subclass, int usb_
135135 unsigned i;
136136 for (i = 0; i < vendorIdCount; i++) {
137137 if (vid == vendorIds[i]) {
138- /* class:vendor (0xff) subclass:android (0x42) proto:adb (0x01) */
139- if(usb_class == 0xff) {
140- if((usb_subclass == 0x42) && (usb_protocol == 0x01)) {
141- return 1;
142- }
138+ if (usb_class == ADB_CLASS && usb_subclass == ADB_SUBCLASS &&
139+ usb_protocol == ADB_PROTOCOL) {
140+ return 1;
143141 }
144142
145143 return 0;
--- a/adb/usb_osx.c
+++ b/adb/usb_osx.c
@@ -32,9 +32,6 @@
3232
3333 #define DBG D
3434
35-#define ADB_SUBCLASS 0x42
36-#define ADB_PROTOCOL 0x1
37-
3835 static IONotificationPortRef notificationPort = 0;
3936 static io_iterator_t* notificationIterators;
4037
--- a/adb/usb_vendors.c
+++ b/adb/usb_vendors.c
@@ -16,25 +16,119 @@
1616
1717 #include "usb_vendors.h"
1818
19-#include "sysdeps.h"
2019 #include <stdio.h>
20+
21+#ifdef _WIN32
22+# define WIN32_LEAN_AND_MEAN
23+# include "windows.h"
24+# include "shlobj.h"
25+#else
26+# include <unistd.h>
27+# include <sys/stat.h>
28+#endif
29+
30+#include "sysdeps.h"
2131 #include "adb.h"
2232
23-int* vendorIds = NULL;
33+#define ANDROID_PATH ".android"
34+#define ANDROID_ADB_INI "adb_usb.ini"
35+
36+#define TRACE_TAG TRACE_USB
37+
38+// Google's USB Vendor ID
39+#define VENDOR_ID_GOOGLE 0x18d1
40+// HTC's USB Vendor ID
41+#define VENDOR_ID_HTC 0x0bb4
42+
43+/** built-in vendor list */
44+int builtInVendorIds[] = {
45+ VENDOR_ID_GOOGLE,
46+ VENDOR_ID_HTC,
47+};
48+
49+#define BUILT_IN_VENDOR_COUNT (sizeof(builtInVendorIds)/sizeof(builtInVendorIds[0]))
50+
51+/* max number of supported vendor ids (built-in + 3rd party). increase as needed */
52+#define VENDOR_COUNT_MAX 128
53+
54+int vendorIds[VENDOR_COUNT_MAX];
2455 unsigned vendorIdCount = 0;
2556
26-void usb_vendors_init(void) {
27- /* for now, only put the built-in VENDOR_ID_* */
28- vendorIdCount = 2;
29- vendorIds = (int*)malloc(vendorIdCount * sizeof(int));
30- vendorIds[0] = VENDOR_ID_GOOGLE;
31- vendorIds[1] = VENDOR_ID_HTC;
57+int get_adb_usb_ini(char* buff, size_t len);
58+
59+void usb_vendors_init(void)
60+{
61+ if (VENDOR_COUNT_MAX < BUILT_IN_VENDOR_COUNT) {
62+ fprintf(stderr, "VENDOR_COUNT_MAX not big enough for built-in vendor list.\n");
63+ exit(2);
64+ }
65+
66+ /* add the built-in vendors at the beginning of the array */
67+ memcpy(vendorIds, builtInVendorIds, sizeof(builtInVendorIds));
68+
69+ /* default array size is the number of built-in vendors */
70+ vendorIdCount = BUILT_IN_VENDOR_COUNT;
71+
72+ if (VENDOR_COUNT_MAX == BUILT_IN_VENDOR_COUNT)
73+ return;
74+
75+ char temp[PATH_MAX];
76+ if (get_adb_usb_ini(temp, sizeof(temp)) == 0) {
77+ FILE * f = fopen(temp, "rt");
78+
79+ if (f != NULL) {
80+ /* The vendor id file is pretty basic. 1 vendor id per line.
81+ Lines starting with # are comments */
82+ while (fgets(temp, sizeof(temp), f) != NULL) {
83+ if (temp[0] == '#')
84+ continue;
85+
86+ long value = strtol(temp, NULL, 0);
87+ if (errno == EINVAL || errno == ERANGE || value > INT_MAX || value < 0) {
88+ fprintf(stderr, "Invalid content in %s. Quitting.\n", ANDROID_ADB_INI);
89+ exit(2);
90+ }
91+
92+ vendorIds[vendorIdCount++] = (int)value;
93+
94+ /* make sure we don't go beyond the array */
95+ if (vendorIdCount == VENDOR_COUNT_MAX) {
96+ break;
97+ }
98+ }
99+ }
100+ }
32101 }
33102
34-void usb_vendors_cleanup(void) {
35- if (vendorIds != NULL) {
36- free(vendorIds);
37- vendorIds = NULL;
38- vendorIdCount = 0;
103+/* Utils methods */
104+
105+/* builds the path to the adb vendor id file. returns 0 if success */
106+int build_path(char* buff, size_t len, const char* format, const char* home)
107+{
108+ if (snprintf(buff, len, format, home, ANDROID_PATH, ANDROID_ADB_INI) >= len) {
109+ return 1;
110+ }
111+
112+ return 0;
113+}
114+
115+/* fills buff with the path to the adb vendor id file. returns 0 if success */
116+int get_adb_usb_ini(char* buff, size_t len)
117+{
118+#ifdef _WIN32
119+ const char* home = getenv("ANDROID_SDK_HOME");
120+ if (home != NULL) {
121+ return build_path(buff, len, "%s\\%s\\%s", home);
122+ } else {
123+ char path[MAX_PATH];
124+ SHGetFolderPath( NULL, CSIDL_PROFILE, NULL, 0, path);
125+ return build_path(buff, len, "%s\\%s\\%s", path);
39126 }
127+#else
128+ const char* home = getenv("HOME");
129+ if (home == NULL)
130+ home = "/tmp";
131+
132+ return build_path(buff, len, "%s/%s/%s", home);
133+#endif
40134 }
--- a/adb/usb_vendors.h
+++ b/adb/usb_vendors.h
@@ -17,10 +17,9 @@
1717 #ifndef __USB_VENDORS_H
1818 #define __USB_VENDORS_H
1919
20-extern int* vendorIds;
20+extern int vendorIds[];
2121 extern unsigned vendorIdCount;
2222
2323 void usb_vendors_init(void);
24-void usb_vendors_cleanup(void);
2524
2625 #endif
\ No newline at end of file
--- /dev/null
+++ b/include/acc/acc.h
@@ -0,0 +1,78 @@
1+/*
2+ * Copyright (C) 2009 The Android Open Source Project
3+ *
4+ * Licensed under the Apache License, Version 2.0 (the "License");
5+ * you may not use this file except in compliance with the License.
6+ * You may obtain a copy of the License at
7+ *
8+ * http://www.apache.org/licenses/LICENSE-2.0
9+ *
10+ * Unless required by applicable law or agreed to in writing, software
11+ * distributed under the License is distributed on an "AS IS" BASIS,
12+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+ * See the License for the specific language governing permissions and
14+ * limitations under the License.
15+ */
16+
17+#ifndef ANDROID_ACC_ACC_H
18+#define ANDROID_ACC_ACC_H
19+
20+#include <stdint.h>
21+#include <sys/types.h>
22+
23+typedef char ACCchar;
24+typedef int32_t ACCint;
25+typedef uint32_t ACCuint;
26+typedef ssize_t ACCsizei;
27+typedef unsigned int ACCenum;
28+typedef void ACCvoid;
29+typedef struct ACCscript ACCscript;
30+
31+#define ACC_NO_ERROR 0x0000
32+#define ACC_INVALID_ENUM 0x0500
33+#define ACC_INVALID_OPERATION 0x0502
34+#define ACC_INVALID_VALUE 0x0501
35+#define ACC_OUT_OF_MEMORY 0x0505
36+
37+#define ACC_COMPILE_STATUS 0x8B81
38+#define ACC_INFO_LOG_LENGTH 0x8B84
39+
40+
41+// ----------------------------------------------------------------------------
42+
43+#ifdef __cplusplus
44+extern "C" {
45+#endif
46+
47+ACCscript* accCreateScript();
48+
49+void accDeleteScript(ACCscript* script);
50+
51+ACCenum accGetError( ACCscript* script );
52+
53+void accScriptSource(ACCscript* script,
54+ ACCsizei count,
55+ const ACCchar** string,
56+ const ACCint* length);
57+
58+void accCompileScript(ACCscript* script);
59+
60+void accGetScriptiv(ACCscript* script,
61+ ACCenum pname,
62+ ACCint* params);
63+
64+void accGetScriptInfoLog(ACCscript* script,
65+ ACCsizei maxLength,
66+ ACCsizei* length,
67+ ACCchar* infoLog);
68+
69+void accGetScriptLabel(ACCscript* script, const ACCchar * name,
70+ ACCvoid** address);
71+
72+#ifdef __cplusplus
73+};
74+#endif
75+
76+// ----------------------------------------------------------------------------
77+
78+#endif
--- a/init/devices.c
+++ b/init/devices.c
@@ -115,6 +115,7 @@ static struct perms_ devperms[] = {
115115 { "/dev/oncrpc/", 0660, AID_ROOT, AID_SYSTEM, 1 },
116116 { "/dev/adsp/", 0660, AID_SYSTEM, AID_AUDIO, 1 },
117117 { "/dev/mt9t013", 0660, AID_SYSTEM, AID_SYSTEM, 0 },
118+ { "/dev/msm_camera/", 0660, AID_SYSTEM, AID_SYSTEM, 1 },
118119 { "/dev/akm8976_daemon",0640, AID_COMPASS, AID_SYSTEM, 0 },
119120 { "/dev/akm8976_aot", 0640, AID_COMPASS, AID_SYSTEM, 0 },
120121 { "/dev/akm8976_pffd", 0640, AID_COMPASS, AID_SYSTEM, 0 },
@@ -384,7 +385,10 @@ static void handle_device_event(struct uevent *uevent)
384385 } else if (!strncmp(uevent->subsystem, "adsp", 4)) {
385386 base = "/dev/adsp/";
386387 mkdir(base, 0755);
387- } else if(!strncmp(uevent->subsystem, "input", 5)) {
388+ } else if (!strncmp(uevent->subsystem, "msm_camera", 10)) {
389+ base = "/dev/msm_camera/";
390+ mkdir(base, 0755);
391+ } else if(!strncmp(uevent->subsystem, "input", 5)) {
388392 base = "/dev/input/";
389393 mkdir(base, 0755);
390394 } else if(!strncmp(uevent->subsystem, "mtd", 3)) {
--- a/libacc/Android.mk
+++ b/libacc/Android.mk
@@ -5,8 +5,15 @@ include $(CLEAR_VARS)
55 # Shared library
66 #
77
8-LOCAL_MODULE:= acc
9-LOCAL_SRC_FILES := acc.cpp disassem.cpp
10-LOCAL_MODULE_TAGS := tests
8+LOCAL_MODULE:= libacc
9+LOCAL_SRC_FILES := acc.cpp
1110
12-include $(BUILD_EXECUTABLE)
11+ifeq ($(TARGET_ARCH),arm)
12+LOCAL_SRC_FILES += disassem.cpp
13+endif
14+
15+LOCAL_SHARED_LIBRARIES := libdl
16+
17+include $(BUILD_SHARED_LIBRARY)
18+
19+include $(call all-makefiles-under,$(LOCAL_PATH))
\ No newline at end of file
--- /dev/null
+++ b/libacc/LICENSE
@@ -0,0 +1,21 @@
1+ Obfuscated Tiny C Compiler
2+
3+ Copyright (C) 2001-2003 Fabrice Bellard
4+
5+ This software is provided 'as-is', without any express or implied
6+ warranty. In no event will the authors be held liable for any damages
7+ arising from the use of this software.
8+
9+ Permission is granted to anyone to use this software for any purpose,
10+ including commercial applications, and to alter it and redistribute it
11+ freely, subject to the following restrictions:
12+
13+ 1. The origin of this software must not be misrepresented; you must not
14+ claim that you wrote the original software. If you use this software
15+ in a product, an acknowledgment in the product and its documentation
16+ *is* required.
17+ 2. Altered source versions must be plainly marked as such, and must not be
18+ misrepresented as being the original software.
19+ 3. This notice may not be removed or altered from any source distribution.
20+
21+
--- a/libacc/acc.cpp
+++ b/libacc/acc.cpp
@@ -4,33 +4,10 @@
44 * in scripting environments where speed and memory footprint are important.
55 *
66 * This code is based upon the "unobfuscated" version of the
7- * Obfuscated Tiny C compiler, and retains the
8- * original copyright notice and license from that compiler, see below.
7+ * Obfuscated Tiny C compiler, see the file LICENSE for details.
98 *
109 */
1110
12-/*
13- Obfuscated Tiny C Compiler
14-
15- Copyright (C) 2001-2003 Fabrice Bellard
16-
17- This software is provided 'as-is', without any express or implied
18- warranty. In no event will the authors be held liable for any damages
19- arising from the use of this software.
20-
21- Permission is granted to anyone to use this software for any purpose,
22- including commercial applications, and to alter it and redistribute it
23- freely, subject to the following restrictions:
24-
25- 1. The origin of this software must not be misrepresented; you must not
26- claim that you wrote the original software. If you use this software
27- in a product, an acknowledgment in the product and its documentation
28- *is* required.
29- 2. Altered source versions must be plainly marked as such, and must not be
30- misrepresented as being the original software.
31- 3. This notice may not be removed or altered from any source distribution.
32- */
33-
3411 #include <ctype.h>
3512 #include <dlfcn.h>
3613 #include <stdarg.h>
@@ -59,6 +36,13 @@
5936 #include "disassem.h"
6037 #endif
6138
39+#include <acc/acc.h>
40+
41+#define LOG_API(...) do {} while(0)
42+// #define LOG_API(...) fprintf (stderr, __VA_ARGS__)
43+
44+// #define ENABLE_ARM_DISASSEMBLY
45+
6246 namespace acc {
6347
6448 class Compiler {
@@ -116,6 +100,27 @@ class Compiler {
116100 }
117101 };
118102
103+ /**
104+ * A code generator creates an in-memory program, generating the code on
105+ * the fly. There is one code generator implementation for each supported
106+ * architecture.
107+ *
108+ * The code generator implements the following abstract machine:
109+ * R0 - the main accumulator.
110+ * R1 - the secondary accumulator.
111+ * FP - a frame pointer for accessing function arguments and local
112+ * variables.
113+ * SP - a stack pointer for storing intermediate results while evaluating
114+ * expressions. The stack pointer grows downwards.
115+ *
116+ * The function calling convention is that all arguments are placed on the
117+ * stack such that the first argument has the lowest address.
118+ * After the call, the result is in R0. The caller is responsible for
119+ * removing the arguments from the stack.
120+ * The R0 and R1 registers are not saved across function calls. The
121+ * FP and SP registers are saved.
122+ */
123+
119124 class CodeGenerator {
120125 public:
121126 CodeGenerator() {}
@@ -125,70 +130,170 @@ class Compiler {
125130 this->pCodeBuf = pCodeBuf;
126131 }
127132
128- /* returns address to patch with local variable size
133+ /* Emit a function prolog.
134+ * argCount is the number of arguments.
135+ * Save the old value of the FP.
136+ * Set the new value of the FP.
137+ * Convert from the native platform calling convention to
138+ * our stack-based calling convention. This may require
139+ * pushing arguments from registers to the stack.
140+ * Allocate "N" bytes of stack space. N isn't known yet, so
141+ * just emit the instructions for adjusting the stack, and return
142+ * the address to patch up. The patching will be done in
143+ * functionExit().
144+ * returns address to patch with local variable size.
129145 */
130146 virtual int functionEntry(int argCount) = 0;
131147
132- virtual void functionExit(int argCount, int localVariableAddress, int localVariableSize) = 0;
148+ /* Emit a function epilog.
149+ * Restore the old SP and FP register values.
150+ * Return to the calling function.
151+ * argCount - the number of arguments to the function.
152+ * localVariableAddress - returned from functionEntry()
153+ * localVariableSize - the size in bytes of the local variables.
154+ */
155+ virtual void functionExit(int argCount, int localVariableAddress,
156+ int localVariableSize) = 0;
133157
134- /* load immediate value */
158+ /* load immediate value to R0 */
135159 virtual void li(int t) = 0;
136160
161+ /* Jump to a target, and return the address of the word that
162+ * holds the target data, in case it needs to be fixed up later.
163+ */
137164 virtual int gjmp(int t) = 0;
138165
139- /* l = 0: je, l == 1: jne */
166+ /* Test R0 and jump to a target if the test succeeds.
167+ * l = 0: je, l == 1: jne
168+ * Return the address of the word that holds the targed data, in
169+ * case it needs to be fixed up later.
170+ */
140171 virtual int gtst(bool l, int t) = 0;
141172
173+ /* Compare R1 against R0, and store the boolean result in R0.
174+ * op specifies the comparison.
175+ */
142176 virtual void gcmp(int op) = 0;
143177
178+ /* Perform the arithmetic op specified by op. R1 is the
179+ * left argument, R0 is the right argument.
180+ */
144181 virtual void genOp(int op) = 0;
145182
146- virtual void clearECX() = 0;
147-
148- virtual void pushEAX() = 0;
183+ /* Set R1 to 0.
184+ */
185+ virtual void clearR1() = 0;
149186
150- virtual void popECX() = 0;
187+ /* Push R0 onto the stack.
188+ */
189+ virtual void pushR0() = 0;
151190
152- virtual void storeEAXToAddressECX(bool isInt) = 0;
191+ /* Pop R1 off of the stack.
192+ */
193+ virtual void popR1() = 0;
153194
154- virtual void loadEAXIndirect(bool isInt) = 0;
195+ /* Store R0 to the address stored in R1.
196+ * isInt is true if a whole 4-byte integer value
197+ * should be stored, otherwise a 1-byte character
198+ * value should be stored.
199+ */
200+ virtual void storeR0ToR1(bool isInt) = 0;
155201
156- virtual void leaEAX(int ea) = 0;
202+ /* Load R0 from the address stored in R0.
203+ * isInt is true if a whole 4-byte integer value
204+ * should be loaded, otherwise a 1-byte character
205+ * value should be loaded.
206+ */
207+ virtual void loadR0FromR0(bool isInt) = 0;
157208
158- virtual void storeEAX(int ea) = 0;
209+ /* Load the absolute address of a variable to R0.
210+ * If ea <= LOCAL, then this is a local variable, or an
211+ * argument, addressed relative to FP.
212+ * else it is an absolute global address.
213+ */
214+ virtual void leaR0(int ea) = 0;
159215
160- virtual void loadEAX(int ea, bool isIncDec, int op) = 0;
216+ /* Store R0 to a variable.
217+ * If ea <= LOCAL, then this is a local variable, or an
218+ * argument, addressed relative to FP.
219+ * else it is an absolute global address.
220+ */
221+ virtual void storeR0(int ea) = 0;
222+
223+ /* load R0 from a variable.
224+ * If ea <= LOCAL, then this is a local variable, or an
225+ * argument, addressed relative to FP.
226+ * else it is an absolute global address.
227+ * If isIncDec is true, then the stored variable's value
228+ * should be post-incremented or post-decremented, based
229+ * on the value of op.
230+ */
231+ virtual void loadR0(int ea, bool isIncDec, int op) = 0;
161232
233+ /* Emit code to adjust the stack for a function call. Return the
234+ * label for the address of the instruction that adjusts the
235+ * stack size. This will be passed as argument "a" to
236+ * endFunctionCallArguments.
237+ */
162238 virtual int beginFunctionCallArguments() = 0;
163239
164- virtual void storeEAToArg(int l) = 0;
165-
240+ /* Emit code to store R0 to the stack at byte offset l.
241+ */
242+ virtual void storeR0ToArg(int l) = 0;
243+
244+ /* Patch the function call preamble.
245+ * a is the address returned from beginFunctionCallArguments
246+ * l is the number of bytes the arguments took on the stack.
247+ * Typically you would also emit code to convert the argument
248+ * list into whatever the native function calling convention is.
249+ * On ARM for example you would pop the first 5 arguments into
250+ * R0..R4
251+ */
166252 virtual void endFunctionCallArguments(int a, int l) = 0;
167253
168-
254+ /* Emit a call to an unknown function. The argument "symbol" needs to
255+ * be stored in the location where the address should go. It forms
256+ * a chain. The address will be patched later.
257+ * Return the address of the word that has to be patched.
258+ */
169259 virtual int callForward(int symbol) = 0;
170260
261+ /* Call a function using PC-relative addressing. t is the PC-relative
262+ * address of the function. It has already been adjusted for the
263+ * architectural jump offset, so just store it as-is.
264+ */
171265 virtual void callRelative(int t) = 0;
172266
267+ /* Call a function pointer. L is the number of bytes the arguments
268+ * take on the stack. The address of the function is stored at
269+ * location SP + l.
270+ */
173271 virtual void callIndirect(int l) = 0;
174272
273+ /* Adjust SP after returning from a function call. l is the
274+ * number of bytes of arguments stored on the stack. isIndirect
275+ * is true if this was an indirect call. (In which case the
276+ * address of the function is stored at location SP + l.)
277+ */
175278 virtual void adjustStackAfterCall(int l, bool isIndirect) = 0;
176279
280+ /* Print a disassembly of the assembled code to out. Return
281+ * non-zero if there is an error.
282+ */
177283 virtual int disassemble(FILE* out) = 0;
178284
179- /* output a symbol and patch all calls to it */
285+ /* Generate a symbol at the current PC. t is the head of a
286+ * linked list of addresses to patch.
287+ */
180288 virtual void gsym(int t) = 0;
181289
182- virtual int finishCompile() {
183-#if defined(__arm__)
184- const long base = long(pCodeBuf->getBase());
185- const long curr = base + long(pCodeBuf->getSize());
186- int err = cacheflush(base, curr, 0);
187- return err;
188-#else
189- return 0;
190-#endif
191- }
290+ /*
291+ * Do any cleanup work required at the end of a compile.
292+ * For example, an instruction cache might need to be
293+ * invalidated.
294+ * Return non-zero if there is an error.
295+ */
296+ virtual int finishCompile() = 0;
192297
193298 /**
194299 * Adjust relative branches by this amount.
@@ -214,6 +319,10 @@ class Compiler {
214319 intptr_t getPC() {
215320 return pCodeBuf->getPC();
216321 }
322+
323+ intptr_t getSize() {
324+ return pCodeBuf->getSize();
325+ }
217326 private:
218327 CodeBuf* pCodeBuf;
219328 };
@@ -228,7 +337,7 @@ class Compiler {
228337 /* returns address to patch with local variable size
229338 */
230339 virtual int functionEntry(int argCount) {
231- fprintf(stderr, "functionEntry(%d);\n", argCount);
340+ LOG_API(stderr, "functionEntry(%d);\n", argCount);
232341 // sp -> arg4 arg5 ...
233342 // Push our register-based arguments back on the stack
234343 if (argCount > 0) {
@@ -243,7 +352,7 @@ class Compiler {
243352 }
244353
245354 virtual void functionExit(int argCount, int localVariableAddress, int localVariableSize) {
246- fprintf(stderr, "functionExit(%d, %d, %d);\n", argCount, localVariableAddress, localVariableSize);
355+ LOG_API("functionExit(%d, %d, %d);\n", argCount, localVariableAddress, localVariableSize);
247356 // Patch local variable allocation code:
248357 if (localVariableSize < 0 || localVariableSize > 255) {
249358 error("localVariables out of range: %d", localVariableSize);
@@ -270,7 +379,7 @@ class Compiler {
270379
271380 /* load immediate value */
272381 virtual void li(int t) {
273- fprintf(stderr, "li(%d);\n", t);
382+ LOG_API("li(%d);\n", t);
274383 if (t >= 0 && t < 255) {
275384 o4(0xE3A00000 + t); // mov r0, #0
276385 } else if (t >= -256 && t < 0) {
@@ -285,20 +394,20 @@ class Compiler {
285394 }
286395
287396 virtual int gjmp(int t) {
288- fprintf(stderr, "gjmp(%d);\n", t);
397+ LOG_API("gjmp(%d);\n", t);
289398 return o4(0xEA000000 | encodeAddress(t)); // b .L33
290399 }
291400
292401 /* l = 0: je, l == 1: jne */
293402 virtual int gtst(bool l, int t) {
294- fprintf(stderr, "gtst(%d, %d);\n", l, t);
403+ LOG_API("gtst(%d, %d);\n", l, t);
295404 o4(0xE3500000); // cmp r0,#0
296405 int branch = l ? 0x1A000000 : 0x0A000000; // bne : beq
297406 return o4(branch | encodeAddress(t));
298407 }
299408
300409 virtual void gcmp(int op) {
301- fprintf(stderr, "gcmp(%d);\n", op);
410+ LOG_API("gcmp(%d);\n", op);
302411 o4(0xE1510000); // cmp r1, r1
303412 switch(op) {
304413 case OP_EQUALS:
@@ -332,7 +441,7 @@ class Compiler {
332441 }
333442
334443 virtual void genOp(int op) {
335- fprintf(stderr, "genOp(%d);\n", op);
444+ LOG_API("genOp(%d);\n", op);
336445 switch(op) {
337446 case OP_MUL:
338447 o4(0x0E0000091); // mul r0,r1,r0
@@ -378,23 +487,23 @@ class Compiler {
378487 #endif
379488 }
380489
381- virtual void clearECX() {
382- fprintf(stderr, "clearECX();\n");
490+ virtual void clearR1() {
491+ LOG_API("clearR1();\n");
383492 o4(0xE3A01000); // mov r1, #0
384493 }
385494
386- virtual void pushEAX() {
387- fprintf(stderr, "pushEAX();\n");
495+ virtual void pushR0() {
496+ LOG_API("pushR0();\n");
388497 o4(0xE92D0001); // stmfd sp!,{r0}
389498 }
390499
391- virtual void popECX() {
392- fprintf(stderr, "popECX();\n");
500+ virtual void popR1() {
501+ LOG_API("popR1();\n");
393502 o4(0xE8BD0002); // ldmfd sp!,{r1}
394503 }
395504
396- virtual void storeEAXToAddressECX(bool isInt) {
397- fprintf(stderr, "storeEAXToAddressECX(%d);\n", isInt);
505+ virtual void storeR0ToR1(bool isInt) {
506+ LOG_API("storeR0ToR1(%d);\n", isInt);
398507 if (isInt) {
399508 o4(0xE5810000); // str r0, [r1]
400509 } else {
@@ -402,16 +511,16 @@ class Compiler {
402511 }
403512 }
404513
405- virtual void loadEAXIndirect(bool isInt) {
406- fprintf(stderr, "loadEAXIndirect(%d);\n", isInt);
514+ virtual void loadR0FromR0(bool isInt) {
515+ LOG_API("loadR0FromR0(%d);\n", isInt);
407516 if (isInt)
408517 o4(0xE5900000); // ldr r0, [r0]
409518 else
410519 o4(0xE5D00000); // ldrb r0, [r0]
411520 }
412521
413- virtual void leaEAX(int ea) {
414- fprintf(stderr, "leaEAX(%d);\n", ea);
522+ virtual void leaR0(int ea) {
523+ LOG_API("leaR0(%d);\n", ea);
415524 if (ea < LOCAL) {
416525 // Local, fp relative
417526 if (ea < -1023 || ea > 1023 || ((ea & 3) != 0)) {
@@ -431,8 +540,8 @@ class Compiler {
431540 }
432541 }
433542
434- virtual void storeEAX(int ea) {
435- fprintf(stderr, "storeEAX(%d);\n", ea);
543+ virtual void storeR0(int ea) {
544+ LOG_API("storeR0(%d);\n", ea);
436545 if (ea < LOCAL) {
437546 // Local, fp relative
438547 if (ea < -4095 || ea > 4095) {
@@ -452,8 +561,8 @@ class Compiler {
452561 }
453562 }
454563
455- virtual void loadEAX(int ea, bool isIncDec, int op) {
456- fprintf(stderr, "loadEAX(%d, %d, %d);\n", ea, isIncDec, op);
564+ virtual void loadR0(int ea, bool isIncDec, int op) {
565+ LOG_API("loadR0(%d, %d, %d);\n", ea, isIncDec, op);
457566 if (ea < LOCAL) {
458567 // Local, fp relative
459568 if (ea < -4095 || ea > 4095) {
@@ -500,12 +609,12 @@ class Compiler {
500609 }
501610
502611 virtual int beginFunctionCallArguments() {
503- fprintf(stderr, "beginFunctionCallArguments();\n");
612+ LOG_API("beginFunctionCallArguments();\n");
504613 return o4(0xE24DDF00); // Placeholder
505614 }
506615
507- virtual void storeEAToArg(int l) {
508- fprintf(stderr, "storeEAToArg(%d);\n", l);
616+ virtual void storeR0ToArg(int l) {
617+ LOG_API("storeR0ToArg(%d);\n", l);
509618 if (l < 0 || l > 4096-4) {
510619 error("l out of range for stack offset: 0x%08x", l);
511620 }
@@ -513,7 +622,7 @@ class Compiler {
513622 }
514623
515624 virtual void endFunctionCallArguments(int a, int l) {
516- fprintf(stderr, "endFunctionCallArguments(0x%08x, %d);\n", a, l);
625+ LOG_API("endFunctionCallArguments(0x%08x, %d);\n", a, l);
517626 if (l < 0 || l > 0x3FC) {
518627 error("L out of range for stack adjustment: 0x%08x", l);
519628 }
@@ -526,13 +635,13 @@ class Compiler {
526635 }
527636
528637 virtual int callForward(int symbol) {
529- fprintf(stderr, "callForward(%d);\n", symbol);
638+ LOG_API("callForward(%d);\n", symbol);
530639 // Forward calls are always short (local)
531640 return o4(0xEB000000 | encodeAddress(symbol));
532641 }
533642
534643 virtual void callRelative(int t) {
535- fprintf(stderr, "callRelative(%d);\n", t);
644+ LOG_API("callRelative(%d);\n", t);
536645 int abs = t + getPC() + jumpOffset();
537646 fprintf(stderr, "abs=%d (0x%08x)\n", abs, abs);
538647 if (t >= - (1 << 25) && t < (1 << 25)) {
@@ -548,7 +657,7 @@ class Compiler {
548657 }
549658
550659 virtual void callIndirect(int l) {
551- fprintf(stderr, "callIndirect(%d);\n", l);
660+ LOG_API("callIndirect(%d);\n", l);
552661 int argCount = l >> 2;
553662 int poppedArgs = argCount > 4 ? 4 : argCount;
554663 int adjustedL = l - (poppedArgs << 2);
@@ -560,7 +669,7 @@ class Compiler {
560669 }
561670
562671 virtual void adjustStackAfterCall(int l, bool isIndirect) {
563- fprintf(stderr, "adjustStackAfterCall(%d, %d);\n", l, isIndirect);
672+ LOG_API("adjustStackAfterCall(%d, %d);\n", l, isIndirect);
564673 int argCount = l >> 2;
565674 int stackArgs = argCount > 4 ? argCount - 4 : 0;
566675 int stackUse = stackArgs + (isIndirect ? 1 : 0);
@@ -578,11 +687,11 @@ class Compiler {
578687
579688 /* output a symbol and patch all calls to it */
580689 virtual void gsym(int t) {
581- fprintf(stderr, "gsym(0x%x)\n", t);
690+ LOG_API("gsym(0x%x)\n", t);
582691 int n;
583692 int base = getBase();
584693 int pc = getPC();
585- fprintf(stderr, "pc = 0x%x\n", pc);
694+ LOG_API("pc = 0x%x\n", pc);
586695 while (t) {
587696 int data = * (int*) t;
588697 int decodedOffset = ((BRANCH_REL_ADDRESS_MASK & data) << 2);
@@ -597,8 +706,20 @@ class Compiler {
597706 }
598707 }
599708
709+ virtual int finishCompile() {
710+#if defined(__arm__)
711+ const long base = long(getBase());
712+ const long curr = long(getPC());
713+ int err = cacheflush(base, curr, 0);
714+ return err;
715+#else
716+ return 0;
717+#endif
718+ }
719+
600720 virtual int disassemble(FILE* out) {
601- disasmOut = out;
721+#ifdef ENABLE_ARM_DISASSEMBLY
722+ disasmOut = out;
602723 disasm_interface_t di;
603724 di.di_readword = disassemble_readword;
604725 di.di_printaddr = disassemble_printaddr;
@@ -610,6 +731,7 @@ class Compiler {
610731 fprintf(out, "%08x: %08x ", i, *(int*) i);
611732 ::disasm(&di, i, 0);
612733 }
734+#endif
613735 return 0;
614736 }
615737
@@ -679,7 +801,7 @@ class Compiler {
679801 }
680802 };
681803
682-#endif // PROVIDE_X86_CODEGEN
804+#endif // PROVIDE_ARM_CODEGEN
683805
684806 #ifdef PROVIDE_X86_CODEGEN
685807
@@ -730,23 +852,23 @@ class Compiler {
730852 o(0x92); /* xchg %edx, %eax */
731853 }
732854
733- virtual void clearECX() {
855+ virtual void clearR1() {
734856 oad(0xb9, 0); /* movl $0, %ecx */
735857 }
736858
737- virtual void pushEAX() {
859+ virtual void pushR0() {
738860 o(0x50); /* push %eax */
739861 }
740862
741- virtual void popECX() {
863+ virtual void popR1() {
742864 o(0x59); /* pop %ecx */
743865 }
744866
745- virtual void storeEAXToAddressECX(bool isInt) {
867+ virtual void storeR0ToR1(bool isInt) {
746868 o(0x0188 + isInt); /* movl %eax/%al, (%ecx) */
747869 }
748870
749- virtual void loadEAXIndirect(bool isInt) {
871+ virtual void loadR0FromR0(bool isInt) {
750872 if (isInt)
751873 o(0x8b); /* mov (%eax), %eax */
752874 else
@@ -754,15 +876,15 @@ class Compiler {
754876 ob(0); /* add zero in code */
755877 }
756878
757- virtual void leaEAX(int ea) {
879+ virtual void leaR0(int ea) {
758880 gmov(10, ea); /* leal EA, %eax */
759881 }
760882
761- virtual void storeEAX(int ea) {
883+ virtual void storeR0(int ea) {
762884 gmov(6, ea); /* mov %eax, EA */
763885 }
764886
765- virtual void loadEAX(int ea, bool isIncDec, int op) {
887+ virtual void loadR0(int ea, bool isIncDec, int op) {
766888 gmov(8, ea); /* mov EA, %eax */
767889 if (isIncDec) {
768890 /* Implement post-increment or post decrement.
@@ -776,7 +898,7 @@ class Compiler {
776898 return oad(0xec81, 0); /* sub $xxx, %esp */
777899 }
778900
779- virtual void storeEAToArg(int l) {
901+ virtual void storeR0ToArg(int l) {
780902 oad(0x248489, l); /* movl %eax, xxx(%esp) */
781903 }
782904
@@ -808,7 +930,7 @@ class Compiler {
808930 }
809931
810932 virtual int disassemble(FILE* out) {
811- return 1;
933+ return 0;
812934 }
813935
814936 /* output a symbol and patch all calls to it */
@@ -822,6 +944,10 @@ class Compiler {
822944 }
823945 }
824946
947+ virtual int finishCompile() {
948+ return 0;
949+ }
950+
825951 private:
826952
827953 /** Output 1 to 4 bytes.
@@ -868,6 +994,39 @@ class Compiler {
868994
869995 #endif // PROVIDE_X86_CODEGEN
870996
997+ class InputStream {
998+ public:
999+ virtual int get() = 0;
1000+ virtual long tell() = 0;
1001+ };
1002+
1003+ class FileInputStream : public InputStream {
1004+ public:
1005+ FileInputStream(FILE* in) : f(in) {}
1006+ virtual int get() { return fgetc(f); }
1007+ virtual long tell() { return ftell(f); }
1008+ private:
1009+ FILE* f;
1010+ };
1011+
1012+ class TextInputStream : public InputStream {
1013+ public:
1014+ TextInputStream(const char* text, size_t textLength)
1015+ : pText(text), mTextLength(textLength), mPosition(0) {
1016+ }
1017+ virtual int get() {
1018+ return mPosition < mTextLength ? pText[mPosition++] : EOF;
1019+ }
1020+ virtual long tell() {
1021+ return mPosition;
1022+ }
1023+
1024+ private:
1025+ const char* pText;
1026+ size_t mTextLength;
1027+ size_t mPosition;
1028+ };
1029+
8711030 /* vars: value of variables
8721031 loc : local variable index
8731032 glo : global variable index
@@ -882,7 +1041,8 @@ class Compiler {
8821041 void* pSymbolBase;
8831042 void* pGlobalBase;
8841043 void* pVarsBase;
885- FILE* file;
1044+
1045+ InputStream* file;
8861046
8871047 CodeBuf codeBuf;
8881048 CodeGenerator* pGen;
@@ -957,7 +1117,7 @@ class Compiler {
9571117 ch = dch;
9581118 }
9591119 } else
960- ch = fgetc(file);
1120+ ch = file->get();
9611121 /* printf("ch=%c 0x%x\n", ch, ch); */
9621122 }
9631123
@@ -1108,7 +1268,7 @@ class Compiler {
11081268 va_list ap;
11091269
11101270 va_start(ap, fmt);
1111- fprintf(stderr, "%ld: ", ftell((FILE *) file));
1271+ fprintf(stderr, "%ld: ", file->tell());
11121272 vfprintf(stderr, fmt, ap);
11131273 fprintf(stderr, "\n");
11141274 va_end(ap);
@@ -1149,7 +1309,7 @@ class Compiler {
11491309 } else if (c == 2) {
11501310 /* -, +, !, ~ */
11511311 unary(0);
1152- pGen->clearECX();
1312+ pGen->clearR1();
11531313 if (t == '!')
11541314 pGen->gcmp(a);
11551315 else
@@ -1175,15 +1335,15 @@ class Compiler {
11751335 unary(0);
11761336 if (tok == '=') {
11771337 next();
1178- pGen->pushEAX();
1338+ pGen->pushR0();
11791339 expr();
1180- pGen->popECX();
1181- pGen->storeEAXToAddressECX(t == TOK_INT);
1340+ pGen->popR1();
1341+ pGen->storeR0ToR1(t == TOK_INT);
11821342 } else if (t) {
1183- pGen->loadEAXIndirect(t == TOK_INT);
1343+ pGen->loadR0FromR0(t == TOK_INT);
11841344 }
11851345 } else if (t == '&') {
1186- pGen->leaEAX(*(int *) tok);
1346+ pGen->leaR0(*(int *) tok);
11871347 next();
11881348 } else {
11891349 n = *(int *) t;
@@ -1195,10 +1355,10 @@ class Compiler {
11951355 /* assignment */
11961356 next();
11971357 expr();
1198- pGen->storeEAX(n);
1358+ pGen->storeR0(n);
11991359 } else if (tok != '(') {
12001360 /* variable */
1201- pGen->loadEAX(n, tokl == 11, tokc);
1361+ pGen->loadR0(n, tokl == 11, tokc);
12021362 if (tokl == 11) {
12031363 next();
12041364 }
@@ -1209,7 +1369,7 @@ class Compiler {
12091369 /* function call */
12101370 if (tok == '(') {
12111371 if (n == 1)
1212- pGen->pushEAX();
1372+ pGen->pushR0();
12131373
12141374 /* push args and invert order */
12151375 a = pGen->beginFunctionCallArguments();
@@ -1217,7 +1377,7 @@ class Compiler {
12171377 l = 0;
12181378 while (tok != ')') {
12191379 expr();
1220- pGen->storeEAToArg(l);
1380+ pGen->storeR0ToArg(l);
12211381 if (tok == ',')
12221382 next();
12231383 l = l + 4;
@@ -1255,9 +1415,9 @@ class Compiler {
12551415 a = pGen->gtst(t == OP_LOGICAL_OR, a); /* && and || output code generation */
12561416 sum(l);
12571417 } else {
1258- pGen->pushEAX();
1418+ pGen->pushR0();
12591419 sum(l);
1260- pGen->popECX();
1420+ pGen->popR1();
12611421
12621422 if ((l == 4) | (l == 5)) {
12631423 pGen->gcmp(t);
@@ -1420,6 +1580,10 @@ class Compiler {
14201580 delete pGen;
14211581 pGen = 0;
14221582 }
1583+ if (file) {
1584+ delete file;
1585+ file = 0;
1586+ }
14231587 }
14241588
14251589 void clear() {
@@ -1470,7 +1634,7 @@ class Compiler {
14701634 #endif
14711635 }
14721636 if (pGen == NULL) {
1473- fprintf(stderr, "No code generator defined.");
1637+ fprintf(stderr, "No code generator defined.\n");
14741638 }
14751639 }
14761640
@@ -1490,16 +1654,16 @@ public:
14901654 cleanup();
14911655 }
14921656
1493- int compile(FILE* in, args& args) {
1657+ int compile(const char* text, size_t textLength) {
14941658 cleanup();
14951659 clear();
14961660 codeBuf.init(ALLOC_SIZE);
1497- setArchitecture(args.architecture);
1661+ setArchitecture(NULL);
14981662 if (!pGen) {
14991663 return -1;
15001664 }
15011665 pGen->init(&codeBuf);
1502- file = in;
1666+ file = new TextInputStream(text, textLength);
15031667 sym_stk = (intptr_t) calloc(1, ALLOC_SIZE);
15041668 dstk = (intptr_t) strcpy((char*) sym_stk,
15051669 " int if else while break return for define main ")
@@ -1534,6 +1698,38 @@ public:
15341698 return pGen->disassemble(out);
15351699 }
15361700
1701+ /* Look through the symbol table to find a symbol.
1702+ * If found, return its value.
1703+ */
1704+ void* lookup(const char* name) {
1705+ if (!sym_stk) {
1706+ return NULL;
1707+ }
1708+ size_t nameLen = strlen(name);
1709+ char* pSym = (char*) sym_stk;
1710+ char c;
1711+ for(;;) {
1712+ c = *pSym++;
1713+ if (c == 0) {
1714+ break;
1715+ }
1716+ if (c == TAG_TOK) {
1717+ if (memcmp(pSym, name, nameLen) == 0
1718+ && pSym[nameLen] == TAG_TOK) {
1719+ int tok = pSym - 1 - (char*) sym_stk;
1720+ tok = tok * 8 + TOK_IDENT;
1721+ if (tok <= TOK_DEFINE) {
1722+ return 0;
1723+ } else {
1724+ tok = vars + tok;
1725+ return * (void**) tok;
1726+ }
1727+ }
1728+ }
1729+ }
1730+ return NULL;
1731+ }
1732+
15371733 };
15381734
15391735 const char* Compiler::operatorChars =
@@ -1578,96 +1774,130 @@ const int Compiler::X86CodeGenerator::operatorHelper[] = {
15781774 };
15791775 #endif
15801776
1581-} // namespace acc
1777+struct ACCscript {
1778+ ACCscript() {
1779+ text = 0;
1780+ textLength = 0;
1781+ accError = ACC_NO_ERROR;
1782+ }
15821783
1583-// This is a separate function so it can easily be set by breakpoint in gdb.
1584-int run(acc::Compiler& c, int argc, char** argv) {
1585- return c.run(argc, argv);
1586-}
1784+ ~ACCscript() {
1785+ delete text;
1786+ }
15871787
1588-int main(int argc, char** argv) {
1589- bool doDump = false;
1590- bool doDisassemble = false;
1591- const char* inFile = NULL;
1592- const char* outFile = NULL;
1593- const char* architecture = NULL;
1594- int i;
1595- for (i = 1; i < argc; i++) {
1596- char* arg = argv[i];
1597- if (arg[0] == '-') {
1598- switch (arg[1]) {
1599- case 'a':
1600- if (i + 1 >= argc) {
1601- fprintf(stderr, "Expected architecture after -a\n");
1602- return 2;
1603- }
1604- architecture = argv[i+1];
1605- i += 1;
1606- break;
1607- case 'd':
1608- if (i + 1 >= argc) {
1609- fprintf(stderr, "Expected filename after -d\n");
1610- return 2;
1611- }
1612- doDump = true;
1613- outFile = argv[i + 1];
1614- i += 1;
1615- break;
1616- case 'S':
1617- doDisassemble = true;
1618- break;
1619- default:
1620- fprintf(stderr, "Unrecognized flag %s\n", arg);
1621- return 3;
1622- }
1623- } else if (inFile == NULL) {
1624- inFile = arg;
1625- } else {
1626- break;
1788+ void setError(ACCenum error) {
1789+ if (accError == ACC_NO_ERROR && error != ACC_NO_ERROR) {
1790+ accError = error;
16271791 }
16281792 }
16291793
1630- FILE* in = stdin;
1631- if (inFile) {
1632- in = fopen(inFile, "r");
1633- if (!in) {
1634- fprintf(stderr, "Could not open input file %s\n", inFile);
1635- return 1;
1636- }
1794+ ACCenum getError() {
1795+ ACCenum result = accError;
1796+ accError = ACC_NO_ERROR;
1797+ return result;
16371798 }
1638- acc::Compiler compiler;
1639- acc::Compiler::args args;
1640- if (architecture != NULL) {
1641- args.architecture = architecture;
1799+
1800+ Compiler compiler;
1801+ char* text;
1802+ int textLength;
1803+ ACCenum accError;
1804+};
1805+
1806+
1807+extern "C"
1808+ACCscript* accCreateScript() {
1809+ return new ACCscript();
1810+}
1811+
1812+extern "C"
1813+ACCenum accGetError( ACCscript* script ) {
1814+ return script->getError();
1815+}
1816+
1817+extern "C"
1818+void accDeleteScript(ACCscript* script) {
1819+ delete script;
1820+}
1821+
1822+extern "C"
1823+void accScriptSource(ACCscript* script,
1824+ ACCsizei count,
1825+ const ACCchar ** string,
1826+ const ACCint * length) {
1827+ int totalLength = 0;
1828+ for(int i = 0; i < count; i++) {
1829+ int len = -1;
1830+ const ACCchar* s = string[i];
1831+ if (length) {
1832+ len = length[i];
1833+ }
1834+ if (len < 0) {
1835+ len = strlen(s);
1836+ }
1837+ totalLength += len;
16421838 }
1643- int compileResult = compiler.compile(in, args);
1644- if (in != stdin) {
1645- fclose(in);
1839+ delete script->text;
1840+ char* text = new char[totalLength + 1];
1841+ script->text = text;
1842+ script->textLength = totalLength;
1843+ char* dest = text;
1844+ for(int i = 0; i < count; i++) {
1845+ int len = -1;
1846+ const ACCchar* s = string[i];
1847+ if (length) {
1848+ len = length[i];
1849+ }
1850+ if (len < 0) {
1851+ len = strlen(s);
1852+ }
1853+ memcpy(dest, s, len);
1854+ dest += len;
16461855 }
1647- if (compileResult) {
1648- fprintf(stderr, "Compile failed: %d\n", compileResult);
1649- return 6;
1856+ text[totalLength] = '\0';
1857+}
1858+
1859+extern "C"
1860+void accCompileScript(ACCscript* script) {
1861+ int result = script->compiler.compile(script->text, script->textLength);
1862+ if (result) {
1863+ script->setError(ACC_INVALID_OPERATION);
16501864 }
1651- if (doDisassemble) {
1652- compiler.disassemble(stderr);
1865+}
1866+
1867+extern "C"
1868+void accGetScriptiv(ACCscript* script,
1869+ ACCenum pname,
1870+ ACCint * params) {
1871+ switch (pname) {
1872+ case ACC_INFO_LOG_LENGTH:
1873+ *params = 0;
1874+ break;
16531875 }
1654- if (doDump) {
1655- FILE* save = fopen(outFile, "w");
1656- if (!save) {
1657- fprintf(stderr, "Could not open output file %s\n", outFile);
1658- return 5;
1659- }
1660- compiler.dump(save);
1661- fclose(save);
1662- } else {
1663- fprintf(stderr, "Executing compiled code:\n");
1664- int codeArgc = argc - i + 1;
1665- char** codeArgv = argv + i - 1;
1666- codeArgv[0] = (char*) (inFile ? inFile : "stdin");
1667- int result = run(compiler, codeArgc, codeArgv);
1668- fprintf(stderr, "result: %d\n", result);
1669- return result;
1876+}
1877+
1878+extern "C"
1879+void accGetScriptInfoLog(ACCscript* script,
1880+ ACCsizei maxLength,
1881+ ACCsizei * length,
1882+ ACCchar * infoLog) {
1883+ if (length) {
1884+ *length = 0;
1885+ }
1886+ if (maxLength > 0 && infoLog) {
1887+ *infoLog = 0;
16701888 }
1889+}
16711890
1672- return 0;
1891+extern "C"
1892+void accGetScriptLabel(ACCscript* script, const ACCchar * name,
1893+ ACCvoid ** address) {
1894+ void* value = script->compiler.lookup(name);
1895+ if (value) {
1896+ *address = value;
1897+ } else {
1898+ script->setError(ACC_INVALID_VALUE);
1899+ }
16731900 }
1901+
1902+} // namespace acc
1903+
--- a/libacc/test
+++ /dev/null
@@ -1,13 +0,0 @@
1-#!/bin/sh
2-rm -f tests/acc
3-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
4-if [ -x "tests/acc" ]; then
5- tests/acc -S tests/returnval.c
6-
7- if [ "$(uname)" = "Linux" ]; then
8- if [ "$(uname -m)" = "i686" ]; then
9- echo "Linux i686. Testing otcc.c"
10- tests/acc tests/otcc.c tests/otcc.c tests/returnval.c
11- fi
12- fi
13-fi
--- a/libacc/testarm
+++ /dev/null
@@ -1,4 +0,0 @@
1-#!/bin/sh
2-adb remount
3-adb push tests/returnval.c /system/bin/returnval.c
4-mm -j8 && adb sync && adb shell /system/bin/acc -S /system/bin/returnval.c
--- a/libacc/tests/.gitignore
+++ b/libacc/tests/.gitignore
@@ -1,2 +1,2 @@
1-acc
1+test-acc
22 *.out
--- /dev/null
+++ b/libacc/tests/Android.mk
@@ -0,0 +1,15 @@
1+LOCAL_PATH:= $(call my-dir)
2+include $(CLEAR_VARS)
3+
4+LOCAL_SRC_FILES:= \
5+ main.cpp
6+
7+LOCAL_SHARED_LIBRARIES := \
8+ libacc
9+
10+LOCAL_MODULE:= acc
11+
12+LOCAL_MODULE_TAGS := tests
13+
14+include $(BUILD_EXECUTABLE)
15+
Binary files a/libacc/tests/hello.out-orig and /dev/null differ
--- /dev/null
+++ b/libacc/tests/main.cpp
@@ -0,0 +1,102 @@
1+/*
2+ * Android "Almost" C Compiler.
3+ * This is a compiler for a small subset of the C language, intended for use
4+ * in scripting environments where speed and memory footprint are important.
5+ *
6+ * This code is based upon the "unobfuscated" version of the
7+ * Obfuscated Tiny C compiler, see the file LICENSE for details.
8+ *
9+ */
10+
11+#include <ctype.h>
12+#include <dlfcn.h>
13+#include <stdarg.h>
14+#include <stdint.h>
15+#include <stdio.h>
16+#include <stdlib.h>
17+#include <string.h>
18+
19+#if defined(__arm__)
20+#include <unistd.h>
21+#endif
22+
23+#include <acc/acc.h>
24+
25+
26+typedef int (*MainPtr)(int, char**);
27+// This is a separate function so it can easily be set by breakpoint in gdb.
28+int run(MainPtr mainFunc, int argc, char** argv) {
29+ return mainFunc(argc, argv);
30+}
31+
32+int main(int argc, char** argv) {
33+ const char* inFile = NULL;
34+ bool printListing;
35+ FILE* in = stdin;
36+ int i;
37+ for (i = 1; i < argc; i++) {
38+ char* arg = argv[i];
39+ if (arg[0] == '-') {
40+ switch (arg[1]) {
41+ case 'S':
42+ printListing = true;
43+ break;
44+ default:
45+ fprintf(stderr, "Unrecognized flag %s\n", arg);
46+ return 3;
47+ }
48+ } else if (inFile == NULL) {
49+ inFile = arg;
50+ } else {
51+ break;
52+ }
53+ }
54+
55+ if (! inFile) {
56+ fprintf(stderr, "input file required\n");
57+ return 2;
58+ }
59+
60+ if (inFile) {
61+ in = fopen(inFile, "r");
62+ if (!in) {
63+ fprintf(stderr, "Could not open input file %s\n", inFile);
64+ return 1;
65+ }
66+ }
67+
68+ fseek(in, 0, SEEK_END);
69+ size_t fileSize = (size_t) ftell(in);
70+ rewind(in);
71+ ACCchar* text = new ACCchar[fileSize];
72+ size_t bytesRead = fread(text, 1, fileSize, in);
73+ if (bytesRead != fileSize) {
74+ fprintf(stderr, "Could not read all of file %s\n", inFile);
75+ }
76+
77+ ACCscript* script = accCreateScript();
78+
79+ const ACCchar* scriptSource[] = {text};
80+ accScriptSource(script, 1, scriptSource, NULL);
81+ delete[] text;
82+
83+ accCompileScript(script);
84+
85+ MainPtr mainPointer = 0;
86+
87+ accGetScriptLabel(script, "main", (ACCvoid**) & mainPointer);
88+
89+ int result = accGetError(script);
90+ if (result == ACC_NO_ERROR) {
91+ fprintf(stderr, "Executing compiled code:\n");
92+ int codeArgc = argc - i + 1;
93+ char** codeArgv = argv + i - 1;
94+ codeArgv[0] = (char*) (inFile ? inFile : "stdin");
95+ result = run(mainPointer, codeArgc, codeArgv);
96+ fprintf(stderr, "result: %d\n", result);
97+ }
98+
99+ accDeleteScript(script);
100+
101+ return result;
102+}
Binary files a/libacc/tests/otcc.out-orig and /dev/null differ
--- /dev/null
+++ b/libacc/tests/testarm
@@ -0,0 +1,9 @@
1+#!/bin/sh
2+adb remount
3+adb shell rm /system/bin/acc
4+adb push data/returnval.c /system/bin/returnval.c
5+cd ..
6+mm -j8
7+cd tests
8+adb sync
9+adb shell /system/bin/acc -S /system/bin/returnval.c
--- /dev/null
+++ b/libacc/tests/testlocal
@@ -0,0 +1,15 @@
1+#!/bin/sh
2+rm -f test-acc
3+cd ..
4+g++ -I../include acc.cpp disassem.cpp tests/main.cpp -g -ldl -o tests/test-acc
5+cd tests
6+if [ -x "test-acc" ]; then
7+ ./test-acc -S data/returnval.c
8+
9+ if [ "$(uname)" = "Linux" ]; then
10+ if [ "$(uname -m)" = "i686" ]; then
11+ echo "Linux i686. Testing otcc.c"
12+ ./test-acc data/otcc.c data/otcc.c data/returnval.c
13+ fi
14+ fi
15+fi
--- a/libcutils/Android.mk
+++ b/libcutils/Android.mk
@@ -17,7 +17,6 @@ LOCAL_PATH := $(my-dir)
1717 include $(CLEAR_VARS)
1818
1919 commonSources := \
20- abort_socket.c \
2120 array.c \
2221 hashmap.c \
2322 atomic.c \
@@ -45,22 +44,23 @@ commonHostSources := \
4544 # some files must not be compiled when building against Mingw
4645 # they correspond to features not used by our host development tools
4746 # which are also hard or even impossible to port to native Win32
48-WITH_MINGW :=
47+WINDOWS_HOST_ONLY :=
4948 ifeq ($(HOST_OS),windows)
5049 ifeq ($(strip $(USE_CYGWIN)),)
51- WITH_MINGW := 1
50+ WINDOWS_HOST_ONLY := 1
5251 endif
5352 endif
5453 # USE_MINGW is defined when we build against Mingw on Linux
5554 ifneq ($(strip $(USE_MINGW)),)
56- WITH_MINGW := 1
55+ WINDOWS_HOST_ONLY := 1
5756 endif
5857
59-ifeq ($(WITH_MINGW),1)
58+ifeq ($(WINDOWS_HOST_ONLY),1)
6059 commonSources += \
6160 uio.c
6261 else
6362 commonSources += \
63+ abort_socket.c \
6464 mspace.c \
6565 selector.c \
6666 tztime.c \
--- a/libcutils/abort_socket.c
+++ b/libcutils/abort_socket.c
@@ -239,7 +239,7 @@ int asocket_write(struct asocket *s, const void *buf, size_t count,
239239 }
240240
241241 if (pfd[0].revents) {
242- if (pfd[0].revents & POLLIN) {
242+ if (pfd[0].revents & POLLOUT) {
243243 /* ready to write() without blocking */
244244 do {
245245 ret = write(s->fd, buf, count);
--- a/nexus/CommandListener.cpp
+++ b/nexus/CommandListener.cpp
@@ -33,54 +33,19 @@
3333
3434 CommandListener::CommandListener() :
3535 FrameworkListener("nexus") {
36- registerCmd(new WifiEnableCmd());
37- registerCmd(new WifiDisableCmd());
38- registerCmd(new WifiScanCmd());
3936 registerCmd(new WifiScanResultsCmd());
4037 registerCmd(new WifiListNetworksCmd());
4138 registerCmd(new WifiAddNetworkCmd());
4239 registerCmd(new WifiRemoveNetworkCmd());
43- registerCmd(new WifiSetVarCmd());
44- registerCmd(new WifiGetVarCmd());
4540
46- registerCmd(new VpnEnableCmd());
47- registerCmd(new VpnSetVarCmd());
48- registerCmd(new VpnGetVarCmd());
49- registerCmd(new VpnDisableCmd());
41+ registerCmd(new GetCmd());
42+ registerCmd(new SetCmd());
5043 }
5144
5245 /* -------------
5346 * Wifi Commands
5447 * ------------ */
5548
56-CommandListener::WifiEnableCmd::WifiEnableCmd() :
57- NexusCommand("wifi_enable") {
58-}
59-
60-int CommandListener::WifiEnableCmd::runCommand(SocketClient *cli, char *data) {
61- Controller *c = NetworkManager::Instance()->findController("WIFI");
62-
63- if (c->enable())
64- cli->sendMsg(ErrorCode::OperationFailed, "Failed to enable wifi", true);
65- else
66- cli->sendMsg(ErrorCode::CommandOkay, "Wifi Enabled", false);
67- return 0;
68-}
69-
70-CommandListener::WifiDisableCmd::WifiDisableCmd() :
71- NexusCommand("wifi_disable") {
72-}
73-
74-int CommandListener::WifiDisableCmd::runCommand(SocketClient *cli, char *data) {
75- Controller *c = NetworkManager::Instance()->findController("WIFI");
76-
77- if (c->disable())
78- cli->sendMsg(ErrorCode::OperationFailed, "Failed to disable wifi", true);
79- else
80- cli->sendMsg(ErrorCode::CommandOkay, "Wifi Disabled", false);
81- return 0;
82-}
83-
8449 CommandListener::WifiAddNetworkCmd::WifiAddNetworkCmd() :
8550 NexusCommand("wifi_add_network") {
8651 }
@@ -116,21 +81,6 @@ int CommandListener::WifiRemoveNetworkCmd::runCommand(SocketClient *cli, char *d
11681 return 0;
11782 }
11883
119-CommandListener::WifiScanCmd::WifiScanCmd() :
120- NexusCommand("wifi_scan") {
121-}
122-
123-int CommandListener::WifiScanCmd::runCommand(SocketClient *cli, char *data) {
124- WifiController *wc = (WifiController *) NetworkManager::Instance()->findController("WIFI");
125-
126- if (wc->setScanMode(atoi(data)))
127- cli->sendMsg(ErrorCode::OperationFailed, "Failed to set scan mode", true);
128- else
129- cli->sendMsg(ErrorCode::CommandOkay, "Scan mode set", false);
130-
131- return 0;
132-}
133-
13484 CommandListener::WifiScanResultsCmd::WifiScanResultsCmd() :
13585 NexusCommand("wifi_scan_results") {
13686 }
@@ -181,68 +131,39 @@ int CommandListener::WifiListNetworksCmd::runCommand(SocketClient *cli, char *da
181131 return 0;
182132 }
183133
184-CommandListener::WifiSetVarCmd::WifiSetVarCmd() :
185- NexusCommand("wifi_setvar") {
186-}
187-
188-int CommandListener::WifiSetVarCmd::runCommand(SocketClient *cli, char *data) {
189- WifiController *wc = (WifiController *) NetworkManager::Instance()->findController("WIFI");
190-
191- char *bword;
192- char *last;
193- char varname[32];
194- char val[250];
195- int networkId;
196-
197- if (!(bword = strtok_r(data, ":", &last)))
198- goto out_inval;
199-
200- networkId = atoi(bword);
201-
202- if (!(bword = strtok_r(NULL, ":", &last)))
203- goto out_inval;
204-
205- strncpy(varname, bword, sizeof(varname));
206-
207- if (!(bword = strtok_r(NULL, ":", &last)))
208- goto out_inval;
209-
210- strncpy(val, bword, sizeof(val));
211-
212- LOGD("Network id %d, varname '%s', value '%s'", networkId, varname, val);
213-
214- return 0;
215-
216-out_inval:
217- errno = EINVAL;
218- cli->sendMsg(ErrorCode::CommandParameterError, "Failed to set variable.", true);
219- return 0;
220-}
134+/* ------------
135+ * Vpn Commands
136+ * ------------ */
221137
222-CommandListener::WifiGetVarCmd::WifiGetVarCmd() :
223- NexusCommand("wifi_getvar") {
138+/* ----------------
139+ * Generic Commands
140+ * ---------------- */
141+CommandListener::GetCmd::GetCmd() :
142+ NexusCommand("get") {
224143 }
225144
226-int CommandListener::WifiGetVarCmd::runCommand(SocketClient *cli, char *data) {
227- WifiController *wc = (WifiController *) NetworkManager::Instance()->findController("WIFI");
228-
145+int CommandListener::GetCmd::runCommand(SocketClient *cli, char *data) {
229146 char *bword;
230147 char *last;
231- char varname[32];
232- int networkId;
148+ char propname[32];
233149
234150 if (!(bword = strtok_r(data, ":", &last)))
235151 goto out_inval;
236152
237- networkId = atoi(bword);
153+ strncpy(propname, bword, sizeof(propname));
238154
239- if (!(bword = strtok_r(NULL, ":", &last)))
240- goto out_inval;
155+ char pb[255];
156+ snprintf(pb, sizeof(pb), "%s:", propname);
241157
242- strncpy(varname, bword, sizeof(varname));
158+ if (!NetworkManager::Instance()->getProperty(propname,
159+ &pb[strlen(pb)],
160+ sizeof(pb) - strlen(pb))) {
161+ goto out_inval;
162+ }
243163
244- LOGD("networkId = %d, varname '%s'", networkId, varname);
164+ cli->sendMsg(ErrorCode::VariableRead, pb, false);
245165
166+ cli->sendMsg(ErrorCode::CommandOkay, "Property read.", false);
246167 return 0;
247168 out_inval:
248169 errno = EINVAL;
@@ -250,106 +171,34 @@ out_inval:
250171 return 0;
251172 }
252173
253-/* ------------
254- * Vpn Commands
255- * ------------ */
256-CommandListener::VpnEnableCmd::VpnEnableCmd() :
257- NexusCommand("vpn_enable") {
258-}
259-
260-int CommandListener::VpnEnableCmd::runCommand(SocketClient *cli, char *data) {
261- Controller *c = NetworkManager::Instance()->findController("VPN");
262-
263- if (c->enable())
264- cli->sendMsg(ErrorCode::OperationFailed, "Failed to enable VPN", true);
265- else
266- cli->sendMsg(ErrorCode::CommandOkay, "VPN enabled", false);
267- return 0;
174+CommandListener::SetCmd::SetCmd() :
175+ NexusCommand("set") {
268176 }
269177
270-CommandListener::VpnSetVarCmd::VpnSetVarCmd() :
271- NexusCommand("vpn_setvar") {
272-}
273-
274-int CommandListener::VpnSetVarCmd::runCommand(SocketClient *cli, char *data) {
275- VpnController *vc = (VpnController *) NetworkManager::Instance()->findController("VPN");
276-
178+int CommandListener::SetCmd::runCommand(SocketClient *cli, char *data) {
277179 char *bword;
278180 char *last;
279- char varname[32];
280- char val[250];
181+ char propname[32];
182+ char propval[250];
281183
282184 if (!(bword = strtok_r(data, ":", &last)))
283185 goto out_inval;
284186
285- strncpy(varname, bword, sizeof(varname));
187+ strncpy(propname, bword, sizeof(propname));
286188
287189 if (!(bword = strtok_r(NULL, ":", &last)))
288190 goto out_inval;
289191
290- strncpy(val, bword, sizeof(val));
291-
292- if (!strcasecmp(varname, "vpn_gateway")) {
293- if (vc->setVpnGateway(val))
294- goto out_inval;
295- } else {
296- cli->sendMsg(ErrorCode::CommandParameterError, "Variable not found.", true);
297- return 0;
298- }
299-
300- cli->sendMsg(ErrorCode::CommandOkay, "Variable written.", false);
301- return 0;
302-
303-out_inval:
304- errno = EINVAL;
305- cli->sendMsg(ErrorCode::CommandParameterError, "Failed to set variable.", true);
306- return 0;
307-}
308-
309-CommandListener::VpnGetVarCmd::VpnGetVarCmd() :
310- NexusCommand("vpn_getvar") {
311-}
192+ strncpy(propval, bword, sizeof(propval));
312193
313-int CommandListener::VpnGetVarCmd::runCommand(SocketClient *cli, char *data) {
314- VpnController *vc = (VpnController *) NetworkManager::Instance()->findController("VPN");
315-
316- char *bword;
317- char *last;
318- char varname[32];
319-
320- if (!(bword = strtok_r(data, ":", &last)))
194+ if (NetworkManager::Instance()->setProperty(propname, propval))
321195 goto out_inval;
322-
323- strncpy(varname, bword, sizeof(varname));
324196
325- if (!strcasecmp(varname, "vpn_gateway")) {
326- char buffer[255];
327-
328- sprintf(buffer, "%s:%s", varname, inet_ntoa(vc->getVpnGateway()));
329- cli->sendMsg(ErrorCode::VariableRead, buffer, false);
330- } else {
331- cli->sendMsg(ErrorCode::CommandParameterError, "Variable not found.", true);
332- return 0;
333- }
334-
335- cli->sendMsg(ErrorCode::CommandOkay, "Variable read.", false);
197+ cli->sendMsg(ErrorCode::CommandOkay, "Property set.", false);
336198 return 0;
199+
337200 out_inval:
338201 errno = EINVAL;
339- cli->sendMsg(ErrorCode::CommandParameterError, "Failed to get variable.", true);
340- return 0;
341-}
342-
343-CommandListener::VpnDisableCmd::VpnDisableCmd() :
344- NexusCommand("vpn_disable") {
345-}
346-
347-int CommandListener::VpnDisableCmd::runCommand(SocketClient *cli, char *data) {
348- Controller *c = NetworkManager::Instance()->findController("VPN");
349-
350- if (c->disable())
351- cli->sendMsg(ErrorCode::OperationFailed, "Failed to disable VPN", true);
352- else
353- cli->sendMsg(ErrorCode::CommandOkay, "VPN disabled", false);
202+ cli->sendMsg(ErrorCode::CommandParameterError, "Failed to set property.", true);
354203 return 0;
355204 }
--- a/nexus/CommandListener.h
+++ b/nexus/CommandListener.h
@@ -25,19 +25,6 @@ public:
2525 virtual ~CommandListener() {}
2626
2727 private:
28- class WifiEnableCmd : public NexusCommand {
29- public:
30- WifiEnableCmd();
31- virtual ~WifiEnableCmd() {}
32- int runCommand(SocketClient *c, char *data);
33- };
34-
35- class WifiDisableCmd : public NexusCommand {
36- public:
37- WifiDisableCmd();
38- virtual ~WifiDisableCmd() {}
39- int runCommand(SocketClient *c, char *data);
40- };
4128
4229 class WifiScanCmd : public NexusCommand {
4330 public:
@@ -74,48 +61,19 @@ private:
7461 int runCommand(SocketClient *c, char *data);
7562 };
7663
77- class WifiSetVarCmd : public NexusCommand {
78- public:
79- WifiSetVarCmd();
80- virtual ~WifiSetVarCmd() {}
81- int runCommand(SocketClient *c, char *data);
82- };
83-
84- class WifiGetVarCmd : public NexusCommand {
85- public:
86- WifiGetVarCmd();
87- virtual ~WifiGetVarCmd() {}
88- int runCommand(SocketClient *c, char *data);
89- };
90-
91- class VpnEnableCmd : public NexusCommand {
92- public:
93- VpnEnableCmd();
94- virtual ~VpnEnableCmd() {}
95- int runCommand(SocketClient *c, char *data);
96- };
97-
98- class VpnSetVarCmd : public NexusCommand {
99- public:
100- VpnSetVarCmd();
101- virtual ~VpnSetVarCmd() {}
102- int runCommand(SocketClient *c, char *data);
103- };
104-
105- class VpnGetVarCmd : public NexusCommand {
64+ class SetCmd : public NexusCommand {
10665 public:
107- VpnGetVarCmd();
108- virtual ~VpnGetVarCmd() {}
66+ SetCmd();
67+ virtual ~SetCmd() {}
10968 int runCommand(SocketClient *c, char *data);
11069 };
11170
112- class VpnDisableCmd : public NexusCommand {
71+ class GetCmd : public NexusCommand {
11372 public:
114- VpnDisableCmd();
115- virtual ~VpnDisableCmd() {}
73+ GetCmd();
74+ virtual ~GetCmd() {}
11675 int runCommand(SocketClient *c, char *data);
11776 };
118-
11977 };
12078
12179 #endif
--- a/nexus/Controller.cpp
+++ b/nexus/Controller.cpp
@@ -14,6 +14,7 @@
1414 * limitations under the License.
1515 */
1616 #include <stdio.h>
17+#include <stdlib.h>
1718 #include <string.h>
1819 #include <fcntl.h>
1920 #include <unistd.h>
@@ -32,8 +33,13 @@
3233 extern "C" int init_module(void *, unsigned int, const char *);
3334 extern "C" int delete_module(const char *, unsigned int);
3435
35-Controller::Controller(const char *name) {
36+Controller::Controller(const char *name, const char *prefix) {
3637 mName = name;
38+ mPropertyPrefix = prefix;
39+ mProperties = new PropertyCollection();
40+
41+ mEnabled = false;
42+ registerProperty("enable");
3743 }
3844
3945 int Controller::start() {
@@ -44,12 +50,69 @@ int Controller::stop() {
4450 return 0;
4551 }
4652
53+const PropertyCollection & Controller::getProperties() {
54+ return *mProperties;
55+}
56+
57+int Controller::setProperty(const char *name, char *value) {
58+ if (!strcmp(name, "enable")) {
59+ int en = atoi(value);
60+ int rc;
61+
62+ rc = (en ? enable() : disable());
63+
64+ if (!rc)
65+ mEnabled = en;
66+
67+ return rc;
68+ }
69+
70+ errno = ENOENT;
71+ return -1;
72+}
73+
74+const char *Controller::getProperty(const char *name, char *buffer, size_t maxsize) {
75+ if (!strcmp(name, "enable")) {
76+ snprintf(buffer, maxsize, "%d", mEnabled);
77+ return buffer;
78+ }
79+
80+ errno = ENOENT;
81+ return NULL;
82+}
83+
84+int Controller::registerProperty(const char *name) {
85+ PropertyCollection::iterator it;
86+
87+ for (it = mProperties->begin(); it != mProperties->end(); ++it) {
88+ if (!strcmp(name, (*it))) {
89+ errno = EADDRINUSE;
90+ LOGE("Failed to register property (%s)", strerror(errno));
91+ return -1;
92+ }
93+ }
94+
95+ mProperties->push_back(name);
96+ return 0;
97+}
98+
99+int Controller::unregisterProperty(const char *name) {
100+ PropertyCollection::iterator it;
101+
102+ for (it = mProperties->begin(); it != mProperties->end(); ++it) {
103+ if (!strcmp(name, (*it))) {
104+ mProperties->erase(it);
105+ return 0;
106+ }
107+ }
108+ errno = ENOENT;
109+ return -1;
110+}
111+
47112 int Controller::loadKernelModule(char *modpath, const char *args) {
48113 void *module;
49114 unsigned int size;
50115
51- LOGD("loadKernelModule(%s, %s)", modpath, args);
52-
53116 module = loadFile(modpath, &size);
54117 if (!module) {
55118 errno = -EIO;
@@ -65,7 +128,6 @@ int Controller::unloadKernelModule(const char *modtag) {
65128 int rc = -1;
66129 int retries = 10;
67130
68- LOGD("unloadKernelModule(%s)", modtag);
69131 while (retries--) {
70132 rc = delete_module(modtag, O_NONBLOCK | O_EXCL);
71133 if (rc < 0 && errno == EAGAIN)
@@ -107,7 +169,6 @@ bool Controller::isKernelModuleLoaded(const char *modtag) {
107169 return false;
108170 }
109171
110-
111172 void *Controller::loadFile(char *filename, unsigned int *_size)
112173 {
113174 int ret, fd;
--- a/nexus/Controller.h
+++ b/nexus/Controller.h
@@ -16,31 +16,48 @@
1616 #ifndef _CONTROLLER_H
1717 #define _CONTROLLER_H
1818
19+#include <unistd.h>
20+#include <sys/types.h>
21+
1922 #include "../../../frameworks/base/include/utils/List.h"
2023
24+#include "PropertyCollection.h"
25+
2126 class Controller {
2227 private:
2328 const char *mName;
29+ const char *mPropertyPrefix;
30+ PropertyCollection *mProperties;
31+ bool mEnabled;
2432
2533 public:
26- Controller(const char *name);
34+ Controller(const char *name, const char *prefix);
2735 virtual ~Controller() {}
2836
2937 virtual int start();
3038 virtual int stop();
3139
32- virtual int enable() = 0;
33- virtual int disable() = 0;
40+ virtual const PropertyCollection &getProperties();
41+ virtual int setProperty(const char *name, char *value);
42+ virtual const char *getProperty(const char *name, char *buffer, size_t maxsize);
3443
35- virtual const char *getName() { return mName; }
44+ const char *getName() { return mName; }
45+ const char *getPropertyPrefix() { return mPropertyPrefix; }
3646
3747 protected:
3848 int loadKernelModule(char *modpath, const char *args);
3949 bool isKernelModuleLoaded(const char *modtag);
4050 int unloadKernelModule(const char *modtag);
4151
52+ int registerProperty(const char *name);
53+ int unregisterProperty(const char *name);
54+
4255 private:
4356 void *loadFile(char *filename, unsigned int *_size);
57+
58+ virtual int enable() = 0;
59+ virtual int disable() = 0;
60+
4461 };
4562
4663 typedef android::List<Controller *> ControllerCollection;
--- a/nexus/LoopController.cpp
+++ b/nexus/LoopController.cpp
@@ -18,7 +18,7 @@
1818 #include "LoopController.h"
1919
2020 LoopController::LoopController() :
21- Controller("LOOP") {
21+ Controller("LOOP", "loop") {
2222 }
2323
2424 int LoopController::enable() {
--- a/nexus/LoopController.h
+++ b/nexus/LoopController.h
@@ -23,6 +23,7 @@ public:
2323 LoopController();
2424 virtual ~LoopController() {}
2525
26+private:
2627 int enable();
2728 int disable();
2829 };
--- a/nexus/NetworkManager.cpp
+++ b/nexus/NetworkManager.cpp
@@ -83,6 +83,73 @@ Controller *NetworkManager::findController(const char *name) {
8383 return NULL;
8484 }
8585
86+int NetworkManager::setProperty(const char *name, char *value) {
87+ char *tmp = strdup(name);
88+ char *next = tmp;
89+ char *prefix;
90+ char *rest;
91+ ControllerCollection::iterator it;
92+
93+ if (!(prefix = strsep(&next, ".")))
94+ goto out_inval;
95+
96+ rest = next;
97+
98+ if (!strncasecmp(prefix, "netman", 6)) {
99+ errno = ENOSYS;
100+ return -1;
101+ }
102+
103+ for (it = mControllers->begin(); it != mControllers->end(); ++it) {
104+ if (!strcasecmp(prefix, (*it)->getPropertyPrefix())) {
105+ return (*it)->setProperty(rest, value);
106+ }
107+ }
108+
109+ errno = ENOENT;
110+ return -1;
111+
112+out_inval:
113+ errno = EINVAL;
114+ return -1;
115+}
116+
117+const char *NetworkManager::getProperty(const char *name, char *buffer,
118+ size_t maxsize) {
119+ char *tmp = strdup(name);
120+ char *next = tmp;
121+ char *prefix;
122+ char *rest;
123+ ControllerCollection::iterator it;
124+
125+ if (!(prefix = strsep(&next, ".")))
126+ goto out_inval;
127+
128+ rest = next;
129+
130+ if (!strncasecmp(prefix, "netman", 6)) {
131+ errno = ENOSYS;
132+ return NULL;
133+ }
134+
135+ for (it = mControllers->begin(); it != mControllers->end(); ++it) {
136+ if (!strcasecmp(prefix, (*it)->getPropertyPrefix())) {
137+ return (*it)->getProperty(rest, buffer, maxsize);
138+ }
139+ }
140+
141+ errno = ENOENT;
142+ return NULL;
143+
144+out_inval:
145+ errno = EINVAL;
146+ return NULL;
147+}
148+
149+const PropertyCollection &NetworkManager::getProperties() {
150+ return *mProperties;
151+}
152+
86153 int NetworkManager::onInterfaceCreated(Controller *c, char *name) {
87154 LOGD("Interface %s created by controller %s", name, c->getName());
88155 return 0;
--- a/nexus/NetworkManager.h
+++ b/nexus/NetworkManager.h
@@ -19,6 +19,7 @@
1919 #include <sysutils/SocketListener.h>
2020
2121 #include "Controller.h"
22+#include "PropertyCollection.h"
2223
2324 class NetworkManager {
2425 private:
@@ -27,6 +28,7 @@ private:
2728 private:
2829 ControllerCollection *mControllers;
2930 SocketListener *mBroadcaster;
31+ PropertyCollection *mProperties;
3032
3133 public:
3234 virtual ~NetworkManager() {}
@@ -37,6 +39,10 @@ public:
3739
3840 Controller *findController(const char *name);
3941
42+ const PropertyCollection &getProperties();
43+ int setProperty(const char *name, char *value);
44+ const char *getProperty(const char *name, char *buffer, size_t maxsize);
45+
4046 void setBroadcaster(SocketListener *sl) { mBroadcaster = sl; }
4147 SocketListener *getBroadcaster() { return mBroadcaster; }
4248
@@ -45,6 +51,9 @@ public:
4551 private:
4652 int startControllers();
4753 int stopControllers();
54+ int registerProperty(const char *name);
55+ int unregisterProperty(const char *name);
56+
4857 NetworkManager();
4958
5059 public:
--- a/nexus/OpenVpnController.cpp
+++ b/nexus/OpenVpnController.cpp
@@ -63,7 +63,6 @@ int OpenVpnController::enable() {
6363 }
6464
6565 int OpenVpnController::disable() {
66-
6766 if (mServiceManager->stop("openvpn"))
6867 return -1;
6968 return 0;
--- a/nexus/OpenVpnController.h
+++ b/nexus/OpenVpnController.h
@@ -31,6 +31,8 @@ public:
3131
3232 int start();
3333 int stop();
34+
35+private:
3436 int enable();
3537 int disable();
3638 };
--- /dev/null
+++ b/nexus/PropertyCollection.h
@@ -0,0 +1,25 @@
1+/*
2+ * Copyright (C) 2008 The Android Open Source Project
3+ *
4+ * Licensed under the Apache License, Version 2.0 (the "License");
5+ * you may not use this file except in compliance with the License.
6+ * You may obtain a copy of the License at
7+ *
8+ * http://www.apache.org/licenses/LICENSE-2.0
9+ *
10+ * Unless required by applicable law or agreed to in writing, software
11+ * distributed under the License is distributed on an "AS IS" BASIS,
12+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+ * See the License for the specific language governing permissions and
14+ * limitations under the License.
15+ */
16+
17+#ifndef _PROPERTY_COLLECTION_H
18+#define _PROPERTY_COLLECTION_H
19+
20+#include "../../../frameworks/base/include/utils/List.h"
21+
22+typedef android::List<const char *> PropertyCollection;
23+
24+#endif
25+
--- a/nexus/VpnController.cpp
+++ b/nexus/VpnController.cpp
@@ -14,6 +14,7 @@
1414 * limitations under the License.
1515 */
1616
17+#include <stdio.h>
1718 #include <string.h>
1819 #include <errno.h>
1920 #include <sys/socket.h>
@@ -23,7 +24,8 @@
2324 #include "VpnController.h"
2425
2526 VpnController::VpnController() :
26- Controller("VPN") {
27+ Controller("VPN", "vpn") {
28+ registerProperty("gateway");
2729 }
2830
2931 int VpnController::start() {
@@ -46,15 +48,23 @@ int VpnController::disable() {
4648 return -1;
4749 }
4850
49-int VpnController::setVpnGateway(const char *vpnGw) {
50- if (!inet_aton(vpnGw, &mVpnGateway)) {
51- errno = EINVAL;
52- return -1;
53- }
54- return 0;
51+int VpnController::setProperty(const char *name, char *value) {
52+ if (!strcmp(name, "gateway")) {
53+ if (!inet_aton(value, &mVpnGateway)) {
54+ errno = EINVAL;
55+ return -1;
56+ }
57+ return 0;
58+ }
59+
60+ return Controller::setProperty(name, value);
5561 }
5662
57-int VpnController::setVpnGateway(struct in_addr *vpnGw) {
58- memcpy(&mVpnGateway, vpnGw, sizeof(struct in_addr));
59- return 0;
63+const char *VpnController::getProperty(const char *name, char *buffer, size_t maxsize) {
64+ if (!strcmp(name, "gateway")) {
65+ snprintf(buffer, maxsize, "%s", inet_ntoa(mVpnGateway));
66+ return buffer;
67+ }
68+
69+ return Controller::getProperty(name, buffer, maxsize);
6070 }
--- a/nexus/VpnController.h
+++ b/nexus/VpnController.h
@@ -33,14 +33,14 @@ public:
3333 virtual int start();
3434 virtual int stop();
3535
36+ virtual int setProperty(const char *name, char *value);
37+ virtual const char *getProperty(const char *name, char *buffer,
38+ size_t maxlen);
39+
40+private:
3641 virtual int enable();
3742 virtual int disable();
3843
39- struct in_addr &getVpnGateway() { return mVpnGateway; }
40- int setVpnGateway(const char *vpnGw);
41- int setVpnGateway(struct in_addr *vpnGw);
42-
43-protected:
4444 };
4545
4646 #endif
--- a/nexus/WifiController.cpp
+++ b/nexus/WifiController.cpp
@@ -13,6 +13,8 @@
1313 * See the License for the specific language governing permissions and
1414 * limitations under the License.
1515 */
16+
17+#include <stdlib.h>
1618 #include <string.h>
1719 #include <errno.h>
1820
@@ -26,7 +28,7 @@
2628 #include "ErrorCode.h"
2729
2830 WifiController::WifiController(char *modpath, char *modname, char *modargs) :
29- Controller("WIFI") {
31+ Controller("WIFI", "wifi") {
3032 strncpy(mModulePath, modpath, sizeof(mModulePath));
3133 strncpy(mModuleName, modname, sizeof(mModuleName));
3234 strncpy(mModuleArgs, modargs, sizeof(mModuleArgs));
@@ -34,6 +36,8 @@ WifiController::WifiController(char *modpath, char *modname, char *modargs) :
3436 mSupplicant = new Supplicant();
3537 mScanner = new WifiScanner(mSupplicant, 10);
3638 mCurrentScanMode = 0;
39+
40+ registerProperty("scanmode");
3741 }
3842
3943 int WifiController::start() {
@@ -94,7 +98,7 @@ out_powerdown:
9498 return -1;
9599 }
96100
97-void WifiController::sendStatusBroadcast(char *msg) {
101+void WifiController::sendStatusBroadcast(const char *msg) {
98102 NetworkManager::Instance()->
99103 getBroadcaster()->
100104 sendBroadcast(ErrorCode::UnsolicitedInformational, msg, false);
@@ -167,3 +171,20 @@ ScanResultCollection *WifiController::createScanResults() {
167171 WifiNetworkCollection *WifiController::createNetworkList() {
168172 return mSupplicant->createNetworkList();
169173 }
174+
175+int WifiController::setProperty(const char *name, char *value) {
176+ if (!strcmp(name, "scanmode"))
177+ return setScanMode((uint32_t) strtoul(value, NULL, 0));
178+
179+ return Controller::setProperty(name, value);
180+}
181+
182+const char *WifiController::getProperty(const char *name, char *buffer, size_t maxsize) {
183+ if (!strcmp(name, "scanmode")) {
184+ snprintf(buffer, maxsize, "0x%.8x", mCurrentScanMode);
185+ return buffer;
186+ }
187+
188+ return Controller::getProperty(name, buffer, maxsize);
189+}
190+
--- a/nexus/WifiController.h
+++ b/nexus/WifiController.h
@@ -54,15 +54,14 @@ public:
5454 int start();
5555 int stop();
5656
57- int enable();
58- int disable();
59-
6057 int addNetwork();
6158 int removeNetwork(int networkId);
6259 WifiNetworkCollection *createNetworkList();
6360
64- int getScanMode() { return mCurrentScanMode; }
65- int setScanMode(uint32_t mode);
61+ virtual int setProperty(const char *name, char *value);
62+ virtual const char *getProperty(const char *name, char *buffer,
63+ size_t maxlen);
64+
6665 ScanResultCollection *createScanResults();
6766
6867 char *getModulePath() { return mModulePath; }
@@ -79,7 +78,13 @@ protected:
7978 virtual bool isFirmwareLoaded() = 0;
8079 virtual bool isPoweredUp() = 0;
8180
82- void sendStatusBroadcast(char *msg);
81+ void sendStatusBroadcast(const char *msg);
82+
83+private:
84+ int setScanMode(uint32_t mode);
85+ int enable();
86+ int disable();
87+
8388 };
8489
8590 #endif
--- a/nexus/WifiScanner.cpp
+++ b/nexus/WifiScanner.cpp
@@ -65,7 +65,7 @@ void WifiScanner::run() {
6565 struct timeval to;
6666 int rc = 0;
6767
68- to.tv_sec = 0;
68+ to.tv_usec = 0;
6969 to.tv_sec = mPeriod;
7070
7171 FD_ZERO(&read_fds);
@@ -83,4 +83,5 @@ void WifiScanner::run() {
8383 } else if (FD_ISSET(mCtrlPipe[0], &read_fds))
8484 break;
8585 } // while
86+ LOGD("Stopping wifi scanner");
8687 }
--- a/rootdir/etc/init.goldfish.sh
+++ b/rootdir/etc/init.goldfish.sh
@@ -34,6 +34,10 @@ case "$boot_anim" in
3434 ;;
3535 esac
3636
37+# call 'qemu-props' to set system properties from the emulator.
38+#
39+/system/bin/qemu-props
40+
3741 # this line doesn't really do anything useful. however without it the
3842 # previous setprop doesn't seem to apply for some really odd reason
3943 setprop ro.qemu.init.completed 1