system/corennnnn
リビジョン | 1edfd382ba69ff96ebd0220b05b134a90b910ea7 (tree) |
---|---|
日時 | 2009-05-28 06:25:54 |
作者 | Mathias Agopian <mathias@goog...> |
コミッター | Mathias Agopian |
Merge commit 'goog/master' into merge_master
@@ -0,0 +1 @@ | ||
1 | +*~ |
@@ -23,6 +23,7 @@ | ||
23 | 23 | #include <errno.h> |
24 | 24 | #include <string.h> |
25 | 25 | #include <time.h> |
26 | +#include <sys/time.h> | |
26 | 27 | |
27 | 28 | #include "sysdeps.h" |
28 | 29 | #include "adb.h" |
@@ -657,10 +658,25 @@ void start_logging(void) | ||
657 | 658 | void start_device_log(void) |
658 | 659 | { |
659 | 660 | 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]; | |
661 | 665 | |
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); | |
664 | 680 | if (fd < 0) |
665 | 681 | return; |
666 | 682 |
@@ -671,11 +687,6 @@ void start_device_log(void) | ||
671 | 687 | |
672 | 688 | fd = unix_open("/dev/null", O_RDONLY); |
673 | 689 | 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; | |
679 | 690 | } |
680 | 691 | #endif |
681 | 692 |
@@ -875,9 +886,10 @@ int adb_main(int is_daemon) | ||
875 | 886 | ** AID_INET to diagnose network issues (netcfg, ping) |
876 | 887 | ** AID_GRAPHICS to access the frame buffer |
877 | 888 | ** AID_NET_BT and AID_NET_BT_ADMIN to diagnose bluetooth (hcidump) |
889 | + ** AID_SDCARD_RW to allow writing to the SD card | |
878 | 890 | */ |
879 | 891 | 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 }; | |
881 | 893 | setgroups(sizeof(groups)/sizeof(groups[0]), groups); |
882 | 894 | |
883 | 895 | /* then switch user and group to "shell" */ |
@@ -919,9 +931,6 @@ int adb_main(int is_daemon) | ||
919 | 931 | fdevent_loop(); |
920 | 932 | |
921 | 933 | usb_cleanup(); |
922 | -#if ADB_HOST | |
923 | - usb_vendors_cleanup(); | |
924 | -#endif | |
925 | 934 | |
926 | 935 | return 0; |
927 | 936 | } |
@@ -1081,9 +1090,8 @@ int main(int argc, char **argv) | ||
1081 | 1090 | adb_device_banner = "recovery"; |
1082 | 1091 | recovery_mode = 1; |
1083 | 1092 | } |
1084 | -#if ADB_DEVICE_LOG | |
1093 | + | |
1085 | 1094 | start_device_log(); |
1086 | -#endif | |
1087 | 1095 | return adb_main(0); |
1088 | 1096 | #endif |
1089 | 1097 | } |
@@ -345,11 +345,6 @@ typedef enum { | ||
345 | 345 | #endif |
346 | 346 | |
347 | 347 | |
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 | - | |
353 | 348 | #if !TRACE_PACKETS |
354 | 349 | #define print_packet(tag,p) do {} while (0) |
355 | 350 | #endif |
@@ -357,11 +352,10 @@ typedef enum { | ||
357 | 352 | #define ADB_PORT 5037 |
358 | 353 | #define ADB_LOCAL_TRANSPORT_PORT 5555 |
359 | 354 | |
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 | |
362 | 358 | |
363 | -// HTC's USB Vendor ID | |
364 | -#define VENDOR_ID_HTC 0x0bb4 | |
365 | 359 | |
366 | 360 | void local_init(); |
367 | 361 | int local_connect(int port); |
@@ -213,7 +213,7 @@ int adb_connect(const char *service) | ||
213 | 213 | fprintf(stdout,"* daemon started successfully *\n"); |
214 | 214 | } |
215 | 215 | /* give the server some time to start properly and detect devices */ |
216 | - adb_sleep_ms(2000); | |
216 | + adb_sleep_ms(3000); | |
217 | 217 | // fall through to _adb_connect |
218 | 218 | } else { |
219 | 219 | // if server was running, check its version to make sure it is not out of date |
@@ -135,11 +135,9 @@ int is_adb_interface(int vid, int pid, int usb_class, int usb_subclass, int usb_ | ||
135 | 135 | unsigned i; |
136 | 136 | for (i = 0; i < vendorIdCount; i++) { |
137 | 137 | 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; | |
143 | 141 | } |
144 | 142 | |
145 | 143 | return 0; |
@@ -32,9 +32,6 @@ | ||
32 | 32 | |
33 | 33 | #define DBG D |
34 | 34 | |
35 | -#define ADB_SUBCLASS 0x42 | |
36 | -#define ADB_PROTOCOL 0x1 | |
37 | - | |
38 | 35 | static IONotificationPortRef notificationPort = 0; |
39 | 36 | static io_iterator_t* notificationIterators; |
40 | 37 |
@@ -16,25 +16,119 @@ | ||
16 | 16 | |
17 | 17 | #include "usb_vendors.h" |
18 | 18 | |
19 | -#include "sysdeps.h" | |
20 | 19 | #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" | |
21 | 31 | #include "adb.h" |
22 | 32 | |
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]; | |
24 | 55 | unsigned vendorIdCount = 0; |
25 | 56 | |
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 | + } | |
32 | 101 | } |
33 | 102 | |
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); | |
39 | 126 | } |
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 | |
40 | 134 | } |
@@ -17,10 +17,9 @@ | ||
17 | 17 | #ifndef __USB_VENDORS_H |
18 | 18 | #define __USB_VENDORS_H |
19 | 19 | |
20 | -extern int* vendorIds; | |
20 | +extern int vendorIds[]; | |
21 | 21 | extern unsigned vendorIdCount; |
22 | 22 | |
23 | 23 | void usb_vendors_init(void); |
24 | -void usb_vendors_cleanup(void); | |
25 | 24 | |
26 | 25 | #endif |
\ No newline at end of file |
@@ -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 |
@@ -115,6 +115,7 @@ static struct perms_ devperms[] = { | ||
115 | 115 | { "/dev/oncrpc/", 0660, AID_ROOT, AID_SYSTEM, 1 }, |
116 | 116 | { "/dev/adsp/", 0660, AID_SYSTEM, AID_AUDIO, 1 }, |
117 | 117 | { "/dev/mt9t013", 0660, AID_SYSTEM, AID_SYSTEM, 0 }, |
118 | + { "/dev/msm_camera/", 0660, AID_SYSTEM, AID_SYSTEM, 1 }, | |
118 | 119 | { "/dev/akm8976_daemon",0640, AID_COMPASS, AID_SYSTEM, 0 }, |
119 | 120 | { "/dev/akm8976_aot", 0640, AID_COMPASS, AID_SYSTEM, 0 }, |
120 | 121 | { "/dev/akm8976_pffd", 0640, AID_COMPASS, AID_SYSTEM, 0 }, |
@@ -384,7 +385,10 @@ static void handle_device_event(struct uevent *uevent) | ||
384 | 385 | } else if (!strncmp(uevent->subsystem, "adsp", 4)) { |
385 | 386 | base = "/dev/adsp/"; |
386 | 387 | 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)) { | |
388 | 392 | base = "/dev/input/"; |
389 | 393 | mkdir(base, 0755); |
390 | 394 | } else if(!strncmp(uevent->subsystem, "mtd", 3)) { |
@@ -5,8 +5,15 @@ include $(CLEAR_VARS) | ||
5 | 5 | # Shared library |
6 | 6 | # |
7 | 7 | |
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 | |
11 | 10 | |
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 |
@@ -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 | + |
@@ -4,33 +4,10 @@ | ||
4 | 4 | * in scripting environments where speed and memory footprint are important. |
5 | 5 | * |
6 | 6 | * 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. | |
9 | 8 | * |
10 | 9 | */ |
11 | 10 | |
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 | - | |
34 | 11 | #include <ctype.h> |
35 | 12 | #include <dlfcn.h> |
36 | 13 | #include <stdarg.h> |
@@ -59,6 +36,13 @@ | ||
59 | 36 | #include "disassem.h" |
60 | 37 | #endif |
61 | 38 | |
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 | + | |
62 | 46 | namespace acc { |
63 | 47 | |
64 | 48 | class Compiler { |
@@ -116,6 +100,27 @@ class Compiler { | ||
116 | 100 | } |
117 | 101 | }; |
118 | 102 | |
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 | + | |
119 | 124 | class CodeGenerator { |
120 | 125 | public: |
121 | 126 | CodeGenerator() {} |
@@ -125,70 +130,170 @@ class Compiler { | ||
125 | 130 | this->pCodeBuf = pCodeBuf; |
126 | 131 | } |
127 | 132 | |
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. | |
129 | 145 | */ |
130 | 146 | virtual int functionEntry(int argCount) = 0; |
131 | 147 | |
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; | |
133 | 157 | |
134 | - /* load immediate value */ | |
158 | + /* load immediate value to R0 */ | |
135 | 159 | virtual void li(int t) = 0; |
136 | 160 | |
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 | + */ | |
137 | 164 | virtual int gjmp(int t) = 0; |
138 | 165 | |
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 | + */ | |
140 | 171 | virtual int gtst(bool l, int t) = 0; |
141 | 172 | |
173 | + /* Compare R1 against R0, and store the boolean result in R0. | |
174 | + * op specifies the comparison. | |
175 | + */ | |
142 | 176 | virtual void gcmp(int op) = 0; |
143 | 177 | |
178 | + /* Perform the arithmetic op specified by op. R1 is the | |
179 | + * left argument, R0 is the right argument. | |
180 | + */ | |
144 | 181 | virtual void genOp(int op) = 0; |
145 | 182 | |
146 | - virtual void clearECX() = 0; | |
147 | - | |
148 | - virtual void pushEAX() = 0; | |
183 | + /* Set R1 to 0. | |
184 | + */ | |
185 | + virtual void clearR1() = 0; | |
149 | 186 | |
150 | - virtual void popECX() = 0; | |
187 | + /* Push R0 onto the stack. | |
188 | + */ | |
189 | + virtual void pushR0() = 0; | |
151 | 190 | |
152 | - virtual void storeEAXToAddressECX(bool isInt) = 0; | |
191 | + /* Pop R1 off of the stack. | |
192 | + */ | |
193 | + virtual void popR1() = 0; | |
153 | 194 | |
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; | |
155 | 201 | |
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; | |
157 | 208 | |
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; | |
159 | 215 | |
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; | |
161 | 232 | |
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 | + */ | |
162 | 238 | virtual int beginFunctionCallArguments() = 0; |
163 | 239 | |
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 | + */ | |
166 | 252 | virtual void endFunctionCallArguments(int a, int l) = 0; |
167 | 253 | |
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 | + */ | |
169 | 259 | virtual int callForward(int symbol) = 0; |
170 | 260 | |
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 | + */ | |
171 | 265 | virtual void callRelative(int t) = 0; |
172 | 266 | |
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 | + */ | |
173 | 271 | virtual void callIndirect(int l) = 0; |
174 | 272 | |
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 | + */ | |
175 | 278 | virtual void adjustStackAfterCall(int l, bool isIndirect) = 0; |
176 | 279 | |
280 | + /* Print a disassembly of the assembled code to out. Return | |
281 | + * non-zero if there is an error. | |
282 | + */ | |
177 | 283 | virtual int disassemble(FILE* out) = 0; |
178 | 284 | |
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 | + */ | |
180 | 288 | virtual void gsym(int t) = 0; |
181 | 289 | |
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; | |
192 | 297 | |
193 | 298 | /** |
194 | 299 | * Adjust relative branches by this amount. |
@@ -214,6 +319,10 @@ class Compiler { | ||
214 | 319 | intptr_t getPC() { |
215 | 320 | return pCodeBuf->getPC(); |
216 | 321 | } |
322 | + | |
323 | + intptr_t getSize() { | |
324 | + return pCodeBuf->getSize(); | |
325 | + } | |
217 | 326 | private: |
218 | 327 | CodeBuf* pCodeBuf; |
219 | 328 | }; |
@@ -228,7 +337,7 @@ class Compiler { | ||
228 | 337 | /* returns address to patch with local variable size |
229 | 338 | */ |
230 | 339 | virtual int functionEntry(int argCount) { |
231 | - fprintf(stderr, "functionEntry(%d);\n", argCount); | |
340 | + LOG_API(stderr, "functionEntry(%d);\n", argCount); | |
232 | 341 | // sp -> arg4 arg5 ... |
233 | 342 | // Push our register-based arguments back on the stack |
234 | 343 | if (argCount > 0) { |
@@ -243,7 +352,7 @@ class Compiler { | ||
243 | 352 | } |
244 | 353 | |
245 | 354 | 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); | |
247 | 356 | // Patch local variable allocation code: |
248 | 357 | if (localVariableSize < 0 || localVariableSize > 255) { |
249 | 358 | error("localVariables out of range: %d", localVariableSize); |
@@ -270,7 +379,7 @@ class Compiler { | ||
270 | 379 | |
271 | 380 | /* load immediate value */ |
272 | 381 | virtual void li(int t) { |
273 | - fprintf(stderr, "li(%d);\n", t); | |
382 | + LOG_API("li(%d);\n", t); | |
274 | 383 | if (t >= 0 && t < 255) { |
275 | 384 | o4(0xE3A00000 + t); // mov r0, #0 |
276 | 385 | } else if (t >= -256 && t < 0) { |
@@ -285,20 +394,20 @@ class Compiler { | ||
285 | 394 | } |
286 | 395 | |
287 | 396 | virtual int gjmp(int t) { |
288 | - fprintf(stderr, "gjmp(%d);\n", t); | |
397 | + LOG_API("gjmp(%d);\n", t); | |
289 | 398 | return o4(0xEA000000 | encodeAddress(t)); // b .L33 |
290 | 399 | } |
291 | 400 | |
292 | 401 | /* l = 0: je, l == 1: jne */ |
293 | 402 | 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); | |
295 | 404 | o4(0xE3500000); // cmp r0,#0 |
296 | 405 | int branch = l ? 0x1A000000 : 0x0A000000; // bne : beq |
297 | 406 | return o4(branch | encodeAddress(t)); |
298 | 407 | } |
299 | 408 | |
300 | 409 | virtual void gcmp(int op) { |
301 | - fprintf(stderr, "gcmp(%d);\n", op); | |
410 | + LOG_API("gcmp(%d);\n", op); | |
302 | 411 | o4(0xE1510000); // cmp r1, r1 |
303 | 412 | switch(op) { |
304 | 413 | case OP_EQUALS: |
@@ -332,7 +441,7 @@ class Compiler { | ||
332 | 441 | } |
333 | 442 | |
334 | 443 | virtual void genOp(int op) { |
335 | - fprintf(stderr, "genOp(%d);\n", op); | |
444 | + LOG_API("genOp(%d);\n", op); | |
336 | 445 | switch(op) { |
337 | 446 | case OP_MUL: |
338 | 447 | o4(0x0E0000091); // mul r0,r1,r0 |
@@ -378,23 +487,23 @@ class Compiler { | ||
378 | 487 | #endif |
379 | 488 | } |
380 | 489 | |
381 | - virtual void clearECX() { | |
382 | - fprintf(stderr, "clearECX();\n"); | |
490 | + virtual void clearR1() { | |
491 | + LOG_API("clearR1();\n"); | |
383 | 492 | o4(0xE3A01000); // mov r1, #0 |
384 | 493 | } |
385 | 494 | |
386 | - virtual void pushEAX() { | |
387 | - fprintf(stderr, "pushEAX();\n"); | |
495 | + virtual void pushR0() { | |
496 | + LOG_API("pushR0();\n"); | |
388 | 497 | o4(0xE92D0001); // stmfd sp!,{r0} |
389 | 498 | } |
390 | 499 | |
391 | - virtual void popECX() { | |
392 | - fprintf(stderr, "popECX();\n"); | |
500 | + virtual void popR1() { | |
501 | + LOG_API("popR1();\n"); | |
393 | 502 | o4(0xE8BD0002); // ldmfd sp!,{r1} |
394 | 503 | } |
395 | 504 | |
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); | |
398 | 507 | if (isInt) { |
399 | 508 | o4(0xE5810000); // str r0, [r1] |
400 | 509 | } else { |
@@ -402,16 +511,16 @@ class Compiler { | ||
402 | 511 | } |
403 | 512 | } |
404 | 513 | |
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); | |
407 | 516 | if (isInt) |
408 | 517 | o4(0xE5900000); // ldr r0, [r0] |
409 | 518 | else |
410 | 519 | o4(0xE5D00000); // ldrb r0, [r0] |
411 | 520 | } |
412 | 521 | |
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); | |
415 | 524 | if (ea < LOCAL) { |
416 | 525 | // Local, fp relative |
417 | 526 | if (ea < -1023 || ea > 1023 || ((ea & 3) != 0)) { |
@@ -431,8 +540,8 @@ class Compiler { | ||
431 | 540 | } |
432 | 541 | } |
433 | 542 | |
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); | |
436 | 545 | if (ea < LOCAL) { |
437 | 546 | // Local, fp relative |
438 | 547 | if (ea < -4095 || ea > 4095) { |
@@ -452,8 +561,8 @@ class Compiler { | ||
452 | 561 | } |
453 | 562 | } |
454 | 563 | |
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); | |
457 | 566 | if (ea < LOCAL) { |
458 | 567 | // Local, fp relative |
459 | 568 | if (ea < -4095 || ea > 4095) { |
@@ -500,12 +609,12 @@ class Compiler { | ||
500 | 609 | } |
501 | 610 | |
502 | 611 | virtual int beginFunctionCallArguments() { |
503 | - fprintf(stderr, "beginFunctionCallArguments();\n"); | |
612 | + LOG_API("beginFunctionCallArguments();\n"); | |
504 | 613 | return o4(0xE24DDF00); // Placeholder |
505 | 614 | } |
506 | 615 | |
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); | |
509 | 618 | if (l < 0 || l > 4096-4) { |
510 | 619 | error("l out of range for stack offset: 0x%08x", l); |
511 | 620 | } |
@@ -513,7 +622,7 @@ class Compiler { | ||
513 | 622 | } |
514 | 623 | |
515 | 624 | 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); | |
517 | 626 | if (l < 0 || l > 0x3FC) { |
518 | 627 | error("L out of range for stack adjustment: 0x%08x", l); |
519 | 628 | } |
@@ -526,13 +635,13 @@ class Compiler { | ||
526 | 635 | } |
527 | 636 | |
528 | 637 | virtual int callForward(int symbol) { |
529 | - fprintf(stderr, "callForward(%d);\n", symbol); | |
638 | + LOG_API("callForward(%d);\n", symbol); | |
530 | 639 | // Forward calls are always short (local) |
531 | 640 | return o4(0xEB000000 | encodeAddress(symbol)); |
532 | 641 | } |
533 | 642 | |
534 | 643 | virtual void callRelative(int t) { |
535 | - fprintf(stderr, "callRelative(%d);\n", t); | |
644 | + LOG_API("callRelative(%d);\n", t); | |
536 | 645 | int abs = t + getPC() + jumpOffset(); |
537 | 646 | fprintf(stderr, "abs=%d (0x%08x)\n", abs, abs); |
538 | 647 | if (t >= - (1 << 25) && t < (1 << 25)) { |
@@ -548,7 +657,7 @@ class Compiler { | ||
548 | 657 | } |
549 | 658 | |
550 | 659 | virtual void callIndirect(int l) { |
551 | - fprintf(stderr, "callIndirect(%d);\n", l); | |
660 | + LOG_API("callIndirect(%d);\n", l); | |
552 | 661 | int argCount = l >> 2; |
553 | 662 | int poppedArgs = argCount > 4 ? 4 : argCount; |
554 | 663 | int adjustedL = l - (poppedArgs << 2); |
@@ -560,7 +669,7 @@ class Compiler { | ||
560 | 669 | } |
561 | 670 | |
562 | 671 | 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); | |
564 | 673 | int argCount = l >> 2; |
565 | 674 | int stackArgs = argCount > 4 ? argCount - 4 : 0; |
566 | 675 | int stackUse = stackArgs + (isIndirect ? 1 : 0); |
@@ -578,11 +687,11 @@ class Compiler { | ||
578 | 687 | |
579 | 688 | /* output a symbol and patch all calls to it */ |
580 | 689 | virtual void gsym(int t) { |
581 | - fprintf(stderr, "gsym(0x%x)\n", t); | |
690 | + LOG_API("gsym(0x%x)\n", t); | |
582 | 691 | int n; |
583 | 692 | int base = getBase(); |
584 | 693 | int pc = getPC(); |
585 | - fprintf(stderr, "pc = 0x%x\n", pc); | |
694 | + LOG_API("pc = 0x%x\n", pc); | |
586 | 695 | while (t) { |
587 | 696 | int data = * (int*) t; |
588 | 697 | int decodedOffset = ((BRANCH_REL_ADDRESS_MASK & data) << 2); |
@@ -597,8 +706,20 @@ class Compiler { | ||
597 | 706 | } |
598 | 707 | } |
599 | 708 | |
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 | + | |
600 | 720 | virtual int disassemble(FILE* out) { |
601 | - disasmOut = out; | |
721 | +#ifdef ENABLE_ARM_DISASSEMBLY | |
722 | + disasmOut = out; | |
602 | 723 | disasm_interface_t di; |
603 | 724 | di.di_readword = disassemble_readword; |
604 | 725 | di.di_printaddr = disassemble_printaddr; |
@@ -610,6 +731,7 @@ class Compiler { | ||
610 | 731 | fprintf(out, "%08x: %08x ", i, *(int*) i); |
611 | 732 | ::disasm(&di, i, 0); |
612 | 733 | } |
734 | +#endif | |
613 | 735 | return 0; |
614 | 736 | } |
615 | 737 |
@@ -679,7 +801,7 @@ class Compiler { | ||
679 | 801 | } |
680 | 802 | }; |
681 | 803 | |
682 | -#endif // PROVIDE_X86_CODEGEN | |
804 | +#endif // PROVIDE_ARM_CODEGEN | |
683 | 805 | |
684 | 806 | #ifdef PROVIDE_X86_CODEGEN |
685 | 807 |
@@ -730,23 +852,23 @@ class Compiler { | ||
730 | 852 | o(0x92); /* xchg %edx, %eax */ |
731 | 853 | } |
732 | 854 | |
733 | - virtual void clearECX() { | |
855 | + virtual void clearR1() { | |
734 | 856 | oad(0xb9, 0); /* movl $0, %ecx */ |
735 | 857 | } |
736 | 858 | |
737 | - virtual void pushEAX() { | |
859 | + virtual void pushR0() { | |
738 | 860 | o(0x50); /* push %eax */ |
739 | 861 | } |
740 | 862 | |
741 | - virtual void popECX() { | |
863 | + virtual void popR1() { | |
742 | 864 | o(0x59); /* pop %ecx */ |
743 | 865 | } |
744 | 866 | |
745 | - virtual void storeEAXToAddressECX(bool isInt) { | |
867 | + virtual void storeR0ToR1(bool isInt) { | |
746 | 868 | o(0x0188 + isInt); /* movl %eax/%al, (%ecx) */ |
747 | 869 | } |
748 | 870 | |
749 | - virtual void loadEAXIndirect(bool isInt) { | |
871 | + virtual void loadR0FromR0(bool isInt) { | |
750 | 872 | if (isInt) |
751 | 873 | o(0x8b); /* mov (%eax), %eax */ |
752 | 874 | else |
@@ -754,15 +876,15 @@ class Compiler { | ||
754 | 876 | ob(0); /* add zero in code */ |
755 | 877 | } |
756 | 878 | |
757 | - virtual void leaEAX(int ea) { | |
879 | + virtual void leaR0(int ea) { | |
758 | 880 | gmov(10, ea); /* leal EA, %eax */ |
759 | 881 | } |
760 | 882 | |
761 | - virtual void storeEAX(int ea) { | |
883 | + virtual void storeR0(int ea) { | |
762 | 884 | gmov(6, ea); /* mov %eax, EA */ |
763 | 885 | } |
764 | 886 | |
765 | - virtual void loadEAX(int ea, bool isIncDec, int op) { | |
887 | + virtual void loadR0(int ea, bool isIncDec, int op) { | |
766 | 888 | gmov(8, ea); /* mov EA, %eax */ |
767 | 889 | if (isIncDec) { |
768 | 890 | /* Implement post-increment or post decrement. |
@@ -776,7 +898,7 @@ class Compiler { | ||
776 | 898 | return oad(0xec81, 0); /* sub $xxx, %esp */ |
777 | 899 | } |
778 | 900 | |
779 | - virtual void storeEAToArg(int l) { | |
901 | + virtual void storeR0ToArg(int l) { | |
780 | 902 | oad(0x248489, l); /* movl %eax, xxx(%esp) */ |
781 | 903 | } |
782 | 904 |
@@ -808,7 +930,7 @@ class Compiler { | ||
808 | 930 | } |
809 | 931 | |
810 | 932 | virtual int disassemble(FILE* out) { |
811 | - return 1; | |
933 | + return 0; | |
812 | 934 | } |
813 | 935 | |
814 | 936 | /* output a symbol and patch all calls to it */ |
@@ -822,6 +944,10 @@ class Compiler { | ||
822 | 944 | } |
823 | 945 | } |
824 | 946 | |
947 | + virtual int finishCompile() { | |
948 | + return 0; | |
949 | + } | |
950 | + | |
825 | 951 | private: |
826 | 952 | |
827 | 953 | /** Output 1 to 4 bytes. |
@@ -868,6 +994,39 @@ class Compiler { | ||
868 | 994 | |
869 | 995 | #endif // PROVIDE_X86_CODEGEN |
870 | 996 | |
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 | + | |
871 | 1030 | /* vars: value of variables |
872 | 1031 | loc : local variable index |
873 | 1032 | glo : global variable index |
@@ -882,7 +1041,8 @@ class Compiler { | ||
882 | 1041 | void* pSymbolBase; |
883 | 1042 | void* pGlobalBase; |
884 | 1043 | void* pVarsBase; |
885 | - FILE* file; | |
1044 | + | |
1045 | + InputStream* file; | |
886 | 1046 | |
887 | 1047 | CodeBuf codeBuf; |
888 | 1048 | CodeGenerator* pGen; |
@@ -957,7 +1117,7 @@ class Compiler { | ||
957 | 1117 | ch = dch; |
958 | 1118 | } |
959 | 1119 | } else |
960 | - ch = fgetc(file); | |
1120 | + ch = file->get(); | |
961 | 1121 | /* printf("ch=%c 0x%x\n", ch, ch); */ |
962 | 1122 | } |
963 | 1123 |
@@ -1108,7 +1268,7 @@ class Compiler { | ||
1108 | 1268 | va_list ap; |
1109 | 1269 | |
1110 | 1270 | va_start(ap, fmt); |
1111 | - fprintf(stderr, "%ld: ", ftell((FILE *) file)); | |
1271 | + fprintf(stderr, "%ld: ", file->tell()); | |
1112 | 1272 | vfprintf(stderr, fmt, ap); |
1113 | 1273 | fprintf(stderr, "\n"); |
1114 | 1274 | va_end(ap); |
@@ -1149,7 +1309,7 @@ class Compiler { | ||
1149 | 1309 | } else if (c == 2) { |
1150 | 1310 | /* -, +, !, ~ */ |
1151 | 1311 | unary(0); |
1152 | - pGen->clearECX(); | |
1312 | + pGen->clearR1(); | |
1153 | 1313 | if (t == '!') |
1154 | 1314 | pGen->gcmp(a); |
1155 | 1315 | else |
@@ -1175,15 +1335,15 @@ class Compiler { | ||
1175 | 1335 | unary(0); |
1176 | 1336 | if (tok == '=') { |
1177 | 1337 | next(); |
1178 | - pGen->pushEAX(); | |
1338 | + pGen->pushR0(); | |
1179 | 1339 | expr(); |
1180 | - pGen->popECX(); | |
1181 | - pGen->storeEAXToAddressECX(t == TOK_INT); | |
1340 | + pGen->popR1(); | |
1341 | + pGen->storeR0ToR1(t == TOK_INT); | |
1182 | 1342 | } else if (t) { |
1183 | - pGen->loadEAXIndirect(t == TOK_INT); | |
1343 | + pGen->loadR0FromR0(t == TOK_INT); | |
1184 | 1344 | } |
1185 | 1345 | } else if (t == '&') { |
1186 | - pGen->leaEAX(*(int *) tok); | |
1346 | + pGen->leaR0(*(int *) tok); | |
1187 | 1347 | next(); |
1188 | 1348 | } else { |
1189 | 1349 | n = *(int *) t; |
@@ -1195,10 +1355,10 @@ class Compiler { | ||
1195 | 1355 | /* assignment */ |
1196 | 1356 | next(); |
1197 | 1357 | expr(); |
1198 | - pGen->storeEAX(n); | |
1358 | + pGen->storeR0(n); | |
1199 | 1359 | } else if (tok != '(') { |
1200 | 1360 | /* variable */ |
1201 | - pGen->loadEAX(n, tokl == 11, tokc); | |
1361 | + pGen->loadR0(n, tokl == 11, tokc); | |
1202 | 1362 | if (tokl == 11) { |
1203 | 1363 | next(); |
1204 | 1364 | } |
@@ -1209,7 +1369,7 @@ class Compiler { | ||
1209 | 1369 | /* function call */ |
1210 | 1370 | if (tok == '(') { |
1211 | 1371 | if (n == 1) |
1212 | - pGen->pushEAX(); | |
1372 | + pGen->pushR0(); | |
1213 | 1373 | |
1214 | 1374 | /* push args and invert order */ |
1215 | 1375 | a = pGen->beginFunctionCallArguments(); |
@@ -1217,7 +1377,7 @@ class Compiler { | ||
1217 | 1377 | l = 0; |
1218 | 1378 | while (tok != ')') { |
1219 | 1379 | expr(); |
1220 | - pGen->storeEAToArg(l); | |
1380 | + pGen->storeR0ToArg(l); | |
1221 | 1381 | if (tok == ',') |
1222 | 1382 | next(); |
1223 | 1383 | l = l + 4; |
@@ -1255,9 +1415,9 @@ class Compiler { | ||
1255 | 1415 | a = pGen->gtst(t == OP_LOGICAL_OR, a); /* && and || output code generation */ |
1256 | 1416 | sum(l); |
1257 | 1417 | } else { |
1258 | - pGen->pushEAX(); | |
1418 | + pGen->pushR0(); | |
1259 | 1419 | sum(l); |
1260 | - pGen->popECX(); | |
1420 | + pGen->popR1(); | |
1261 | 1421 | |
1262 | 1422 | if ((l == 4) | (l == 5)) { |
1263 | 1423 | pGen->gcmp(t); |
@@ -1420,6 +1580,10 @@ class Compiler { | ||
1420 | 1580 | delete pGen; |
1421 | 1581 | pGen = 0; |
1422 | 1582 | } |
1583 | + if (file) { | |
1584 | + delete file; | |
1585 | + file = 0; | |
1586 | + } | |
1423 | 1587 | } |
1424 | 1588 | |
1425 | 1589 | void clear() { |
@@ -1470,7 +1634,7 @@ class Compiler { | ||
1470 | 1634 | #endif |
1471 | 1635 | } |
1472 | 1636 | if (pGen == NULL) { |
1473 | - fprintf(stderr, "No code generator defined."); | |
1637 | + fprintf(stderr, "No code generator defined.\n"); | |
1474 | 1638 | } |
1475 | 1639 | } |
1476 | 1640 |
@@ -1490,16 +1654,16 @@ public: | ||
1490 | 1654 | cleanup(); |
1491 | 1655 | } |
1492 | 1656 | |
1493 | - int compile(FILE* in, args& args) { | |
1657 | + int compile(const char* text, size_t textLength) { | |
1494 | 1658 | cleanup(); |
1495 | 1659 | clear(); |
1496 | 1660 | codeBuf.init(ALLOC_SIZE); |
1497 | - setArchitecture(args.architecture); | |
1661 | + setArchitecture(NULL); | |
1498 | 1662 | if (!pGen) { |
1499 | 1663 | return -1; |
1500 | 1664 | } |
1501 | 1665 | pGen->init(&codeBuf); |
1502 | - file = in; | |
1666 | + file = new TextInputStream(text, textLength); | |
1503 | 1667 | sym_stk = (intptr_t) calloc(1, ALLOC_SIZE); |
1504 | 1668 | dstk = (intptr_t) strcpy((char*) sym_stk, |
1505 | 1669 | " int if else while break return for define main ") |
@@ -1534,6 +1698,38 @@ public: | ||
1534 | 1698 | return pGen->disassemble(out); |
1535 | 1699 | } |
1536 | 1700 | |
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 | + | |
1537 | 1733 | }; |
1538 | 1734 | |
1539 | 1735 | const char* Compiler::operatorChars = |
@@ -1578,96 +1774,130 @@ const int Compiler::X86CodeGenerator::operatorHelper[] = { | ||
1578 | 1774 | }; |
1579 | 1775 | #endif |
1580 | 1776 | |
1581 | -} // namespace acc | |
1777 | +struct ACCscript { | |
1778 | + ACCscript() { | |
1779 | + text = 0; | |
1780 | + textLength = 0; | |
1781 | + accError = ACC_NO_ERROR; | |
1782 | + } | |
1582 | 1783 | |
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 | + } | |
1587 | 1787 | |
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; | |
1627 | 1791 | } |
1628 | 1792 | } |
1629 | 1793 | |
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; | |
1637 | 1798 | } |
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; | |
1642 | 1838 | } |
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; | |
1646 | 1855 | } |
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); | |
1650 | 1864 | } |
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; | |
1653 | 1875 | } |
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; | |
1670 | 1888 | } |
1889 | +} | |
1671 | 1890 | |
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 | + } | |
1673 | 1900 | } |
1901 | + | |
1902 | +} // namespace acc | |
1903 | + |
@@ -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 |
@@ -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 |
@@ -1,2 +1,2 @@ | ||
1 | -acc | |
1 | +test-acc | |
2 | 2 | *.out |
@@ -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 | + |
@@ -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 | +} |
@@ -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 |
@@ -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 |
@@ -17,7 +17,6 @@ LOCAL_PATH := $(my-dir) | ||
17 | 17 | include $(CLEAR_VARS) |
18 | 18 | |
19 | 19 | commonSources := \ |
20 | - abort_socket.c \ | |
21 | 20 | array.c \ |
22 | 21 | hashmap.c \ |
23 | 22 | atomic.c \ |
@@ -45,22 +44,23 @@ commonHostSources := \ | ||
45 | 44 | # some files must not be compiled when building against Mingw |
46 | 45 | # they correspond to features not used by our host development tools |
47 | 46 | # which are also hard or even impossible to port to native Win32 |
48 | -WITH_MINGW := | |
47 | +WINDOWS_HOST_ONLY := | |
49 | 48 | ifeq ($(HOST_OS),windows) |
50 | 49 | ifeq ($(strip $(USE_CYGWIN)),) |
51 | - WITH_MINGW := 1 | |
50 | + WINDOWS_HOST_ONLY := 1 | |
52 | 51 | endif |
53 | 52 | endif |
54 | 53 | # USE_MINGW is defined when we build against Mingw on Linux |
55 | 54 | ifneq ($(strip $(USE_MINGW)),) |
56 | - WITH_MINGW := 1 | |
55 | + WINDOWS_HOST_ONLY := 1 | |
57 | 56 | endif |
58 | 57 | |
59 | -ifeq ($(WITH_MINGW),1) | |
58 | +ifeq ($(WINDOWS_HOST_ONLY),1) | |
60 | 59 | commonSources += \ |
61 | 60 | uio.c |
62 | 61 | else |
63 | 62 | commonSources += \ |
63 | + abort_socket.c \ | |
64 | 64 | mspace.c \ |
65 | 65 | selector.c \ |
66 | 66 | tztime.c \ |
@@ -239,7 +239,7 @@ int asocket_write(struct asocket *s, const void *buf, size_t count, | ||
239 | 239 | } |
240 | 240 | |
241 | 241 | if (pfd[0].revents) { |
242 | - if (pfd[0].revents & POLLIN) { | |
242 | + if (pfd[0].revents & POLLOUT) { | |
243 | 243 | /* ready to write() without blocking */ |
244 | 244 | do { |
245 | 245 | ret = write(s->fd, buf, count); |
@@ -33,54 +33,19 @@ | ||
33 | 33 | |
34 | 34 | CommandListener::CommandListener() : |
35 | 35 | FrameworkListener("nexus") { |
36 | - registerCmd(new WifiEnableCmd()); | |
37 | - registerCmd(new WifiDisableCmd()); | |
38 | - registerCmd(new WifiScanCmd()); | |
39 | 36 | registerCmd(new WifiScanResultsCmd()); |
40 | 37 | registerCmd(new WifiListNetworksCmd()); |
41 | 38 | registerCmd(new WifiAddNetworkCmd()); |
42 | 39 | registerCmd(new WifiRemoveNetworkCmd()); |
43 | - registerCmd(new WifiSetVarCmd()); | |
44 | - registerCmd(new WifiGetVarCmd()); | |
45 | 40 | |
46 | - registerCmd(new VpnEnableCmd()); | |
47 | - registerCmd(new VpnSetVarCmd()); | |
48 | - registerCmd(new VpnGetVarCmd()); | |
49 | - registerCmd(new VpnDisableCmd()); | |
41 | + registerCmd(new GetCmd()); | |
42 | + registerCmd(new SetCmd()); | |
50 | 43 | } |
51 | 44 | |
52 | 45 | /* ------------- |
53 | 46 | * Wifi Commands |
54 | 47 | * ------------ */ |
55 | 48 | |
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 | - | |
84 | 49 | CommandListener::WifiAddNetworkCmd::WifiAddNetworkCmd() : |
85 | 50 | NexusCommand("wifi_add_network") { |
86 | 51 | } |
@@ -116,21 +81,6 @@ int CommandListener::WifiRemoveNetworkCmd::runCommand(SocketClient *cli, char *d | ||
116 | 81 | return 0; |
117 | 82 | } |
118 | 83 | |
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 | - | |
134 | 84 | CommandListener::WifiScanResultsCmd::WifiScanResultsCmd() : |
135 | 85 | NexusCommand("wifi_scan_results") { |
136 | 86 | } |
@@ -181,68 +131,39 @@ int CommandListener::WifiListNetworksCmd::runCommand(SocketClient *cli, char *da | ||
181 | 131 | return 0; |
182 | 132 | } |
183 | 133 | |
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 | + * ------------ */ | |
221 | 137 | |
222 | -CommandListener::WifiGetVarCmd::WifiGetVarCmd() : | |
223 | - NexusCommand("wifi_getvar") { | |
138 | +/* ---------------- | |
139 | + * Generic Commands | |
140 | + * ---------------- */ | |
141 | +CommandListener::GetCmd::GetCmd() : | |
142 | + NexusCommand("get") { | |
224 | 143 | } |
225 | 144 | |
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) { | |
229 | 146 | char *bword; |
230 | 147 | char *last; |
231 | - char varname[32]; | |
232 | - int networkId; | |
148 | + char propname[32]; | |
233 | 149 | |
234 | 150 | if (!(bword = strtok_r(data, ":", &last))) |
235 | 151 | goto out_inval; |
236 | 152 | |
237 | - networkId = atoi(bword); | |
153 | + strncpy(propname, bword, sizeof(propname)); | |
238 | 154 | |
239 | - if (!(bword = strtok_r(NULL, ":", &last))) | |
240 | - goto out_inval; | |
155 | + char pb[255]; | |
156 | + snprintf(pb, sizeof(pb), "%s:", propname); | |
241 | 157 | |
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 | + } | |
243 | 163 | |
244 | - LOGD("networkId = %d, varname '%s'", networkId, varname); | |
164 | + cli->sendMsg(ErrorCode::VariableRead, pb, false); | |
245 | 165 | |
166 | + cli->sendMsg(ErrorCode::CommandOkay, "Property read.", false); | |
246 | 167 | return 0; |
247 | 168 | out_inval: |
248 | 169 | errno = EINVAL; |
@@ -250,106 +171,34 @@ out_inval: | ||
250 | 171 | return 0; |
251 | 172 | } |
252 | 173 | |
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") { | |
268 | 176 | } |
269 | 177 | |
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) { | |
277 | 179 | char *bword; |
278 | 180 | char *last; |
279 | - char varname[32]; | |
280 | - char val[250]; | |
181 | + char propname[32]; | |
182 | + char propval[250]; | |
281 | 183 | |
282 | 184 | if (!(bword = strtok_r(data, ":", &last))) |
283 | 185 | goto out_inval; |
284 | 186 | |
285 | - strncpy(varname, bword, sizeof(varname)); | |
187 | + strncpy(propname, bword, sizeof(propname)); | |
286 | 188 | |
287 | 189 | if (!(bword = strtok_r(NULL, ":", &last))) |
288 | 190 | goto out_inval; |
289 | 191 | |
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)); | |
312 | 193 | |
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)) | |
321 | 195 | goto out_inval; |
322 | - | |
323 | - strncpy(varname, bword, sizeof(varname)); | |
324 | 196 | |
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); | |
336 | 198 | return 0; |
199 | + | |
337 | 200 | out_inval: |
338 | 201 | 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); | |
354 | 203 | return 0; |
355 | 204 | } |
@@ -25,19 +25,6 @@ public: | ||
25 | 25 | virtual ~CommandListener() {} |
26 | 26 | |
27 | 27 | 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 | - }; | |
41 | 28 | |
42 | 29 | class WifiScanCmd : public NexusCommand { |
43 | 30 | public: |
@@ -74,48 +61,19 @@ private: | ||
74 | 61 | int runCommand(SocketClient *c, char *data); |
75 | 62 | }; |
76 | 63 | |
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 { | |
106 | 65 | public: |
107 | - VpnGetVarCmd(); | |
108 | - virtual ~VpnGetVarCmd() {} | |
66 | + SetCmd(); | |
67 | + virtual ~SetCmd() {} | |
109 | 68 | int runCommand(SocketClient *c, char *data); |
110 | 69 | }; |
111 | 70 | |
112 | - class VpnDisableCmd : public NexusCommand { | |
71 | + class GetCmd : public NexusCommand { | |
113 | 72 | public: |
114 | - VpnDisableCmd(); | |
115 | - virtual ~VpnDisableCmd() {} | |
73 | + GetCmd(); | |
74 | + virtual ~GetCmd() {} | |
116 | 75 | int runCommand(SocketClient *c, char *data); |
117 | 76 | }; |
118 | - | |
119 | 77 | }; |
120 | 78 | |
121 | 79 | #endif |
@@ -14,6 +14,7 @@ | ||
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | 16 | #include <stdio.h> |
17 | +#include <stdlib.h> | |
17 | 18 | #include <string.h> |
18 | 19 | #include <fcntl.h> |
19 | 20 | #include <unistd.h> |
@@ -32,8 +33,13 @@ | ||
32 | 33 | extern "C" int init_module(void *, unsigned int, const char *); |
33 | 34 | extern "C" int delete_module(const char *, unsigned int); |
34 | 35 | |
35 | -Controller::Controller(const char *name) { | |
36 | +Controller::Controller(const char *name, const char *prefix) { | |
36 | 37 | mName = name; |
38 | + mPropertyPrefix = prefix; | |
39 | + mProperties = new PropertyCollection(); | |
40 | + | |
41 | + mEnabled = false; | |
42 | + registerProperty("enable"); | |
37 | 43 | } |
38 | 44 | |
39 | 45 | int Controller::start() { |
@@ -44,12 +50,69 @@ int Controller::stop() { | ||
44 | 50 | return 0; |
45 | 51 | } |
46 | 52 | |
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 | + | |
47 | 112 | int Controller::loadKernelModule(char *modpath, const char *args) { |
48 | 113 | void *module; |
49 | 114 | unsigned int size; |
50 | 115 | |
51 | - LOGD("loadKernelModule(%s, %s)", modpath, args); | |
52 | - | |
53 | 116 | module = loadFile(modpath, &size); |
54 | 117 | if (!module) { |
55 | 118 | errno = -EIO; |
@@ -65,7 +128,6 @@ int Controller::unloadKernelModule(const char *modtag) { | ||
65 | 128 | int rc = -1; |
66 | 129 | int retries = 10; |
67 | 130 | |
68 | - LOGD("unloadKernelModule(%s)", modtag); | |
69 | 131 | while (retries--) { |
70 | 132 | rc = delete_module(modtag, O_NONBLOCK | O_EXCL); |
71 | 133 | if (rc < 0 && errno == EAGAIN) |
@@ -107,7 +169,6 @@ bool Controller::isKernelModuleLoaded(const char *modtag) { | ||
107 | 169 | return false; |
108 | 170 | } |
109 | 171 | |
110 | - | |
111 | 172 | void *Controller::loadFile(char *filename, unsigned int *_size) |
112 | 173 | { |
113 | 174 | int ret, fd; |
@@ -16,31 +16,48 @@ | ||
16 | 16 | #ifndef _CONTROLLER_H |
17 | 17 | #define _CONTROLLER_H |
18 | 18 | |
19 | +#include <unistd.h> | |
20 | +#include <sys/types.h> | |
21 | + | |
19 | 22 | #include "../../../frameworks/base/include/utils/List.h" |
20 | 23 | |
24 | +#include "PropertyCollection.h" | |
25 | + | |
21 | 26 | class Controller { |
22 | 27 | private: |
23 | 28 | const char *mName; |
29 | + const char *mPropertyPrefix; | |
30 | + PropertyCollection *mProperties; | |
31 | + bool mEnabled; | |
24 | 32 | |
25 | 33 | public: |
26 | - Controller(const char *name); | |
34 | + Controller(const char *name, const char *prefix); | |
27 | 35 | virtual ~Controller() {} |
28 | 36 | |
29 | 37 | virtual int start(); |
30 | 38 | virtual int stop(); |
31 | 39 | |
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); | |
34 | 43 | |
35 | - virtual const char *getName() { return mName; } | |
44 | + const char *getName() { return mName; } | |
45 | + const char *getPropertyPrefix() { return mPropertyPrefix; } | |
36 | 46 | |
37 | 47 | protected: |
38 | 48 | int loadKernelModule(char *modpath, const char *args); |
39 | 49 | bool isKernelModuleLoaded(const char *modtag); |
40 | 50 | int unloadKernelModule(const char *modtag); |
41 | 51 | |
52 | + int registerProperty(const char *name); | |
53 | + int unregisterProperty(const char *name); | |
54 | + | |
42 | 55 | private: |
43 | 56 | void *loadFile(char *filename, unsigned int *_size); |
57 | + | |
58 | + virtual int enable() = 0; | |
59 | + virtual int disable() = 0; | |
60 | + | |
44 | 61 | }; |
45 | 62 | |
46 | 63 | typedef android::List<Controller *> ControllerCollection; |
@@ -18,7 +18,7 @@ | ||
18 | 18 | #include "LoopController.h" |
19 | 19 | |
20 | 20 | LoopController::LoopController() : |
21 | - Controller("LOOP") { | |
21 | + Controller("LOOP", "loop") { | |
22 | 22 | } |
23 | 23 | |
24 | 24 | int LoopController::enable() { |
@@ -23,6 +23,7 @@ public: | ||
23 | 23 | LoopController(); |
24 | 24 | virtual ~LoopController() {} |
25 | 25 | |
26 | +private: | |
26 | 27 | int enable(); |
27 | 28 | int disable(); |
28 | 29 | }; |
@@ -83,6 +83,73 @@ Controller *NetworkManager::findController(const char *name) { | ||
83 | 83 | return NULL; |
84 | 84 | } |
85 | 85 | |
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 | + | |
86 | 153 | int NetworkManager::onInterfaceCreated(Controller *c, char *name) { |
87 | 154 | LOGD("Interface %s created by controller %s", name, c->getName()); |
88 | 155 | return 0; |
@@ -19,6 +19,7 @@ | ||
19 | 19 | #include <sysutils/SocketListener.h> |
20 | 20 | |
21 | 21 | #include "Controller.h" |
22 | +#include "PropertyCollection.h" | |
22 | 23 | |
23 | 24 | class NetworkManager { |
24 | 25 | private: |
@@ -27,6 +28,7 @@ private: | ||
27 | 28 | private: |
28 | 29 | ControllerCollection *mControllers; |
29 | 30 | SocketListener *mBroadcaster; |
31 | + PropertyCollection *mProperties; | |
30 | 32 | |
31 | 33 | public: |
32 | 34 | virtual ~NetworkManager() {} |
@@ -37,6 +39,10 @@ public: | ||
37 | 39 | |
38 | 40 | Controller *findController(const char *name); |
39 | 41 | |
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 | + | |
40 | 46 | void setBroadcaster(SocketListener *sl) { mBroadcaster = sl; } |
41 | 47 | SocketListener *getBroadcaster() { return mBroadcaster; } |
42 | 48 |
@@ -45,6 +51,9 @@ public: | ||
45 | 51 | private: |
46 | 52 | int startControllers(); |
47 | 53 | int stopControllers(); |
54 | + int registerProperty(const char *name); | |
55 | + int unregisterProperty(const char *name); | |
56 | + | |
48 | 57 | NetworkManager(); |
49 | 58 | |
50 | 59 | public: |
@@ -63,7 +63,6 @@ int OpenVpnController::enable() { | ||
63 | 63 | } |
64 | 64 | |
65 | 65 | int OpenVpnController::disable() { |
66 | - | |
67 | 66 | if (mServiceManager->stop("openvpn")) |
68 | 67 | return -1; |
69 | 68 | return 0; |
@@ -31,6 +31,8 @@ public: | ||
31 | 31 | |
32 | 32 | int start(); |
33 | 33 | int stop(); |
34 | + | |
35 | +private: | |
34 | 36 | int enable(); |
35 | 37 | int disable(); |
36 | 38 | }; |
@@ -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 | + |
@@ -14,6 +14,7 @@ | ||
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | 16 | |
17 | +#include <stdio.h> | |
17 | 18 | #include <string.h> |
18 | 19 | #include <errno.h> |
19 | 20 | #include <sys/socket.h> |
@@ -23,7 +24,8 @@ | ||
23 | 24 | #include "VpnController.h" |
24 | 25 | |
25 | 26 | VpnController::VpnController() : |
26 | - Controller("VPN") { | |
27 | + Controller("VPN", "vpn") { | |
28 | + registerProperty("gateway"); | |
27 | 29 | } |
28 | 30 | |
29 | 31 | int VpnController::start() { |
@@ -46,15 +48,23 @@ int VpnController::disable() { | ||
46 | 48 | return -1; |
47 | 49 | } |
48 | 50 | |
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); | |
55 | 61 | } |
56 | 62 | |
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); | |
60 | 70 | } |
@@ -33,14 +33,14 @@ public: | ||
33 | 33 | virtual int start(); |
34 | 34 | virtual int stop(); |
35 | 35 | |
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: | |
36 | 41 | virtual int enable(); |
37 | 42 | virtual int disable(); |
38 | 43 | |
39 | - struct in_addr &getVpnGateway() { return mVpnGateway; } | |
40 | - int setVpnGateway(const char *vpnGw); | |
41 | - int setVpnGateway(struct in_addr *vpnGw); | |
42 | - | |
43 | -protected: | |
44 | 44 | }; |
45 | 45 | |
46 | 46 | #endif |
@@ -13,6 +13,8 @@ | ||
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | + | |
17 | +#include <stdlib.h> | |
16 | 18 | #include <string.h> |
17 | 19 | #include <errno.h> |
18 | 20 |
@@ -26,7 +28,7 @@ | ||
26 | 28 | #include "ErrorCode.h" |
27 | 29 | |
28 | 30 | WifiController::WifiController(char *modpath, char *modname, char *modargs) : |
29 | - Controller("WIFI") { | |
31 | + Controller("WIFI", "wifi") { | |
30 | 32 | strncpy(mModulePath, modpath, sizeof(mModulePath)); |
31 | 33 | strncpy(mModuleName, modname, sizeof(mModuleName)); |
32 | 34 | strncpy(mModuleArgs, modargs, sizeof(mModuleArgs)); |
@@ -34,6 +36,8 @@ WifiController::WifiController(char *modpath, char *modname, char *modargs) : | ||
34 | 36 | mSupplicant = new Supplicant(); |
35 | 37 | mScanner = new WifiScanner(mSupplicant, 10); |
36 | 38 | mCurrentScanMode = 0; |
39 | + | |
40 | + registerProperty("scanmode"); | |
37 | 41 | } |
38 | 42 | |
39 | 43 | int WifiController::start() { |
@@ -94,7 +98,7 @@ out_powerdown: | ||
94 | 98 | return -1; |
95 | 99 | } |
96 | 100 | |
97 | -void WifiController::sendStatusBroadcast(char *msg) { | |
101 | +void WifiController::sendStatusBroadcast(const char *msg) { | |
98 | 102 | NetworkManager::Instance()-> |
99 | 103 | getBroadcaster()-> |
100 | 104 | sendBroadcast(ErrorCode::UnsolicitedInformational, msg, false); |
@@ -167,3 +171,20 @@ ScanResultCollection *WifiController::createScanResults() { | ||
167 | 171 | WifiNetworkCollection *WifiController::createNetworkList() { |
168 | 172 | return mSupplicant->createNetworkList(); |
169 | 173 | } |
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 | + |
@@ -54,15 +54,14 @@ public: | ||
54 | 54 | int start(); |
55 | 55 | int stop(); |
56 | 56 | |
57 | - int enable(); | |
58 | - int disable(); | |
59 | - | |
60 | 57 | int addNetwork(); |
61 | 58 | int removeNetwork(int networkId); |
62 | 59 | WifiNetworkCollection *createNetworkList(); |
63 | 60 | |
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 | + | |
66 | 65 | ScanResultCollection *createScanResults(); |
67 | 66 | |
68 | 67 | char *getModulePath() { return mModulePath; } |
@@ -79,7 +78,13 @@ protected: | ||
79 | 78 | virtual bool isFirmwareLoaded() = 0; |
80 | 79 | virtual bool isPoweredUp() = 0; |
81 | 80 | |
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 | + | |
83 | 88 | }; |
84 | 89 | |
85 | 90 | #endif |
@@ -65,7 +65,7 @@ void WifiScanner::run() { | ||
65 | 65 | struct timeval to; |
66 | 66 | int rc = 0; |
67 | 67 | |
68 | - to.tv_sec = 0; | |
68 | + to.tv_usec = 0; | |
69 | 69 | to.tv_sec = mPeriod; |
70 | 70 | |
71 | 71 | FD_ZERO(&read_fds); |
@@ -83,4 +83,5 @@ void WifiScanner::run() { | ||
83 | 83 | } else if (FD_ISSET(mCtrlPipe[0], &read_fds)) |
84 | 84 | break; |
85 | 85 | } // while |
86 | + LOGD("Stopping wifi scanner"); | |
86 | 87 | } |
@@ -34,6 +34,10 @@ case "$boot_anim" in | ||
34 | 34 | ;; |
35 | 35 | esac |
36 | 36 | |
37 | +# call 'qemu-props' to set system properties from the emulator. | |
38 | +# | |
39 | +/system/bin/qemu-props | |
40 | + | |
37 | 41 | # this line doesn't really do anything useful. however without it the |
38 | 42 | # previous setprop doesn't seem to apply for some really odd reason |
39 | 43 | setprop ro.qemu.init.completed 1 |